引言
如果你經(jīng)過仔細思考認真研究終于產(chǎn)生了一個好想法(交易策略),當然恨不得立刻投入交易賺大錢岖寞。但是抡四,世間不如意十之八九,往往好想法并不一定產(chǎn)生好結(jié)果仗谆。市場并沒有按照預期的情況發(fā)展指巡,結(jié)果不但沒有賺還虧損不少。:-(
怎么才能在不虧損的情況下隶垮,先驗證下我們的交易策略是否有效藻雪?碼農(nóng)說,測試唄@晖獭(另一種驗證方法是“證明”勉耀,此處暫不涉及)
怎么測試?兩條路:
- 虛擬交易蹋偏,假投資便斥,好處是實際交易情況,不足是費時費力威始,而且大家都知道測試只能測試某些情況很難全覆蓋所有的情況椭住,就算虛擬交易多年勝利也不能保證之后的勝利。
- 拿過去的交易數(shù)據(jù)測試字逗,好處就是數(shù)據(jù)大覆蓋的可能情況多測試更全面京郑。另外宅广,就是快!迅速獲得驗證后些举,結(jié)果好的話就可以投入實際使用了跟狱!這就是回測。
兩種回測方式
回測分兩種:事件驅(qū)動回測户魏,向量化回測驶臊。兩種有什么不同呢?
- 事件驅(qū)動回測一般一次處理一個事件(通常就是一個歷史數(shù)據(jù)叼丑,如日線中的一天數(shù)據(jù)关翎,實時交易中的一次報價)
- 向量化回測則一次處理所有事件,對所有向量或矩陣數(shù)據(jù)進行同時計算鸠信。(在pandas中纵寝,向量就是
Series
,矩陣就是DataFrame
)
舉例
舉一個簡單的例子星立,我們的策略是在價格低于10元的時候買進爽茴,高于10元的時候賣出。假設(shè)我們有價格數(shù)據(jù)绰垂,想要確定哪天買入哪天賣出室奏。
data = {
"2017-02-01": 10.07,
"2017-02-02": 9.87,
"2017-02-03": 9.91,
"2017-02-04": 10.01
}
如果使用事件驅(qū)動回測,我們循環(huán)遍歷每天的數(shù)據(jù)劲装,檢查價格因素:
for date, price in data.items():
if price < 10:
buy_signal = True
else:
buy_signal = False
print(date, buy_signal)
結(jié)果顯示:
2017-02-01 False
2017-02-02 True
2017-02-03 True
2017-02-04 False
如果使用向量化回測胧沫,我們一次性檢查所有的價格以確定買賣信號:
import pandas as pd
prices = pd.Series(data)
buy_signals = prices < 10
buy_signals.head()
結(jié)果顯示:
2017-02-01 False
2017-02-02 True
2017-02-03 True
2017-02-04 False
dtype: bool
兩種回測的方式不同,產(chǎn)生的結(jié)果是相同的占业。
兩種回測方式的特點
向量化回測比事件驅(qū)動回測快得多
我們之所以做回測绒怨,一個非常重要的原因就是可以快速基于大量的歷史數(shù)據(jù)做策略測試。實際情況下纺酸,回測數(shù)據(jù)是非常大量的窖逗,而我們需要做測試的策略可能很多址否,對于每個策略需要調(diào)整的參數(shù)也可能很多餐蔬,所以,速度是可能是一個非常關(guān)鍵的考慮佑附。在高速的情況下樊诺,我們可以做大量的策略測試以尋找合適的策略。想象一下音同,如果我們一天可以跑人家100天甚至1000天的回測词爬,那效果......
做了一個實驗比較pyalgotrade和vector-bt的運行情況(實現(xiàn)了同樣的均線策略,跑同樣的數(shù)據(jù)集合):
from timeit import default_timer as timer
......此處忽略start策略的定義
t = timer()
strat.run()
print("done. %.4fs" % (timer() - t))
......此處忽略mybt的定義
t = timer()
a = mybt(rate_sr)
print("done. %.4fs" % (timer() - t))
結(jié)果如下:
記錄條目數(shù)量 | pyalgotrade 耗時 | vector-bt 耗時 | 耗時相對倍數(shù) | |
---|---|---|---|---|
日線 | 111 | 0.0241s | 0.0027s | 9 |
分鐘線 | 26400 | 6.0542s | 0.0103s | 588 |
兩線倍數(shù) | 237.8 | 251 | 3.8 | |
- | - | - | - | - |
日線 | 289 | 0.0783s | 0.0026s | 30 |
分鐘線 | 69360 | 16.0826s | 0.0220s | 731 |
兩線倍數(shù) | 240 | 205 | 8.46 |
注:這里vector-bt沒有使用多核并行权均,從vector-bt的實驗情況可知使用多核并行可以獲得700倍的速度提升顿膨。
結(jié)論:
從結(jié)果可看出锅锨,事件驅(qū)動回測的處理時間和需要處理的數(shù)據(jù)條目數(shù)量成正比,符合預期恋沃;向量化回測處理300條數(shù)據(jù)的情況下必搞,比事件驅(qū)動回測快30倍,而且和數(shù)據(jù)規(guī)模不成正比囊咏,70000條數(shù)據(jù)的情況下恕洲,比事件驅(qū)動回測快700倍!如果需要批量處理數(shù)據(jù)的情況梅割,使用多核并行霜第,700*700=490000倍速度!OMG户辞,我的判斷沒錯泌类!
向量化回測適合統(tǒng)計和機器學習算法
絕大部分統(tǒng)計和機器學習算法都基于向量或矩陣數(shù)據(jù)。事件驅(qū)動回測一次處理一個數(shù)據(jù)的方式無法適用這些先進的算法咆课,而向量化回測正好合適末誓。
事件驅(qū)動回測適合初學者或者非程序猿
事件驅(qū)動回測一般接口比較簡單,多數(shù)情況下只要給出 OnBar/OnTick 之類的函數(shù)以定義買入賣出條件和動作就可以了书蚪,所以方便使用喇澡。
因為使用的人多,所以能夠找到的文檔也多殊校,所以更方便使用晴玖。然后......循環(huán)回復......
向量化回測則相對復雜,需要懂得向量運算为流,懂的和用的人就少呕屎,就沒有啥文檔指導使用,然后......呵呵
切換到實際交易
對于事件驅(qū)動回測敬察,需要把歷史數(shù)據(jù)源切換為實時市場數(shù)據(jù)源秀睛,再把虛擬買賣換成實際交易接口就可以了。
對于向量化回測莲祸,需要做一次即時回測蹂安,然后拿交易信號向量的最后一行去交易就可以了。