3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化交易中,策略在回测(Backtest)和模拟交易(Paper Trading)中表现不一致是一个非常常见且重要的问题。这通常不是由单一原因造成的,而是数据环境、代码逻辑、撮合机制等多方面因素共同作用的结果。
以下是导致回测与模拟交易结果出现偏差的主要原因及详细解析:
这是导致回测表现优异但模拟盘亏损的最常见原因。
before_trading_start 中使用当天的 close 价格进行选股。如果策略逻辑中包含不确定的随机因素,每次运行的结果都会不同。
dict(字典)和 set(集合)在迭代时顺序是不固定的(尤其是在不同 Python 版本或解释器重启后)。如果策略逻辑是“取股票池中的前5只买入”,而股票池存储在 set 中,回测和模拟盘选出的股票可能完全不同。random 库生成随机数,且没有固定随机种子(seed)。回测是基于历史数据的理论模拟,而模拟交易更接近真实市场环境。
match_with_order_book),系统会根据买一/卖一价和盘口挂单量进行撮合。如果对手盘不足,可能无法成交或部分成交。set_option('use_real_price', True)(真实价格模式)。如果关闭此选项,回测使用的是基于回测结束日期的前复权数据,这会导致历史价格与当时真实价格不符,计算买入股数时产生偏差。g 全局变量和 context,如果代码中有无法被序列化保存的对象(如数据库连接、打开的文件句柄),重启后会丢失或报错,而回测不会经历重启。skip_paused=True),导致回测中买入了停牌股(回测引擎可能允许以停牌前价格买入,或者一直持有不动)。initialize 中必须调用 set_option('use_real_price', True)。list(set(stocks)) 或 dict.keys() 的结果进行 .sort() 排序,确保顺序固定。random 模块,或在使用前设定固定的 random.seed()。set_option("avoid_future_data", True),让系统自动检测并报错常见的未来数据引用。log.info。对比回测日志和模拟交易日志,定位第一处出现差异的地方。Q1: 为什么我的策略在回测中收益很高,一上模拟盘就不交易或亏损?
A: 最可能的原因是使用了未来函数。例如在 before_trading_start 中获取了当天的 close 价格来判断涨跌,这在回测中能拿到数据,但在模拟盘实盘时刻,当天的收盘价还未产生,导致信号无法触发或触发错误。
Q2: 为什么使用字典(Dict)存储股票会导致结果不一致?
A: 在 Python 中,字典和集合是无序的(尤其是在 Python 3.6 之前,虽然后续版本优化了顺序,但仍不建议依赖其顺序)。如果策略逻辑是 for stock in g.security_dict: 然后买入前3只,每次运行遍历的顺序可能不同,导致买入的股票不同。建议先将键值转为列表并排序:for stock in sorted(g.security_dict.keys()):。
Q3: 开启“盘口撮合”对模拟交易有什么影响?
A: 开启 set_option('match_with_order_book', True) 后,模拟交易会更严格地模拟真实市场的流动性。如果您的策略资金量较大或交易不活跃的标的,可能会因为盘口挂单不足而无法成交,或者成交价格比回测(通常假设无限流动性)更差,导致收益低于回测。
Q4: 模拟交易中途修改代码会影响结果吗?
A: 会。回测是基于同一套代码逻辑从头跑到尾。模拟交易中途修改代码后,策略的逻辑变了,但持仓和资金状态是继承自旧代码的,这种逻辑断层会导致结果与静态回测完全不同。建议修改代码后,重新建立一个新的回测和模拟交易进行对比。