引言
如果你经过仔细思考认真研究终于产生了一个好想法(交易策略),当然恨不得立刻投入交易赚大钱。但是,世间不如意十之八九,往往好想法并不一定产生好结果。市场并没有按照预期的情况发展,结果不但没有赚还亏损不少。:-(
怎么才能在不亏损的情况下,先验证下我们的交易策略是否有效?码农说,测试呗!(另一种验证方法是“证明”,此处暂不涉及)
怎么测试?两条路:
- 虚拟交易,假投资,好处是实际交易情况,不足是费时费力,而且大家都知道测试只能测试某些情况很难全覆盖所有的情况,就算虚拟交易多年胜利也不能保证之后的胜利。
- 拿过去的交易数据测试,好处就是数据大覆盖的可能情况多测试更全面。另外,就是快!迅速获得验证后,结果好的话就可以投入实际使用了!这就是回测。
两种回测方式
回测分两种:事件驱动回测,向量化回测。两种有什么不同呢?
- 事件驱动回测一般一次处理一个事件(通常就是一个历史数据,如日线中的一天数据,实时交易中的一次报价)
- 向量化回测则一次处理所有事件,对所有向量或矩阵数据进行同时计算。(在pandas中,向量就是
Series
,矩阵就是DataFrame
)
举例
举一个简单的例子,我们的策略是在价格低于10元的时候买进,高于10元的时候卖出。假设我们有价格数据,想要确定哪天买入哪天卖出。
data = {
"2017-02-01": 10.07,
"2017-02-02": 9.87,
"2017-02-03": 9.91,
"2017-02-04": 10.01
}
如果使用事件驱动回测,我们循环遍历每天的数据,检查价格因素:
for date, price in data.items():
if price < 10:
buy_signal = True
else:
buy_signal = False
print(date, buy_signal)
结果显示:
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()
结果显示:
2017-02-01 False
2017-02-02 True
2017-02-03 True
2017-02-04 False
dtype: bool
两种回测的方式不同,产生的结果是相同的。
两种回测方式的特点
向量化回测比事件驱动回测快得多
我们之所以做回测,一个非常重要的原因就是可以快速基于大量的历史数据做策略测试。实际情况下,回测数据是非常大量的,而我们需要做测试的策略可能很多,对于每个策略需要调整的参数也可能很多,所以,速度是可能是一个非常关键的考虑。在高速的情况下,我们可以做大量的策略测试以寻找合适的策略。想象一下,如果我们一天可以跑人家100天甚至1000天的回测,那效果......
做了一个实验比较pyalgotrade和vector-bt的运行情况(实现了同样的均线策略,跑同样的数据集合):
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))
结果如下:
记录条目数量 | pyalgotrade 耗时 | vector-bt 耗时 | 耗时相对倍数 | |
---|---|---|---|---|
日线 | 111 | 0.0241s | 0.0027s | 9 |
分钟线 | 26400 | 6.0542s | 0.0103s | 588 |
两线倍数 | 237.8 | 251 | 3.8 | |
- | - | - | - | - |
日线 | 289 | 0.0783s | 0.0026s | 30 |
分钟线 | 69360 | 16.0826s | 0.0220s | 731 |
两线倍数 | 240 | 205 | 8.46 |
注:这里vector-bt没有使用多核并行,从vector-bt的实验情况可知使用多核并行可以获得700倍的速度提升。
结论:
从结果可看出,事件驱动回测的处理时间和需要处理的数据条目数量成正比,符合预期;向量化回测处理300条数据的情况下,比事件驱动回测快30倍,而且和数据规模不成正比,70000条数据的情况下,比事件驱动回测快700倍!如果需要批量处理数据的情况,使用多核并行,700*700=490000倍速度!OMG,我的判断没错!
向量化回测适合统计和机器学习算法
绝大部分统计和机器学习算法都基于向量或矩阵数据。事件驱动回测一次处理一个数据的方式无法适用这些先进的算法,而向量化回测正好合适。
事件驱动回测适合初学者或者非程序猿
事件驱动回测一般接口比较简单,多数情况下只要给出 OnBar/OnTick 之类的函数以定义买入卖出条件和动作就可以了,所以方便使用。
因为使用的人多,所以能够找到的文档也多,所以更方便使用。然后......循环回复......
向量化回测则相对复杂,需要懂得向量运算,懂的和用的人就少,就没有啥文档指导使用,然后......呵呵
切换到实际交易
对于事件驱动回测,需要把历史数据源切换为实时市场数据源,再把虚拟买卖换成实际交易接口就可以了。
对于向量化回测,需要做一次即时回测,然后拿交易信号向量的最后一行去交易就可以了。