關(guān)于機(jī)器學(xué)習(xí)與比特幣的示例
我曾經(jīng)編寫過豬老三的世界中使用機(jī)器學(xué)習(xí)對(duì)股價(jià)和漲跌進(jìn)行預(yù)測(cè)的幻想示例:
在豬老三的世界中實(shí)現(xiàn)了:機(jī)器學(xué)習(xí).fit(x, y) = (股價(jià)預(yù)測(cè),漲跌預(yù)測(cè)) =發(fā)財(cái)
在豬老三的童話中我設(shè)定的可以影響股價(jià)走勢(shì)的參數(shù)是有限個(gè)的,特別是影響漲跌的因素很容易構(gòu)造特征。在真實(shí)的市場(chǎng)中可以影響股價(jià)走勢(shì)的因素是***多的,而且這些因素之間的也可以是相關(guān)的。就像你求解一個(gè)方程組,這個(gè)方程組不是有一個(gè)兩個(gè)解,它是有***個(gè)解的系統(tǒng),并且每個(gè)解都與其他任意個(gè)解相關(guān),但又并非簡(jiǎn)單線性相關(guān)。市場(chǎng)是一個(gè)二級(jí)混沌系統(tǒng),認(rèn)為任何想通過技術(shù)對(duì)股價(jià)進(jìn)行預(yù)測(cè)或者漲跌預(yù)測(cè)都是不可能的,不倫你自己認(rèn)為你使用的技術(shù)本身有多高深,無異于管中窺豹。
本系列教程中講到的ump裁判系統(tǒng)是abupy中通過機(jī)器學(xué)習(xí)技術(shù)對(duì)回測(cè)結(jié)果進(jìn)行學(xué)習(xí),反向指導(dǎo)決策新的交易是否攔截的實(shí)際應(yīng)用,本節(jié)講解機(jī)器學(xué)習(xí)在量化領(lǐng)域很有作用的另一個(gè)方向:閥值的估計(jì),因?yàn)闊o論是編寫選股策略,擇時(shí)策略還是任何涉及決策的代碼模型中都離不開閥值,比如最常用的止盈止損策略,在代碼的編寫中就一定會(huì)涉及閥值,比如之前的章節(jié)一直使用的abupy中內(nèi)置止盈止損策略AbuFactorCloseAtrNStop。
之所以一定會(huì)涉及閥值的確定是因?yàn)榫拖駝倓傉f的類似你求解一個(gè)方程組,如果所有的參數(shù)都是未知數(shù),那么你怎么解出你需要的答案,所以一定要把一些變量變成常數(shù)值,然后通過這些常數(shù)值來確定更多的變量,最終解出你所關(guān)心的解。
對(duì)于閥值的確定傳統(tǒng)的做法是根據(jù)經(jīng)驗(yàn)來設(shè)定,實(shí)際上所謂的經(jīng)驗(yàn)是個(gè)體對(duì)問題的統(tǒng)計(jì)模型, 在機(jī)器學(xué)習(xí)技術(shù)的幫助下,可以實(shí)現(xiàn)更客觀,全面,適應(yīng)范圍更廣的閥值設(shè)定。
不論是個(gè)體經(jīng)驗(yàn)對(duì)閥值進(jìn)行常量定估還是通過機(jī)器學(xué)習(xí)技術(shù)通過數(shù)據(jù)模型對(duì)閥值進(jìn)行定估,都達(dá)不到絕對(duì)準(zhǔn)確預(yù)測(cè)結(jié)果的目標(biāo),量化交易的概率優(yōu)勢(shì)并不具有絕對(duì)的優(yōu)勢(shì),即達(dá)不到預(yù)測(cè)的程度,量化交易中大多策略是基于對(duì)歷史規(guī)律的總結(jié),在規(guī)律的基礎(chǔ)上發(fā)現(xiàn)概率優(yōu)勢(shì),它的***理論依據(jù)是人性的相似性以及人性很難改變的事實(shí),如果每一個(gè)瞬間的股票價(jià)格都是全體交易者對(duì)價(jià)值所達(dá)成的一種瞬間共識(shí),那么歷史的規(guī)律在今后的交易中同樣具有指導(dǎo)意義。
按照上面解方程的說法就是,定估的常量只要能滿足大多數(shù)時(shí)候解出合理的解,甚至很多時(shí)候定估的常量只要能滿足有時(shí)候能解出合理的解就可以,對(duì)于有時(shí)候能解出合理的情況,可以在上層通過非均衡技術(shù)對(duì)決策進(jìn)行二次邏輯過濾,我反復(fù)提及過的非均衡技術(shù)思想是量化中很很重要的一種設(shè)計(jì)思路,因?yàn)槲覀兞炕哪繕?biāo)結(jié)果就是非均衡,我們想要贏的錢比輸?shù)亩唷?/p>
1. 比特幣特征的提取
下面通過對(duì)比特幣的短線交易決策為例,示例上述論點(diǎn)以及abupy中機(jī)器學(xué)習(xí)模塊的使用,以及數(shù)據(jù)獲?。?/p>
- from abupy import abu, ml, nd, tl, pd_resample, AbuML, AbuMLPd, AbuMetricsBase
- from abupy import ABuSymbolPd, ABuScalerUtil, get_price, ABuMarketDrawing, ABuKLUtil
- # btc是比特幣symbol代號(hào)
- btc = ABuSymbolPd.make_kl_df('btc', start='2013-09-01', end='2017-07-26')
之前在比特幣, 萊特幣的回測(cè)那節(jié)使用ABuKLUtil.date_week_wave對(duì)走勢(shì)的日震蕩做過統(tǒng)計(jì)如下:
- ABuKLUtil.date_week_wave(btc)
- date_week
- 周一 5.0108
- 周二 5.5610
- 周三 5.4437
- 周四 5.7275
- 周五 5.3008
- 周六 4.7875
- 周日 4.6528
- Name: wave, dtype: float64
從上面可以看出大概0.055的日震蕩幅度可以成做大波動(dòng)的交易對(duì)比特幣來說,下面對(duì)數(shù)據(jù)添加新列big_wave,可以看到結(jié)果大波動(dòng)的占總交易日的1/3:
- btc['big_wave'] = (btc.high - btc.low) / btc.pre_close > 0.055
- btc['big_wave'] = btc['big_wave'].astype(int)
- btc['big_wave'].value_counts()
- 0 1005
- 1 420
- Name: big_wave, dtype: int64
任何大的決策其實(shí)都是由很多看極起來極不起眼的小事組成的,如果我們是做比特幣日內(nèi)的交易者,首先你需要判斷今天適不適合做交易,做出這個(gè)判斷的依據(jù)里有一條即是今天的波動(dòng)需要足夠大,下面通過機(jī)器學(xué)習(xí)技術(shù)演示如何決策今天的波動(dòng)是否足夠大。
備注:由于abupy中內(nèi)置沙盒數(shù)據(jù)沒有分時(shí)的數(shù)據(jù),所以本示例使用日線數(shù)據(jù)做為分析對(duì)象,實(shí)際策略中應(yīng)該使用的是分鐘數(shù)據(jù)
首先切割訓(xùn)練集和測(cè)試集,保留***60天走勢(shì)數(shù)據(jù)做為測(cè)試集數(shù)據(jù):
- btc_train_raw = btc[:-60]
- btc_test_raw = btc[-60:]
下面為訓(xùn)練集和測(cè)試集數(shù)據(jù)都加上5,10,21,60日均線特征:
- def calc_ma(tc, ma):
- ma_key = 'ma{}'.format(ma)
- tc[ma_key] = nd.ma.calc_ma_from_prices(tc.close, ma, min_periods=1)
- for ma in [5, 10, 21, 60]:
- calc_ma(btc_train_raw, ma)
- calc_ma(btc_test_raw, ma)
- btc_train_raw.tail(1)
編寫特征抽取組合函數(shù)btc_siblings_df:
- 它首先將所有交易日以3個(gè)為一組,切割成多個(gè)子df,即每一個(gè)子df中有3個(gè)交易日的交易數(shù)據(jù)
- 使用數(shù)據(jù)標(biāo)準(zhǔn)化將連續(xù)3天交易日中的連續(xù)數(shù)值特征進(jìn)行標(biāo)準(zhǔn)化操作
- 抽取***天,第二天的大多數(shù)特征分別改名字以one,two為特征前綴,如:one_open,one_close,two_ma5,two_high…..,
- 第三天的特征只使用’open’, ‘low’, ‘pre_close’, ‘date_week’,該名前綴today,如today_open,today_date_week
- 第三天的抽取了’big_wave’,其將在之后做為y
- 將抽取改名字后的特征連接起來組合成為一條新數(shù)據(jù),即3天的交易數(shù)據(jù)特征->1條新的數(shù)據(jù)
代碼如下所示:
- def btc_siblings_df(btc_raw):
- # 將所有交易日以3個(gè)為一組,切割成多個(gè)子df,即每一個(gè)子df中有3個(gè)交易日的交易數(shù)據(jù)
- btc_siblings = [btc_raw.ix[sib_ind * 3:(sib_ind + 1) * 3, :]
- for sib_ind in np.arange(0, int(btc_raw.shape[0] / 3))]
- btc_df = pd.DataFrame()
- for sib_btc in btc_siblings:
- # 使用數(shù)據(jù)標(biāo)準(zhǔn)化將連續(xù)3天交易日中的連續(xù)數(shù)值特征進(jìn)行標(biāo)準(zhǔn)化操作
- sib_btc_scale = ABuScalerUtil.scaler_std(
- sib_btc.filter(['open', 'close', 'high', 'low', 'volume', 'pre_close',
- 'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14']))
- # 把標(biāo)準(zhǔn)化后的和big_wave,date_week連接起來
- sib_btc_scale = pd.concat([sib_btc['big_wave'], sib_btc_scale, sib_btc['date_week']], axis=1)
- # 抽取***天,第二天的大多數(shù)特征分別改名字以one,two為特征前綴,如:one_open,one_close,two_ma5,two_high.....
- a0 = sib_btc_scale.iloc[0].filter(['open', 'close', 'high', 'low', 'volume', 'pre_close',
- 'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14', 'date_week'])
- a0.rename(index={'open': 'one_open', 'close': 'one_close', 'high': 'one_high', 'low': 'one_low',
- 'volume': 'one_volume', 'pre_close': 'one_pre_close',
- 'ma5': 'one_ma5', 'ma10': 'one_ma10', 'ma21': 'one_ma21',
- 'ma60': 'one_ma60', 'atr21': 'one_atr21', 'atr14': 'one_atr14',
- 'date_week': 'one_date_week'}, inplace=True)
- a1 = sib_btc_scale.iloc[1].filter(['open', 'close', 'high', 'low', 'volume', 'pre_close',
- 'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14', 'date_week'])
- a1.rename(index={'open': 'two_open', 'close': 'two_close', 'high': 'two_high', 'low': 'two_low',
- 'volume': 'two_volume', 'pre_close': 'two_pre_close',
- 'ma5': 'two_ma5', 'ma10': 'two_ma10', 'ma21': 'two_ma21',
- 'ma60': 'two_ma60', 'atr21': 'two_atr21', 'atr14': 'two_atr14',
- 'date_week': 'two_date_week'}, inplace=True)
- # 第三天的特征只使用'open', 'low', 'pre_close', 'date_week',該名前綴today,如today_open,today_date_week
- a2 = sib_btc_scale.iloc[2].filter(['big_wave', 'open', 'low', 'pre_close', 'date_week'])
- a2.rename(index={'open': 'today_open', 'low': 'today_low',
- 'pre_close': 'today_pre_close',
- 'date_week': 'today_date_week'}, inplace=True)
- # 將抽取改名字后的特征連接起來組合成為一條新數(shù)據(jù),即3天的交易數(shù)據(jù)特征->1條新的數(shù)據(jù)
- btc_df = btc_df.append(pd.concat([a0, a1, a2], axis=0), ignore_index=True)
- return btc_df
第三天的特征避免使用high是因?yàn)橛?xùn)練的目標(biāo)y是big_wave,之所以可以使用當(dāng)天的low是因?yàn)楸忍貛攀袌?chǎng)的特點(diǎn)為24小時(shí)交易,即沒有明確的一天的概念,也即沒有明確一天中的***,實(shí)盤使用即人工對(duì)當(dāng)前***根據(jù)24小時(shí)***進(jìn)行猜測(cè),或直接使用24小時(shí)***,或者使用當(dāng)前的***價(jià)格都可,組成數(shù)據(jù)后使用模型進(jìn)行決策,決策的結(jié)果即為未來數(shù)小時(shí)內(nèi)是否會(huì)有大的波動(dòng),實(shí)際上最終大波動(dòng)的決策成立,需要其它很多模型共同生效,比如外盤的走勢(shì)決策等等。
下面使用訓(xùn)練集數(shù)據(jù)btc_train_raw做為參數(shù)抽取組合特征,重新組合好的特征如tail所示:
- btc_train0 = btc_siblings_df(btc_train_raw)
- btc_train0.tail()

如上所示這樣我們只能得到454條訓(xùn)練集數(shù)據(jù),但由于每3條連續(xù)交易日數(shù)據(jù)組合成一個(gè)特征,只要向前跳一條數(shù)據(jù)進(jìn)行特征組合抽取即可以得到另一組新特征,下面分別跳過***個(gè),第二個(gè)數(shù)據(jù),抽取btc_train1,btc_train2:
- btc_train1 = btc_siblings_df(btc_train_raw[1:])
- btc_train2 = btc_siblings_df(btc_train_raw[2:])
下面把上面的3組特征連起來,然后把周幾這個(gè)特征使用pd.get_dummies進(jìn)行離散化處理,使得所有特征值的范圍都在0-1之間,最終的特征如下btc_train所示:
- btc_train = pd.concat([btc_train0, btc_train1, btc_train2])
- btc_train.index = np.arange(0, btc_train.shape[0])
- dummies_one_week = pd.get_dummies(btc_train['one_date_week'], prefix='one_date_week')
- dummies_two_week = pd.get_dummies(btc_train['two_date_week'], prefix='two_date_week')
- dummies_today_week = pd.get_dummies(btc_train['today_date_week'], prefix='today_date_week')
- btc_train.drop(['one_date_week', 'two_date_week', 'today_date_week'], inplace=True, axis=1)
- btc_train = pd.concat([btc_train, dummies_one_week, dummies_two_week, dummies_today_week], axis=1)
- pd.options.display.max_rows=10
- btc_train
2. abu中內(nèi)置機(jī)器學(xué)習(xí)模塊的使用
下面使用abupy中內(nèi)置機(jī)器學(xué)習(xí)工具AbuML對(duì)特征數(shù)據(jù)進(jìn)行封裝,代碼如下所示,下面的y值即是big_wave列:
- train_matrix = btc_train.as_matrix()
- y = train_matrix[:, 0]
- x = train_matrix[:, 1:]
- btc_ml = AbuML(x, y, btc_train)
AbuML會(huì)根據(jù)數(shù)據(jù)特點(diǎn)自動(dòng)內(nèi)部選擇使用分類器或者回歸器,下面進(jìn)行特指***分類器操作,比如特指使用隨機(jī)森林做為分類器,執(zhí)行random_forest_classifier_best會(huì)在內(nèi)部對(duì)n_estimators參數(shù)和訓(xùn)練集數(shù)據(jù)進(jìn)行g(shù)rid search擬合,尋找最合適的參數(shù)最終做為內(nèi)部分類器:
- btc_ml.random_forest_classifier_best()
- start grid search please wait...
- RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
- max_depth=None, max_features='auto', max_leaf_nodes=None,
- min_impurity_split=1e-07, min_samples_leaf=1,
- min_samples_split=2, min_weight_fraction_leaf=0.0,
- n_estimators=260, n_jobs=1, oob_score=False, random_state=None,
- verbose=0, warm_start=False)
所有best函數(shù)中尋找***參數(shù)內(nèi)部只根據(jù)學(xué)習(xí)器的特點(diǎn)尋找最少量的參數(shù)設(shè)置,如果需要自定義參數(shù)范圍可使用如下所示:
- param_grid = {'max_features': ['sqrt', 'log2'], 'n_estimators': np.arange(50, 500, 50)}
- btc_ml.random_forest_classifier_best(param_grid=param_grid)
- start grid search please wait...
- RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
- max_depth=None, max_features='sqrt', max_leaf_nodes=None,
- min_impurity_split=1e-07, min_samples_leaf=1,
- min_samples_split=2, min_weight_fraction_leaf=0.0,
- n_estimators=400, n_jobs=1, oob_score=False, random_state=None,
- verbose=0, warm_start=False)
下面使用btc_ml對(duì)訓(xùn)練集進(jìn)行交叉準(zhǔn)確率評(píng)分:
- btc_ml.cross_val_accuracy_score()
- RandomForestClassifier score mean: 0.8151620867325032
- array([ 0.781 , 0.8102, 0.7883, 0.8382, 0.8162, 0.8162, 0.8235,
- 0.8456, 0.7794, 0.8529])
下面使用btc_ml對(duì)訓(xùn)練集進(jìn)行交叉roc_auc評(píng)分:
- btc_ml.cross_val_roc_auc_score()
- RandomForestClassifier score mean: 0.8399573797130188
- array([ 0.815 , 0.8785, 0.8166, 0.8018, 0.8707, 0.8484, 0.8148,
- 0.8551, 0.8005, 0.8981])
AbuML對(duì)外的函數(shù)都支持關(guān)鍵子參數(shù)fiter_type,可以指定使用的學(xué)習(xí)器類型如回歸,聚類等,每個(gè)函數(shù)都通過內(nèi)部裝飾器聲明自己支持的學(xué)習(xí)器類型對(duì)不支持的類型輸出不支持,如下想通過指定使用回歸器進(jìn)行roc_auc評(píng)分:
- btc_ml.cross_val_roc_auc_score(fiter_type=ml.EMLFitType.E_FIT_REG)
- cross_val_roc_auc_score not support reg!
上述輸出顯示函數(shù)不支持回歸器,因?yàn)閮?nèi)部實(shí)現(xiàn)中通過entry_wrapper裝飾器聲明了只支持E_FIT_CLF,即分類器:
- @entry_wrapper(support=(EMLFitType.E_FIT_CLF,))
- def cross_val_roc_auc_score(self, cv=10, **kwargs):
- """
- 被裝飾器entry_wrapper(support=(EMLFitType.E_FIT_CLF,))裝飾,
- 即支持有監(jiān)督學(xué)習(xí)分類,使用cross_val_score對(duì)數(shù)據(jù)進(jìn)行roc_auc度量,如果數(shù)據(jù)的y的
- label標(biāo)簽 > 2,通過label_binarize將label標(biāo)簽進(jìn)行二值化處理,
- 依次計(jì)算二值化的列的roc_auc,結(jié)果返回score***的數(shù)據(jù)度量
- :param cv: 透?jìng)鱟ross_val_score的參數(shù),默認(rèn)10
- :param kwargs: 外部可以傳遞x, y, 通過
- x = kwargs.pop('x', self.x)
- y = kwargs.pop('y', self.y)
- 確定傳遞self._do_cross_val_score中參數(shù)x,y,
- 以及裝飾器使用的fiter_type,eg:
- ttn_abu.cross_val_roc_auc_score(fiter_type=ml.EMLFitType.E_FIT_REG)
- :return: cross_val_score返回的score序列,
- eg: array([ 1. , 0.9 , 1. , 0.9 , 1. , 0.9 , 1. , 0.9 , 0.95, 1. ])
- """
- x = kwargs.pop('x', self.x)
- y = kwargs.pop('y', self.y)
- return self._do_cross_val_score(x, y, cv, _EMLScoreType.E_SCORE_ROC_AUC.value)
更多詳情實(shí)現(xiàn)請(qǐng)閱讀源代碼AbuML
下面使用train_test_split_xy查看訓(xùn)練集輸出的precision_score,recall_score,混淆矩陣,以及f1等度量結(jié)果:
- btc_ml.train_test_split_xy()
- x-y:(1363, 48)-(1363,)
- train_x-train_y:(1226, 48)-(1226,)
- test_x-test_y:(137, 48)-(137,)
- accuracy = 0.77
- precision_score = 0.62
- recall_score = 0.39
- Predicted
- | 0 | 1 |
- |-----|-----|
- 0 | 90 | 9 |
- Actual |-----|-----|
- 1 | 23 | 15 |
- |-----|-----|
- precision recall f1-score support
- 0.0 0.80 0.91 0.85 99
- 1.0 0.62 0.39 0.48 38
- avg / total 0.75 0.77 0.75 137
下面通過plot_roc_estimator繪制roc曲線:
- btc_ml.plot_roc_estimator()
下面通過plot_confusion_matrices繪制混淆矩陣:
- btc_ml.plot_confusion_matrices()
- [[915 65]
- [183 200]]
下面通過plot_decision_function繪制決策邊界,由于繪制2d圖,內(nèi)部已經(jīng)使用pca將數(shù)據(jù)特征降維后再繪制:
- btc_ml.plot_decision_function()
下面通過plot_graphviz_tree繪制邏輯決策圖:
- btc_ml.plot_graphviz_tree()
- RandomForestClassifier not hasattr tree_, use decision tree replace
下面通過feature_selection對(duì)特征的支持度進(jìn)行評(píng)級(jí):
- pd.options.display.max_rows = 48
- btc_ml.feature_selection(show=False).sort_values(by='ranking')
下面通過importances_coef_pd對(duì)特征的重要程度進(jìn)行量化:
- btc_ml.importances_coef_pd().sort_values(by='importance')[::-1]
3. 測(cè)試集的驗(yàn)證與非均衡技術(shù)
下面將前面保留切割的60條測(cè)試數(shù)據(jù)進(jìn)行特征抽取組合,方式和抽取訓(xùn)練集時(shí)一樣,代碼如下所示:
- btc_test0 = btc_siblings_df(btc_test_raw)
- btc_test1 = btc_siblings_df(btc_test_raw[1:])
- btc_test2 = btc_siblings_df(btc_test_raw[2:])
- btc_test = pd.concat([btc_test0, btc_test1, btc_test2])
- btc_test.index = np.arange(0, btc_test.shape[0])
- dummies_one_week = pd.get_dummies(btc_test['one_date_week'], prefix='one_date_week')
- dummies_two_week = pd.get_dummies(btc_test['two_date_week'], prefix='two_date_week')
- dummies_today_week = pd.get_dummies(btc_test['today_date_week'], prefix='today_date_week')
- btc_test.drop(['one_date_week', 'two_date_week', 'today_date_week'], inplace=True, axis=1)
- btc_test = pd.concat([btc_test, dummies_one_week, dummies_two_week, dummies_today_week], axis=1)
- matrix_test = btc_test.as_matrix()
- y_test = matrix_test[:, 0]
- x_test = matrix_test[:, 1:]
對(duì)測(cè)試集數(shù)據(jù)進(jìn)行準(zhǔn)確率評(píng)估,代碼如下所示:
- from sklearn import metrics
- y_predict = [btc_ml.predict(x_test[test_ind])[0] for test_ind in np.arange(0, matrix_test.shape[0])]
- print('測(cè)試集正確率{:3f}'.format(metrics.accuracy_score(y_test, y_predict)))
- 測(cè)試集正確率0.620690
如上所示上面的準(zhǔn)確率結(jié)果為60%以上正確,下面使用predict_proba看看概率結(jié)果:
- y_prob = [btc_ml.predict_proba(x_test[test_ind])[0] for test_ind in np.arange(0, matrix_test.shape[0])]
- y_prob[-10:]
- [array([ 0.495, 0.505]),
- array([ 0.9075, 0.0925]),
- array([ 0.7875, 0.2125]),
- array([ 0.83, 0.17]),
- array([ 0.8375, 0.1625]),
- array([ 0.96, 0.04]),
- array([ 0.58, 0.42]),
- array([ 0.495, 0.505]),
- array([ 0.6575, 0.3425]),
- array([ 0.565, 0.435])]
本節(jié)開始的時(shí)候說過很多時(shí)候定估的決策只要能滿足有時(shí)候能解出合理的解就可以,通過非均衡技術(shù)對(duì)決策進(jìn)行二次邏輯過濾即可,下面解釋這句話的意思,通過上面y_predict輸出你可以看到準(zhǔn)確率結(jié)果為60%以上,如果你只按照這個(gè)決策認(rèn)定比特幣今天是否有大行情還是有很多錯(cuò)誤的可能,上面的y_prob輸出了每一個(gè)決策的概率。
那么我們?nèi)绻M霰忍貛沤灰字幌M跊Q策模型有很大把握的情況下才做,否則寧可少賺點(diǎn)錢也不做應(yīng)該怎么做呢?
上面predict的決策在某一個(gè)值在0.5以上即進(jìn)行了判斷,如果我們希望把握更大一些就需要調(diào)整這個(gè)值,比如0.55以上才能認(rèn)定決策,那首要的問題就是如何選定這個(gè)閥值,下面示例使用search_match_pos_threshold進(jìn)行閥值的確定:
- btc_ml.search_match_pos_threshold(accuracy_match=0.85)
- 0.580 satisfy require, accuracy:0.854, effect_rate:0.879
結(jié)果如上所示,search_match_pos_threshold函數(shù)的作用是對(duì)訓(xùn)練集數(shù)據(jù)進(jìn)行非均衡結(jié)果度量,從0.5至0.99的范圍內(nèi)開始不斷向上調(diào)整決策閥值:
比如測(cè)試閥值為0.55,那么如果決策的概率為array([ 0.5378, 0.4622]),那么通過閥值二分化后結(jié)果為(0, 0),這個(gè)結(jié)果將不計(jì)入正確率統(tǒng)計(jì)中,即認(rèn)為未達(dá)成有效的決策,但如果決策的概率為 array([ 0.9711, 0.0289]),那么通過閥值二分化后結(jié)果為(1, 0),認(rèn)為達(dá)成有效的決策,當(dāng)有效的決策正確率達(dá)到參數(shù)accuracy_match傳遞的值,本例中使用0.85即85%的正確率時(shí),停止搜索,本例返回的結(jié)果為0.580,即使用閥值0.580可以達(dá)成非均衡決策的85%正確率。
備注:與之對(duì)應(yīng)search_match_neg_threshold進(jìn)行閥值搜索,從0.5至0.01的范圍內(nèi)開始不斷向下調(diào)整決策閥值,更多詳情請(qǐng)閱讀源代碼。
下面使用0.580做為閥值,通過predict_proba_threshold函數(shù)進(jìn)行決策,代碼如下:
- y_prob_threshold = [btc_ml.predict_proba_threshold(x_test[test_ind], 0.580, 0)
- for test_ind in np.arange(0, matrix_test.shape[0])]
上面predict_proba_threshold傳遞的第三個(gè)參數(shù)0為未達(dá)成有效決策的情況下返回的決策結(jié)果,即閥值二分化后結(jié)果為(0, 0)后這里返回0,因?yàn)樵诒忍貛胚@個(gè)示例中如果交易者想要保守的方式?jīng)Q策今天是否適合做日內(nèi)交易,那么就希望只在有很大概率的情況下返回1,即適合交易,其它情況下沒有太大把握下全部返回0即可,下面使用precision_score計(jì)算查準(zhǔn)率:
- metrics.precision_score(y_test, y_prob_threshold)
- 1.0
如上所示查準(zhǔn)率100%正確,但召回率評(píng)分非常低,即比特幣在很多有大行情的情況下為了保守,放棄了日交易,只在把握大的時(shí)候行動(dòng):
- metrics.recall_score(y_test, y_prob_threshold)
- 0.20000000000000001
與上面的情況相反也有些激進(jìn)的交易者想要的決策結(jié)果是只要今天不是很大把握說沒有行情,那就進(jìn)行交易。
下面使用0.90做為閥值,通過predict_proba_threshold函數(shù)進(jìn)行決策,第三個(gè)參數(shù)1即在為未達(dá)成有效決策的情況下返回的決策結(jié)果為1,可以看到結(jié)果的決策中大多數(shù)都被決策為1,代碼如下:
- y_prob_threshold = [btc_ml.predict_proba_threshold(x_test[test_ind], 0.90, 1)
- for test_ind in np.arange(0, matrix_test.shape[0])]
- pd.Series(y_prob_threshold).value_counts()
- 1 49
- 0 9
- dtype: int64
4. 繼承AbuMLPd對(duì)數(shù)據(jù)處理進(jìn)行封裝
在abupy中不建議直接使用AbuML類進(jìn)行構(gòu)造,推薦使用繼承AbuMLPd后實(shí)現(xiàn)make_xy方法,在make_xy中將數(shù)據(jù)訓(xùn)練集和測(cè)試集進(jìn)行組裝完成,AbuMLPd基類通過代理方法對(duì)AbuML中的所有方法進(jìn)行代理,即可以和使用AbuML中的方法一樣的接口操作,本節(jié)使用的示例內(nèi)置在abupy項(xiàng)目中BtcBigWaveClf類,具體實(shí)現(xiàn)請(qǐng)直接閱讀BtcBigWaveClf。
小結(jié):由于abupy中內(nèi)置沙盒數(shù)據(jù)沒有分時(shí)的數(shù)據(jù),所以本示例使用日線數(shù)據(jù)做為分析對(duì)象,實(shí)際策略中應(yīng)該使用的是分鐘數(shù)據(jù),本節(jié)示例主要為配合abupy中機(jī)器學(xué)習(xí)模塊的使用示例所寫,與真實(shí)的日內(nèi)交易決策還有很大差別。