一个跑了三个月的ICT反转策略,真正的瓶颈不在策略逻辑,而在回测框架本身。30天的单品种模拟,第一版代码要跑27分钟。调参痛苦,探索替代方案基本不可能。
两个晚上的性能分析,加上一个针对性改动,同样的回测现在8.9秒跑完。184倍提速,改动却小得近乎尴尬。
![]()
这是关于什么慢、为什么慢,以及"缓存+二分查找"模式如何解决问题的完整复盘。如果你用Python写自己的回测代码,大概率也在桌上留着类似的提速空间。
![]()
策略是Smart Money Reversal风格的入场,带LRB(流动性突破)再入场机制。回测框架是标准的事件驱动循环:对历史数据的每根分钟K线,评估信号条件、管理持仓、检查金字塔再入场、更新盈亏。数据量大约每天7000根分钟K线,30天约21万根。
21万根K线跑27分钟,每秒130根——对Python里一个紧凑的数值循环来说,这速度慢得可笑。即便算上pandas开销,也该快10倍。该上性能分析了。
cProfile的结果很清晰。累计时间最高的函数不是策略评估器,也不是订单管理器,而是pandas.tslib.tz_convert——在K线迭代器里被调用。具体代码是每根K线都把时间戳转成纽约时区,再判断是否在开市时段内。pandas的时间戳转换不便宜:要查tzdata、算夏令时偏移、分配新的Timestamp对象。单次调用微秒级,没问题;21万次调用,回测还没进自己的代码,就先花八九分钟卡在pandas的内部C扩展里。
![]()
第二慢的是一个二分查找,被我 naive 地写成了线性扫描的"开市时段边界"有序列表,每次模拟吃掉四分钟。第三是不必要的DataFrame切片,用df.loc[prev_ts:ts]找前N根K线,也在做线性索引查找。
三个独立问题,根源同一个错误:该在开头一次性做的事,放进了热循环里。
第一部分修复:时区缓存。不再每根K线现场转换,而是在加载历史数据时预计算好纽约本地时间的单列,热循环里彻底砍掉转换操作。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.