3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个非常经典且普遍的量化交易问题。你遇到的情况通常被称为**“过拟合”(Overfitting)或“幸存者偏差”**。在量化领域,回测表现极其优秀但实盘亏损的现象非常常见。
以下是导致这种现象的核心原因分析,以及在 QMT 平台中避免这些问题的具体建议。
这是最常见的原因。当你测试了大量策略或参数组合,并从中选出“效果最好”的一个时,你实际上是在筛选运气,而不是筛选逻辑。
在编写策略代码时,无意中使用了当时那个时间点无法获取的数据。
ContextInfo.get_financial_data 时未正确设置 report_type 或时间参数,容易引入此类偏差。回测环境通常过于理想化,忽略了实际交易中的摩擦成本。
不要用所有历史数据来优化参数。
检查策略对参数变化的敏感程度。
MA(20) 时表现极好,但在 MA(19) 或 MA(21) 时表现极差,说明该策略是“孤岛”策略,不可靠。在 QMT 的策略编辑器或代码中,必须设置严格的费率和滑点。
def init(ContextInfo):
# 设置滑点:例如设置为 0.02 元,或者按比例设置
# 1:固定值,2:比例
ContextInfo.set_slippage(1, 0.02)
# 设置佣金:例如万分之三,最低5元
# [买入印花税, 卖出印花税, 开仓佣金, 平仓佣金, 平今佣金, 最低佣金]
# 注意:股票卖出有印花税(目前0.05%),买入无
ContextInfo.set_commission(0, [0, 0.0005, 0.0003, 0.0003, 0, 5])
report_type 参数。
announce_time(公告日)作为基准,或者在回测逻辑中加入时间滞后。ContextInfo.do_order() 在次日开盘成交,或者在代码逻辑中确保使用的是上一根 K 线的数据来计算信号,并在当前 K 线(或次日)执行。ContextInfo.get_market_data_ex 获取历史数据时,注意 end_time 不要包含未来数据。在实盘投入资金前,先在 QMT 的模拟交易模式下运行一段时间(例如 1-3 个月)。
Q: 如何判断我的策略是否使用了未来函数?
A: 最简单的方法是查看成交明细。如果你的策略在日线回测中,能够以当天的最低价买入,或者在最高价卖出,或者在涨停板打开前买入,这通常意味着使用了未来函数。另外,检查代码中是否使用了类似 close (当根K线收盘价) 来决定当根K线的交易。
Q: QMT回测时,撮合机制是怎样的?
A: QMT 回测通常基于 K 线撮合。如果是日线回测,默认是在信号触发的次日开盘撮合(除非使用了 quickTrade 参数)。如果设置为收盘价成交,而你的信号依赖于收盘价,这就构成了逻辑闭环的未来函数。建议设置为“次日开盘价”撮合,这更符合实际。
Q: 为什么我的策略在小市值股票上回测很好,实盘买不进去?
A: 这是流动性陷阱。回测假设你可以无限量成交。对于小市值或低流动性股票,实盘中你的买单可能会推高价格(冲击成本),或者根本没有足够的卖单(流动性枯竭)。建议在策略中加入流动性过滤,例如剔除日成交额小于 2000 万的股票。
Q: 什么是“参数高原”?
A: 参数高原是指在参数的一定范围内,策略的绩效表现都比较好且稳定。例如,均线策略在 18日、19日、20日、21日、22日均线都能盈利,这就形成了一个高原。如果只有 20日盈利,其他都亏损,那就是“参数尖峰”,这种策略实盘极易失效。