3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化交易中,策略回测收益非常漂亮,但实盘交易却表现平平甚至亏损,这种现象被称为“回测与实盘的偏差”。在 QMT 平台上,造成这种差异的原因通常可以归纳为运行机制差异、未来函数的使用、交易成本与滑点以及市场环境变化四个方面。
以下是详细的深度解析:
QMT 的回测模式(Backtest)和实盘/模拟运行模式(Run/Live)在底层驱动机制上存在本质区别,这是导致结果不一致的最常见技术原因。
handlebar 函数的调用频率handlebar 每天只被调用一次(通常被视为收盘后或收盘前的一瞬间)。handlebar 就会被调用一次。
ContextInfo.is_last_bar() 判断),实盘中可能会在盘中因为价格波动多次触发信号,导致频繁开平仓,而回测中无法体现这种盘中波动。passorder 且 quickTrade=0:逻辑与回测一致,当前 K 线走完确认信号,下根 K 线第一笔 Tick 发单。passorder 且 quickTrade=1(立即下单):信号一旦成立立即发出委托。这会导致回测(通常基于收盘价结算)与实盘(基于盘中瞬时价格)产生巨大差异。do_order,它会强制在信号产生的 K 线结束时立即成交(模拟收盘价成交),但在实盘中,如果计算耗时或网络延迟,成交价可能偏离收盘价。这是回测中最致命的错误,指在策略中使用了当时时间点无法获取的数据。
close(收盘价)来决定是否在当天买入。
close 价格是不断跳动的最新价,直到收盘那一刻才确定。实盘中无法以确定的收盘价在盘中成交。ContextInfo.get_market_data_ex 获取历史数据时,不要包含当前正在运行且未结束的 K 线数据用于决策,或者明确逻辑是在 K 线结束时刻才进行判断。回测环境通常是理想化的,而实盘环境是充满摩擦的。
ContextInfo.get_divid_factors),会导致价格信号计算错误。为了让 QMT 的回测结果更具参考价值,建议采取以下措施:
handlebar 中使用 if not ContextInfo.is_last_bar(): return 来确保逻辑只在 K 线结束或最新 Tick 到来时运行。passorder 中的 quickTrade 参数设置,理解其对成交时机的影响。Q: QMT 中 quickTrade=1 和 quickTrade=0 在回测中有什么区别?
A: 在回测模式下,quickTrade 参数通常被忽略或行为不同于实盘。回测主要依据 K 线数据撮合。但在实盘中,quickTrade=1 会在信号触发的瞬间立即下单,而 0 会等到当前 K 线走完、下一根 K 线开始时下单。这是造成差异的主要原因之一。
Q: 为什么我的策略在回测中买入了涨停板的股票,实盘却买不进?
A: 回测系统通常只判断价格是否触及,默认能成交。但实盘中涨停板通常封单巨大,买单排队无法成交。需要在策略中加入逻辑:判断当前价格是否等于涨停价,如果是,则禁止买入。
Q: 如何在 QMT 代码中判断是否是实盘模式?
A: 可以使用 ContextInfo.do_back_test 属性。如果 ContextInfo.do_back_test 为 True,则表示当前处于回测模式;为 False 则表示处于实盘或模拟运行模式。利用此标志可以编写针对不同环境的兼容代码。