🚀 AI 一键生成 qmt 策略代码

QMT 进阶教程:如何在 Python 策略中调用界面定义的扩展数据?

qmt | 发布时间: 2025/12/20
以下内容由 EasyQuant 生成。

问题描述

如何在 Python 代码里引用界面上做好的扩展数据?

解决方案

在 QMT (Quantitative Trading Platform) 中,引用界面上已经制作好的扩展数据(通常是用户自定义的指标或外部导入的数据),主要使用 API 提供的引用函数。

最常用的函数是 ext_data(获取单点数据)和 ext_data_range(获取区间数据)。

以下是详细的操作步骤和代码示例。

核心函数说明

1. 获取特定时刻的扩展数据:ext_data

该函数通常用于 handlebar 中,获取当前 K 线对应的扩展数据值。

  • 语法: ext_data(extdataname, stockcode, deviation, ContextInfo)
  • 参数:
    • extdataname: 字符串,界面上定义的扩展数据名称(必须完全一致)。
    • stockcode: 字符串,股票代码(如 '600000.SH')。
    • deviation: 数字,K 线偏移量。0 表示当前 K 线,-1 表示前一根 K 线。
    • ContextInfo: 策略上下文对象。
  • 返回: 数字(指标值)。

2. 获取一段时间的扩展数据:ext_data_range

该函数用于获取指定时间段内的扩展数据序列。

  • 语法: ext_data_range(extdataname, stockcode, begintime, endtime, ContextInfo)
  • 参数:
    • begintime/endtime: 字符串,格式如 '20230101' 或 '20230101093000'。
  • 返回: 字典 (Dict),时间戳为 Key,数值为 Value。

3. 获取全量扩展数据(高效):ContextInfo.get_ext_all_data

建议在 init 中调用,一次性加载数据,效率最高。

  • 语法: ContextInfo.get_ext_all_data(extdataname, start_time, end_time)
  • 返回: Pandas Panel 对象(包含值和排名)。

完整代码示例

假设你在 QMT 界面上已经创建了一个名为 "MyIndicator" 的扩展数据。

# -*- coding: gbk -*-

def init(ContextInfo):
    # 设置股票池
    ContextInfo.set_universe(['600000.SH', '000001.SZ'])
    
    # 方法3:在初始化时一次性获取所有扩展数据(推荐用于回测或需要大量数据时)
    # 注意:extdataname 必须与界面上建立的扩展数据名称完全一致
    try:
        # 获取从 20220101 到 20230101 的数据
        ContextInfo.all_ext_data = ContextInfo.get_ext_all_data(
            'MyIndicator', 
            '20220101', 
            '20230101'
        )
        print("批量加载扩展数据成功")
    except Exception as e:
        print("批量加载扩展数据失败:", e)

def handlebar(ContextInfo):
    # 获取当前处理的股票代码
    stock_code = ContextInfo.stockcode
    
    # --- 方法1:获取当前 K 线的扩展数据值 ---
    # 0 表示当前 K 线,如果需要前一根 K 线的数据,可以使用 -1
    current_val = ext_data('MyIndicator', stock_code, 0, ContextInfo)
    
    # 获取前一根 K 线的值
    prev_val = ext_data('MyIndicator', stock_code, -1, ContextInfo)
    
    print(f"代码: {stock_code}, 当前扩展数据值: {current_val}, 前一根值: {prev_val}")
    
    # --- 方法2:获取指定时间段的扩展数据 ---
    # 仅在最后一根 K 线时打印,避免日志过多
    if ContextInfo.is_last_bar():
        start_t = '20230101'
        end_t = '20230201'
        range_data = ext_data_range('MyIndicator', stock_code, start_t, end_t, ContextInfo)
        print(f"区间数据示例 ({stock_code}):", range_data)

    # 简单的交易逻辑示例:如果当前扩展数据值大于 10 则买入
    if current_val > 10:
        print(f"{stock_code} 触发买入信号,指标值: {current_val}")
        # order_shares(stock_code, 100, ContextInfo, 'account_id') 

注意事项

  1. 名称匹配:代码中的 extdataname 必须与 QMT 客户端【数据管理】->【扩展数据】列表中显示的名称完全一致(区分大小写)。
  2. 数据计算:在引用之前,请确保在界面上已经对该扩展数据进行了刷新计算,否则可能获取不到数据或获取到空值。
  3. 周期一致性:扩展数据在生成时有固定的周期(如日线、分钟线)。在策略中引用时,最好确保策略运行周期与扩展数据周期逻辑上是匹配的,或者理解偏移量 deviation 在不同周期下的含义。
  4. 性能优化:如果在 handlebar 中频繁调用 ext_data 可能会影响回测速度。对于大规模计算,建议使用 ContextInfo.get_ext_all_datainit 中预加载。

Q&A

Q: 为什么调用 ext_data 返回的值是 NaN 或 0?
A: 这通常有几个原因:

  1. 扩展数据名称写错了。
  2. 界面上没有对该扩展数据进行“刷新计算”,导致本地没有数据文件。
  3. 策略运行的时间段内,该扩展数据本身就没有值(例如停牌或数据源缺失)。

Q: ext_data 中的 deviation 参数 -1 代表什么?
A: deviation 代表 K 线的偏移量。0 代表当前正在计算的这根 K 线,-1 代表当前 K 线左边的一根(即上一周期),1 代表向右偏移(通常用于未来函数,实盘中不可用)。

Q: 扩展数据可以引用 Python 计算的结果吗?
A: QMT 的扩展数据主要是基于界面上的公式(类似通达信公式)生成的。如果你需要引用 Python 计算的复杂数据,建议直接在 Python 策略代码中计算,或者将 Python 计算结果保存为本地文件(如 CSV),然后在策略中读取 CSV,而不是通过“扩展数据”接口。

Q: get_ext_all_data 返回的数据结构是什么?
A: 它返回一个 pandas.Panel 对象(在旧版 pandas 中)或类似的多维结构。Items 轴通常是时间戳,Major_axis 是股票代码,Minor_axis 是数据域(通常包含 'value' 和 'rank')。具体使用时建议先 print 出来查看结构。