3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个非常经典且普遍的量化交易问题。策略回测表现优异(高收益、低回撤),但实盘交易却大相径庭,这种现象通常被称为**“回测失真”**。
造成这种情况的原因主要可以归纳为三大类:代码逻辑错误(未来函数)、模型过度拟合、以及环境与交易摩擦的差异。
以下是基于量化交易原理及 QMT 平台特性的详细分析:
这是最常见导致回测虚假繁荣的原因。策略在计算信号时,使用了当时实际上无法获取的数据。
close(收盘价)来决定是否在当天买入,这就是未来函数。因为在盘中交易时,收盘价还没有产生。high 或 low 来触发止盈止损,回测引擎通常会假设你能以该价格成交,但实盘中你可能根本无法在该价格触达的瞬间成交。QMT 的 handlebar 机制在实盘和回测中略有不同,处理不当会导致信号消失。
handlebar 会随每一个 Tick(分笔数据)驱动运行。如果你的策略逻辑是“股价 > 均线则买入”,盘中某一瞬间股价冲高触发买入,但收盘时股价回落,信号消失。回测通常是基于已完成的 K 线(Bar)计算的,不会记录这种盘中的“虚假信号”,而实盘中你可能已经成交了,导致实盘亏损但回测中没有这笔交易。ContextInfo.is_last_bar() 判定是否为 K 线结束时刻。passorder 函数中的 quickTrade 参数设置。如果设置为 1(立即下单),容易出现信号闪烁问题;设置为 0 通常更稳健(等待 K 线走完)。策略是为了迎合历史数据而“硬凑”出来的。
MA(23) 和 RSI(14) 在过去两年效果极好,但换成 MA(24) 效果就崩塌。这说明策略没有逻辑支撑,只是恰好撞上了历史数据的噪声。回测环境过于理想化,忽略了真实交易的成本。
ContextInfo.get_market_data_ex 等规范接口。passorder 的 quickTrade 参数是否符合你的预期。ContextInfo.is_new_bar() 或 ContextInfo.is_last_bar()。Q: 什么是 QMT 中的“未来函数”?
A: 在 QMT 中,如果在计算当前 K 线(Bar)的指标时,引用了该 K 线尚未走完时的数据(如在盘中就确信当天的收盘价是 X),或者引用了当时尚未发布的财务数据,即为未来函数。
Q: 如何在 QMT 回测中设置滑点以模拟真实情况?
A: 可以使用 ContextInfo.set_slippage(type, value) 接口。例如 ContextInfo.set_slippage(1, 0.02) 表示按固定值 0.02 元设置滑点,或者在策略编辑器的“回测参数”面板中直接设置。
Q: 为什么我的策略在 QMT 模拟盘中有信号,但没有委托?
A: 这通常不是回测失真,而是代码逻辑问题。请检查:1. 资金是否充足;2. 是否处于非交易时间;3. passorder 函数的参数是否正确(如账号ID、操作类型);4. 是否触发了风控限制。
Q: 如何避免信号闪烁?
A: 最稳健的方法是使用“走完 K 线”模式。在 Python 代码中,可以通过判断 ContextInfo.is_last_bar() 是否为 True 且当前时间接近收盘,或者在 handlebar 中计算信号,但使用 do_order 在下一根 K 线的起始时刻进行下单。