同一份策略、同一段日期,昨天跑出的收益曲线和今天不一样,排查起来很费时间。代码提交记录没有变化,参数也相同,最后才发现行情文件被重新下载过:有几行停牌数据被补齐,结果自然跟着变了。
现在我会在每次回测开始前,给输入数据生成一个“指纹”。它不是用来加密,而是快速回答一个问题:这次运行吃进去的数据,是否和上次完全一致。
做法可以很轻量。先固定排序、列顺序和索引,再对 DataFrame 逐行哈希,最后汇总成一串 SHA-256:
import hashlib
import pandas as pd
def fingerprint(df):
x = df.sort_values(["trade_date", "symbol"])
x = x.reset_index(drop=True)
rows = pd.util.hash_pandas_object(x, index=True)
return hashlib.sha256(rows.values.tobytes()).hexdigest()
pandas 的 hash_pandas_object 会根据数据值生成逐行哈希,也可以把索引纳入计算。外层再用 hashlib 汇总,日志里只需保存一串十六进制结果,不必复制整份行情文件。
不过,直接哈希也有两个容易踩的坑。第一,行顺序、字段顺序和数据类型变化都会让结果变化,所以指纹前必须明确排序和类型转换规则。第二,数据指纹只能说明字节层面是否一致,不能说明数据含义是否一致。如果复权方式、时区或价格单位改了,还要把这些配置一起写进运行清单。
我的回测日志现在固定记录数据指纹、行数、起止日期、字段名、策略参数和代码版本。遇到结果漂移时,先比较这些信息:指纹不同就查数据管道,指纹相同再查随机种子、依赖版本和策略代码。这样能把“为什么变了”从猜测变成可复查的问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。