问题描述
解决方案
根据 QMT 官方文档说明,回测模式和运行模式是 QMT 策略开发中的两种核心状态,它们在数据驱动方式、运行区间、支持品种以及交易执行逻辑上存在显著区别。
以下是详细的对比说明:
1. 核心定义与目的
-
回测模式 (Backtest Mode)
- 定义:以历史行情数据为依据,模拟策略在过去某段时间内的运行情况。
- 目的:验证策略逻辑的有效性,评估策略在历史行情下的表现(如年化收益率、夏普比率、最大回撤等)。
- 资金性质:使用虚拟资金,交易记录仅用于计算回测绩效,不产生任何实际或模拟柜台委托。
-
运行模式 (Run Mode)
- 定义:根据实时行情信号进行运算(也包含主图加载的历史数据),模拟策略在当前市场的运行。
- 目的:进行策略的实时模拟运行,观察实时信号生成情况。
- 资金性质:默认情况下进行模拟信号运算,不进行真实委托。
- 注意:如果需要发送真实的实盘委托,需将策略加载到“模型交易”面板中,并将模式切换为“实盘”。
2. 详细对比表
| 维度 | 回测模式 | 运行模式 |
|---|---|---|
| 数据依据 | 纯历史行情数据(需提前下载补充)。 | 主图历史数据 + 实时推送的 Tick 行情。 |
| 运行区间 | 由“回测参数”中的开始时间和结束时间决定。 | 从主图行情的开始时间一直运行到当前最新时间,并随行情更新持续运行。 |
| 支持品种 | 股票、期货、ETF期权。 | 股票、期货、ETF期权、两融(信用交易)、沪港通、深港通。 |
| API 行为 | ContextInfo.do_back_test 为 True。交易函数仅记录逻辑买卖点。 |
ContextInfo.do_back_test 为 False。handlebar 在最后一根 K 线会随 Tick 变动多次触发(除非代码限制)。 |
| 交易撮合 | 根据设置的滑点和费率进行虚拟撮合。 | 根据实时行情触发信号,若在“模型交易”中挂实盘,则发送真实委托。 |
3. 代码层面的区别 (API)
在编写 Python 策略时,可以通过 API 判断当前处于哪种模式,从而执行不同的逻辑:
-
判断模式:
使用ContextInfo.do_back_test变量。True:当前处于回测模式。False:当前处于运行模式(包含实盘)。
-
运行机制 (Handlebar):
- 回测模式:
handlebar(ContextInfo)函数严格按照 K 线时间序列,每根 K 线调用一次(从过去到现在)。 - 运行模式:
- 历史 K 线部分:每根 K 线调用一次。
- 最新 K 线(实时):每接收到一个新的 Tick(分笔数据),
handlebar就会被调用一次。 - 关键逻辑:在运行模式下,通常需要使用
ContextInfo.is_last_bar()来判断是否为最新 K 线,并结合ContextInfo.is_new_bar()或定时器来控制下单频率,防止在同一根 K 线内因 Tick 跳动重复下单。
- 回测模式:
4. 常见误区
-
误区:点击编辑器上的“运行”按钮就是实盘交易。
- 纠正:编辑器中的“运行”按钮通常仅用于模拟运行(主图信号展示)。要进行实盘交易,必须在 QMT 客户端左侧菜单进入【模型交易】,新建交易模型并关联账号,状态设为“实盘”。
-
误区:回测没问题,实盘就一定没问题。
- 纠正:回测通常基于收盘价或固定滑点,而运行模式(实盘)面临真实的市场流动性、盘口价差、网络延迟和信号闪烁(未来函数)问题。
Q&A
Q: 为什么我在回测模式下无法交易两融(信用)账户?
A: 根据 QMT 文档,回测模式目前仅支持股票、期货、ETF期权三种业务,不支持两融(信用)、沪港通和深港通的回测。如果需要测试两融策略,建议在“运行模式”下进行模拟观察。
Q: 在运行模式下,如何避免 handleBar 在每个 Tick 都触发下单?
A: 在运行模式下,handlebar 会随每个 Tick 触发。为了避免重复下单,通常有以下两种方法:
- 使用
ContextInfo.is_new_bar()判断是否为新 K 线的第一个 Tick,仅在此时下单。 - 在代码中设置全局变量标记当前 K 线是否已交易,或者使用
do_order()函数配合quickTrade=1参数来控制信号触发时机。
Q: 回测时 passorder 函数的 quickTrade 参数有效吗?
A: 无效。文档指出 quickTrade 参数(立即下单)在回测模式时无效。回测通常遵循“见信号,下一根 K 线开盘/收盘成交”的逻辑,或者由 do_order 强制触发。