做者: 阿布html
阿布量化版權全部 未經容許 禁止轉載python
abu量化系統github地址(歡迎+star,你的支持是我更新的動力!)git
本節ipython notebookgithub
在第一節即說過:api
以前的節講的都是擇時(何時投資), 本節將講解選股。緩存
與擇時小節相似,實現示例在中abu量化系統實現一個選股策略。微信
以下代碼AbuPickRegressAngMinMax爲選股因子,它的做用是將股票前期走勢進行線性擬合計算一個角度,參數爲選股條件,將選股條件做用於角度後進行股票的篩選。機器學習
from abupy import AbuPickStockBase, ps, ABuRegUtil class AbuPickRegressAngMinMax(AbuPickStockBase): """擬合角度選股因子示例類""" def _init_self(self, **kwargs): """經過kwargs設置擬合角度邊際條件,配置因子參數""" # 暫時與base保持一致不使用kwargs.pop('a', default)方式 # fit_pick中 ang > threshold_ang_min, 默認負無窮,即默認全部都符合 self.threshold_ang_min = -np.inf if 'threshold_ang_min' in kwargs: # 設置最小角度閥值 self.threshold_ang_min = kwargs['threshold_ang_min'] # fit_pick中 ang < threshold_ang_max, 默認正無窮,即默認全部都符合 self.threshold_ang_max = np.inf if 'threshold_ang_max' in kwargs: # 設置最大角度閥值 self.threshold_ang_max = kwargs['threshold_ang_max'] @ps.reversed_result def fit_pick(self, kl_pd, target_symbol): """開始根據自定義擬合角度邊際參數進行選股""" # 計算走勢角度 ang = ABuRegUtil.calc_regress_deg(kl_pd.close, show=False) # 根據參數進行角度條件判斷 if self.threshold_ang_min < ang < self.threshold_ang_max: return True return False def fit_first_choice(self, pick_worker, choice_symbols, *args, **kwargs): raise NotImplementedError('AbuPickRegressAng fit_first_choice unsupported now!')
上面編寫的AbuPickRegressAngMinMax即爲一個完整的選股策略:函數
選股模塊主要功能依託AbuPickStockWorker,其相似擇時模塊中的AbuPickTimeWorker,其經過init_stock_pickers()函數將全部選股因子實例化,而後在以後的fit()操做中,遍歷全部選股因子,使用選股因子的fit_pick()函數,保留全部選股因子的fit_pick()都返回True的股票,只要有一個選股因子的fit_pick結果是False就將股票剔除。oop
詳細代碼請查閱 AbuPickStockWorker源代碼。
本節只講簡單講解選股使用示例,好比只想選取符合上升走勢的股票:
from abupy import AbuPickStockWorker from abupy import AbuBenchmark, AbuCapital, AbuKLManager # 選股條件threshold_ang_min=0.0, 即要求股票走勢爲向上上升趨勢 stock_pickers = [{'class': AbuPickRegressAngMinMax, 'threshold_ang_min': 0.0, 'reversed': False}] # 從這幾個股票裏進行選股,只是爲了演示方便 # 通常的選股都會是數量比較多的狀況好比全市場股票 choice_symbols = ['usNOAH', 'usSFUN', 'usBIDU', 'usAAPL', 'usGOOG', 'usTSLA', 'usWUBA', 'usVIPS'] benchmark = AbuBenchmark() capital = AbuCapital(1000000, benchmark) kl_pd_manger = AbuKLManager(benchmark, capital) stock_pick = AbuPickStockWorker(capital, benchmark, kl_pd_manger, choice_symbols=choice_symbols, stock_pickers=stock_pickers) stock_pick.fit() # 打印最後的選股結果 stock_pick.choice_symbols
['usSFUN', 'usBIDU', 'usTSLA', 'usWUBA', 'usVIPS']
上面的實現方式和第一節中講解擇時回測的使用時同樣經過分解流程方式一步一步實現使用AbuPickStockWorker進行選股,目的是爲了更清晰的說明內部操做流程,編碼過程會顯的有些複雜臃腫。
實際上在編寫完成一個策略後只須要abu.run_loop_back()函數便可以完成回測,在後面的小節中會進行講解。
上面選股的結果將noah剔除,由於它在回測以前的選股週期內趨勢爲降低趨勢,以下圖所示:
# 從kl_pd_manger緩存中獲取選股走勢數據, # 注意get_pick_stock_kl_pd()爲選股數據,get_pick_time_kl_pd()爲擇時 kl_pd_noah = kl_pd_manger.get_pick_stock_kl_pd('usNOAH') # 繪製並計算角度 deg = ABuRegUtil.calc_regress_deg(kl_pd_noah.close) print('noah 選股週期內角度={}'.format(round(deg, 3)))
noah 選股週期內角度=-9.289
注意上面的選股數據要使用擇時回測數據以前的一段時間數據,在AbuPickStockBase中定義了xd,min_xd選股週期獲取參數,
在AbuKLManager中經過get_pick_stock_kl_pd()函數配合xd,min_xd參數獲取選股週期數據
更多詳情請閱讀AbuPickStockBase源代碼與AbuKLManager源代碼
上述選股代碼實如今ABuPickStockExecute.do_pick_stock_work()中進行了封裝,即講AbuPickStockWorker及一些零散操做進行封裝。
更多詳情請閱讀ABuPickStockExecute,使用示例以下所示:
eg:繼續使用AbuPickRegressAngMinMax作爲選股因子,以下定義threshold_ang_min=0.0, threshold_ang_max=10.0,即只選取上升趨勢且上升角度小於10度的股票,下面示例使用ABuPickStockExecute.do_pick_stock_work()函數
from abupy import ABuPickStockExecute stock_pickers = [{'class': AbuPickRegressAngMinMax, 'threshold_ang_min': 0.0, 'threshold_ang_max': 10.0, 'reversed': False}] ABuPickStockExecute.do_pick_stock_work(choice_symbols, benchmark, capital, stock_pickers)
['usSFUN', 'usBIDU']
能夠看到結果sfun和baidu都符合,下面代碼驗證一下:
kl_pd_sfun = kl_pd_manger.get_pick_stock_kl_pd('usSFUN') print('sfun 選股週期內角度={:.3f}'.format(ABuRegUtil.calc_regress_deg(kl_pd_sfun.close)))
sfun 選股週期內角度=8.230
kl_pd_baidu = kl_pd_manger.get_pick_stock_kl_pd('usBIDU') print('bidu 選股週期內角度={:.3f}'.format(ABuRegUtil.calc_regress_deg(kl_pd_baidu.close)))
bidu 選股週期內角度=9.644
上面結果顯示兩支股票在選股週期中的價格趨勢擬合角度都在0-10之間。
假設修改需求想要選取週期內趨勢角度在0度-10度以外的全部股票,能夠這樣編寫代碼:
# 和上面的代碼惟一的區別就是reversed=True stock_pickers = [{'class': AbuPickRegressAngMinMax, 'threshold_ang_min': 0.0, 'threshold_ang_max': 10.0, 'reversed': True}] ABuPickStockExecute.do_pick_stock_work(choice_symbols, benchmark, capital, stock_pickers)
['usNOAH', 'usTSLA', 'usWUBA', 'usVIPS']
能夠看到結果與以前相反除了baidu和sfun以外全部股票都被選上,因爲在AbuPickStockBase中定義函數reversed_result(),它的做用就是定義結果是否反轉。
具體實現請閱讀AbuPickStockBase中reversed_result裝飾器的實現。
使用實際很簡單,在每一個具體的選股因子上的fit_pick()函數上根據須要選擇是否安上裝飾器,以下編寫價格選股因子所示:
class AbuPickStockPriceMinMax(AbuPickStockBase): """價格選股因子示例類""" def _init_self(self, **kwargs): """經過kwargs設置選股價格邊際條件,配置因子參數""" # 暫時與base保持一致不使用kwargs.pop('a', default)方式 # fit_pick中選擇 > 最小(threshold_price_min), 默認負無窮,即默認全部都符合 self.threshold_price_min = -np.inf if 'threshold_price_min' in kwargs: # 最小价格閥值 self.threshold_price_min = kwargs['threshold_price_min'] # fit_pick中選擇 < 最大(threshold_price_max), 默認正無窮,即默認全部都符合 self.threshold_price_max = np.inf if 'threshold_price_max' in kwargs: # 最大價格閥值 self.threshold_price_max = kwargs['threshold_price_max'] @ps.reversed_result def fit_pick(self, kl_pd, target_symbol): """開始根據自定義價格邊際參數進行選股""" if kl_pd.close.max() < self.threshold_price_max and kl_pd.close.min() > self.threshold_price_min: # kl_pd.close的最大價格 < 最大價格閥值 且 kl_pd.close的最小价格 > 最小价格閥值 return True return False def fit_first_choice(self, pick_worker, choice_symbols, *args, **kwargs): raise NotImplementedError('AbuPickStockPriceMinMax fit_first_choice unsupported now!')
備註:本節所編寫的選股示例代碼之內置在abupy項目代碼中可經過以下方式直接導入:
from abupy import AbuPickStockPriceMinMax from abupy import AbuPickRegressAngMinMax
繼續使用ABuPickStockExecute,使上面兩個選股因子同時生效,結果符合的只有BIDU及TSLA,代碼以下所示:
from abupy import AbuPickStockPriceMinMax # 選股list使用兩個不一樣的選股因子組合,並行同時生效 stock_pickers = [{'class': AbuPickRegressAngMinMax, 'threshold_ang_min': 0.0, 'reversed': False}, {'class': AbuPickStockPriceMinMax, 'threshold_price_min': 50.0, 'reversed': False}] %time ABuPickStockExecute.do_pick_stock_work(choice_symbols, benchmark, capital, stock_pickers)
['usBIDU', 'usTSLA']
與並行擇時實現方式相似,選股使用AbuPickStockMaster並行執行多個進程來提高選股效率。
具體代碼請查詢AbuPickStockMaster,下面爲使用示例, 使用do_pick_stock_with_process()函數執行默認n_process_pick_stock=8,即默認同時運行8個進程。
# 選股list使用兩個不一樣的選股因子組合,並行同時生效 stock_pickers = [{'class': AbuPickRegressAngMinMax, 'threshold_ang_min': 0.0, 'reversed': False}, {'class': AbuPickStockPriceMinMax, 'threshold_price_min': 50.0, 'reversed': False}] cs = AbuPickStockMaster.do_pick_stock_with_process(capital, benchmark, stock_pickers, choice_symbols)
pid:6614 pick stocks complete:100.0% pid:6615 pick stocks complete:100.0% pid:6616 pick stocks complete:100.0% pid:6617 pick stocks complete:100.0% pid:6618 pick stocks complete:100.0% pid:6619 pick stocks complete:100.0% pid:6620 pick stocks complete:100.0% pid:6621 pick stocks complete:100.0% pid:6617 done! pid:6618 done! pid:6615 done! pid:6614 done! pid:6616 done! pid:6620 done! pid:6619 done! pid:6621 done!
從上面輸出能夠看到選股階段啓動了8個進程,由於股票數量太少,進程啓動銷燬也須要必定時間,因此上例總體效率並無提升。
更多示例請閱讀《量化交易之路》書中的示例以及對應的ipython代碼或者python代碼
abu量化系統文檔教程持續更新中,請關注公衆號中的更新提醒。
更多關於量化交易相關請閱讀《量化交易之路》
更多關於量化交易與機器學習相關請閱讀《機器學習之路》
更多關於abu量化系統請關注微信公衆號: abu_quant