用 Python 做策略回测,耗时很长,有什么加速办法?

论坛 期权论坛 期权     
JYHX   2018-9-23 04:08   46552   9
用python 做策略回测,耗时很长。40万条数据花了快一个小时。
想问下,通常50万数量级的数据的回测用时多少?(简单策略,一支股票一年的tick差不多40万)
有什么加速办法?
-----------------------------------------------------------------------------------------分割线
首先真诚感谢各位帮助。回馈知乎,附上我最后的处理方法。
本人最后使用了cython 来处理python 中for loop 的部分, 运行时间缩短显著。建议无法对数据实行整列计算,而只能选择loop, 逐个数据递推,来生成一列数据的情况。可以使用cython处理loop部分。

直接上图,下面是一个生成列的小测试,分别计算两种方法效率。用时相差2个数量级。

分享到 :
0 人收藏

9 个回复

倒序浏览
2#
知之  4级常客 | 2018-9-23 04:08:04 发帖IP地址来自
少用for,尽量用numpy/pandas的向量化方法。
少用自己写的python方法,先看看numpy /pandas是不是已有现成的功能。
有几个numpy 的加速包,比如numexpr.
安装Intel MKL.
最后,可以讲关键部分用c/c++实现。

如果无法避开python的for,建议使用Numba来提速,理想情况下可以达到和numpy向量化差不多的速度。
我只能帮你到这里了||-_-
3#
TraderJay\'s  3级会员 | 2018-9-23 04:08:05 发帖IP地址来自
太慢了, 我逐tick(也就是不使用向量化,完全和实盘一样推送tick)python 回测40w数据大概也是几分钟这个级别。我还没用cython, 只是用numpy。如果向量化回测 只需要十几秒。

一点小经验,逐tick的时候不要用pandas,比numpy慢两个量级。

当然这个速度要做参数优化遍l历还是够呛,目前我是向量化回测找参数,再翻译成逐tick策略。不过这样一个策略要写几套代码。容易出bug。

下一步优化考虑一下几个方案备选, 希望听听大家意见:
1.
把策略引擎用c++实现 boost.python封装成python library

2. c++引擎调用python策略层

3. cython
4#
低端叫兽  4级常客 | 2018-9-23 04:08:06 发帖IP地址来自
2016.4.19做的回测,80万条数据用了3分半跑完(四进程)。
用python想降低回测时延,可以从下面几个角度下功夫:
1.有几个cpu核开几个进程,记得不是线程是进程。
2.在数据结构和算法上下功夫。
3.在CPU cache命中率上下功夫,loop时操作的数据尽可能在内存上紧凑,不要在loop里遍历pandas的列,因为这会导致cache命中率大幅降低。而CPU访问内存的时延远在访问cache之上。楼主回测时延高问题应该就出在这里。可以把pandas的列转换成list再在loop中使用。
5#
越过刀锋  1级新秀 | 2018-9-23 04:08:08 发帖IP地址来自
我们目前正在开发的回测引擎使用的也是python,近期也在进行性能方面的优化,以下建议供参考:

1. 在动手优化之前,先profile看看,程序时间都花在哪些地方了:
python -m cProfile -o output.prof your_program
跑完之后,会生成一个output.profile文件。接下来需要对这个文件进行分析,这方面的工具我推荐SnakeViz,神器。安装非常简单,pip install snakeviz 即可。
snakeviz output.prof
运行之后,会打开一个浏览器窗口,好好看看,哪些函数耗时最多,耗时是因为调用次数太多呢,还是因为单次调用耗时长,明确优化重点;

2. 减少重复计算,缓存计算结果。看看 functools.lru_cache。

3. 能用list comprehension的地方,不要用for;能用numpy的地方,不要手写循环,不要用pandas;

4. 看你的回测,40w个tick的话,数据量不算大,应该是直接load到内存里的吧?

5. 还是慢的话,上Numba — Numba,就是安装麻烦一些,使用起来非常方便,速度提高一两个数量级没问题;

6. 如果你用的包PyPy都支持的话,试试pypy;

7. Cython、c module,上面的都没效果的话,这个是最后的候选方案了。

----------------
广告时间:
我们目前正在招人,欢迎各位投条:
Ricequant - Beta
6#
不姓马的小马哥  1级新秀 | 2018-9-23 04:08:09 发帖IP地址来自
一般来说,如果不是做tick级别的portfolio统计套利,大部分的单腿或者两三腿的策略逻辑都可以通过numpy或者pandas的rolling函数及其他矩阵的操作实现。
无法矩阵化操作的内容较为常见的有如下一些内容:
滑动止损/止盈/时间出场,
EMA之类的路径依赖指标,
rolling的回归等等。

较为复杂的可能包括一些tick级别的模拟成交回测,当年我还在纯用python硬怼的时候回测真是怼的眼泪都掉下来。
然而当我痛下决心花了俩晚上在所有使用tick级别的for循环的地方用c++重写,然后用swig、 boost.python神马的一wrap,嘿,腰不酸了,腿不疼了。一口气测几年不喘气了。

所以,有什么可纠结的呢?投入c++大法写几个函数,转眼就超生。numpy,talib为什么快?因为人家就是用c写的啊!
7#
find goo  4级常客 | 2018-9-23 04:08:10 发帖IP地址来自
你这代码写得有问题,如果是技术指标,不是每个tick都要从头到脚运行,如计算MA在100分钟tick计算是从0-100来遍历,在200分钟用0-200来遍历,不是这样的,这种方法如tick一多这样计算到后面是指数增长,再高级的服务器也hold不住。正确方法是用窗口函数来计算技术指标,只计算窗口有效值,再append到已经计算好的值中去,如计算200tick的MA,根据周期如20,只需要计算过去20个tick,遍历20次,这样计算量不会出现指数增长,而是一个窗口计算复杂度*tick长度n。

窗口计算方法和整个遍历计算不太一样,需要转换,talib是一种遍历方法,你可以一次算完存储后再使用,但没有窗口计算法高效,因为窗口计算法可以根据条件来判断计算还是不计算。窗口函数计算方法,可以用于实时分秒策略,来了一个tick,就很快分析出,高频交易时可以抢到时间。
8#
JoinQuant  3级会员 | 2018-9-23 04:08:11 发帖IP地址来自
你的大蟒是不是太慢了???
给你的python加速。

Cython(语法要改) Numba(兼容性不好,不用改)
9#
空明流转  5级知名 | 2018-9-23 04:08:12 发帖IP地址来自
我觉得多少是你的算法有问题。
在排除算法问题后可以用PyPy尝试加速一下。
10#
陈亚龙  4级常客 | 2018-9-23 04:08:13 发帖IP地址来自
楼主做的tick级的回测,一次几只股票回测几年?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP