🚀 AI 一键生成 qmt 策略代码

为什么QMT回测时读取Order对象的证券名称和投资备注为空?

qmt | 发布时间: 2026/5/27
以下内容由 EasyQuant 生成。

问题描述

为什么在回测时,下单成功后,读取order对象部分属性值时,返回是空字符串?

比如如下的代码,回测下单后,可以读取到股票代码,但读取证券名称和投资备注时,返回却是空字符串。

def handlebar(C):

msg = f"投资备注字符串 用来区分不同委托"
passorder(23, 1101, g.account, '600000.SH', 5, -1, 100, '测试下单', 2, msg, C)
passorder(23, 1101, g.account, '600000.SH', 5, -1, 200, '测试下单', 2, msg, C)
orders=get_trade_detail_data(g.account,'STOCK','ORDER')
print('查询委托结果:')
for o in orders:
print(f'股票代码:{o.m_strInstrumentID}',
f'证券名称: {o.m_strInstrumentName}',
f'投资备注: {o.m_strRemark}')

解决方案

在 QMT 平台中,出现回测时 Order 对象的 m_strInstrumentName(证券名称)和 m_strRemark(投资备注)为空字符串的现象,是由 QMT 的底层回测机制 决定的。

核心原因分析

  1. 回测引擎的性能优化:在回测模式下,QMT 使用的是本地的虚拟撮合引擎。为了极大提升历史数据的回测速度并降低内存消耗,虚拟撮合引擎只记录计算策略净值、盈亏所必需的核心字段(如:证券代码 m_strInstrumentID、委托价格、委托数量、买卖方向、成交状态等)。
  2. 非核心字段被忽略:像 m_strInstrumentName(中文名称)和 m_strRemark(投资备注)这类描述性、非计算性的字段,在回测的虚拟订单生成时会被省略,因此读取时返回的是空字符串。
  3. 实盘与回测的差异:如果您将策略切换到实盘模式模拟交易模式(连接了真实的交易柜台或模拟柜台),柜台在接收到 passorder 传过去的 userOrderId(即投资备注)后,会完整地生成包含名称和备注的委托回报,此时您再调用 get_trade_detail_data 就能正常读取到这些字段了。

回测中的替代解决方案

既然回测引擎不保存这些字段,我们可以通过 Python 代码在策略层面自行维护和获取这些信息:

1. 获取证券名称

不要依赖 Order 对象自带的名称属性,而是直接使用 QMT 提供的 API ContextInfo.get_stock_name() 动态获取:

stock_code = o.m_strInstrumentID
stock_name = ContextInfo.get_stock_name(stock_code)

2. 记录和区分投资备注

如果您的策略强依赖“投资备注”来区分不同的委托逻辑,可以在 ContextInfo 中维护一个全局字典,利用委托号 (m_strOrderSysID)代码+时间 作为映射的 Key,自行记录备注信息。

改进后的代码示例:

def init(C):
    # 初始化一个字典,用于在回测中记录自定义备注
    C.my_order_remarks = {}

def handlebar(C):
    msg1 = "测试下单_100股"
    msg2 = "测试下单_200股"
    
    # 下单
    passorder(23, 1101, g.account, '600000.SH', 5, -1, 100, '测试下单', 2, msg1, C)
    # 获取最新委托号并记录备注
    order_id_1 = get_last_order_id(g.account, 'STOCK', 'ORDER')
    if order_id_1 != '-1':
        C.my_order_remarks[order_id_1] = msg1
        
    passorder(23, 1101, g.account, '600000.SH', 5, -1, 200, '测试下单', 2, msg2, C)
    order_id_2 = get_last_order_id(g.account, 'STOCK', 'ORDER')
    if order_id_2 != '-1':
        C.my_order_remarks[order_id_2] = msg2

    # 查询委托结果
    orders = get_trade_detail_data(g.account, 'STOCK', 'ORDER')
    print('查询委托结果:')
    for o in orders:
        stock_code = o.m_strInstrumentID
        # 替代方案 1:动态获取股票名称
        stock_name = C.get_stock_name(stock_code)
        
        # 替代方案 2:从自定义字典中获取备注,实盘中可以直接用 o.m_strRemark
        remark = C.my_order_remarks.get(o.m_strOrderSysID, o.m_strRemark)
        
        print(f'委托号:{o.m_strOrderSysID}',
              f'股票代码:{stock_code}',
              f'证券名称:{stock_name}',
              f'投资备注:{remark}')

总结

  • 回测时m_strInstrumentNamem_strRemark 为空是正常现象(引擎优化所致)。
  • 实盘/模拟时:这两个字段会有正常的值。
  • 建议:在编写兼容回测和实盘的策略时,尽量使用 ContextInfo.get_stock_name() 获取名称,并通过全局变量辅助记录回测时的订单状态。