问题描述
ETF 是 T+0, 回测的时候, 为什么还是按 T+1, 当天买的, 不能卖?
解决方案
在 QMT 平台中进行历史回测时,遇到 ETF 品种被当作 T+1 处理(当天买入无法当天卖出)是一个常见的问题。以下是产生该问题的原因以及相应的解决思路。
一、 问题原因解析
QMT 的历史回测引擎在底层设计时,为了统一处理 A 股市场的回测逻辑,默认将所有股票市场(沪深交易所)的现货品种(包括 A 股股票、ETF 基金、LOF 基金等)的交易规则设定为 T+1。
这意味着在回测模式下,系统会在每日收盘后才将当天买入的持仓结转为“可用持仓”。因此,当你在盘中尝试卖出当天买入的 ETF 时,回测引擎会因为“可用持仓不足”而拒绝该笔卖出委托。
二、 解决方法与替代方案
由于这是回测引擎底层的默认规则限制,目前无法直接通过一个简单的参数开关将其切换为 T+0。但你可以通过以下几种方案来解决或绕过这个问题:
方案一:使用“运行”模式(模拟盘/实盘)进行测试(推荐)
QMT 的运行模式(模拟交易或实盘交易)与历史回测模式不同。运行模式直接连接券商的模拟柜台或真实交易柜台。真实的交易柜台能够正确识别 ETF 品种的属性,并严格按照交易所的 T+0 规则处理可用持仓。
- 操作方法:将策略的运行模式切换为“运行”(模拟盘),在盘中实时接收行情进行测试。此时当天买入的 ETF 会立即增加可用持仓,支持当天卖出。
方案二:在代码层面自行维护虚拟持仓(适用于必须进行历史回测的场景)
如果你必须进行长期的历史数据回测来验证 T+0 策略的收益率,可以通过在 Python 代码中自行维护一个“虚拟可用持仓”变量,并使用不校验底层可用持仓的下单方式(或忽略系统的废单报错,自行计算收益)。
注意:QMT 的 passorder 函数在回测时如果可用持仓不足会直接拦截。要实现完全的自定义 T+0 回测,通常需要自己编写一个简单的撮合逻辑来记录买卖点和计算净值,而不是依赖 QMT 自带的回测绩效分析面板。
方案三:利用期货品种替代测试逻辑
如果你的策略逻辑主要依赖于指数的波动(例如沪深300、中证500),且只是想验证 T+0 策略的有效性,可以考虑在回测时将标的替换为对应的股指期货(如 IF、IC)。
- 原因:QMT 的回测引擎对期货品种(如
IF.IF)原生支持 T+0 交易(平今仓)。 - 操作方法:将策略中的 ETF 代码(如
510300.SH)临时替换为对应的股指期货主力合约,验证策略的买卖点和逻辑是否正确。
三、 总结
- 历史回测模式:受限于引擎底层规则,A 股市场品种(含 ETF)默认 T+1。
- 模拟/实盘运行模式:由真实柜台处理,完美支持 ETF 的 T+0 交易。
建议在开发 ETF T+0 策略时,先用历史数据验证买卖信号的准确性(忽略无法卖出的报错或自行写代码统计收益),确认信号无误后,直接放入模拟盘中运行几天,以检验真实的 T+0 交易效果。