🚀 AI 一键生成 qmt 策略代码

如何在 QMT 中创建并使用自定义的技术指标?

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

问题描述

我想根据自己的想法创建一个新的技术指标,应该怎么做?

解决方案

在 QMT (Quantitative Trading Platform) 中创建自定义技术指标,本质上是利用 Python 强大的数据处理能力(如 Pandas、Numpy)来编写计算逻辑,并通过 QMT 提供的绘图接口将结果展示在 K 线图上。

以下是创建自定义技术指标的完整步骤和代码示例。

创建自定义指标的核心步骤

  1. 获取数据:在 handlebar 函数中,使用 ContextInfo.get_market_data_ex 获取历史行情数据(如收盘价、成交量等)。
  2. 计算逻辑:利用 Python 的数学库(如 Pandas)根据你的想法编写计算公式。
  3. 绘图输出:使用 ContextInfo.paint() 函数将计算出的数值绘制在图表上。

示例:创建一个“动态波动通道”指标

假设你的想法是创建一个简单的自定义指标:以 20 日均线为中轨,上下各加减 2 倍的 20 日标准差作为通道(类似布林带,但我们手动实现以演示过程)。

完整代码实现

# -*- coding: gbk -*-
import pandas as pd
import numpy as np

def init(ContextInfo):
    # 初始化函数,设置一些常量
    ContextInfo.period = 20      # 均线周期
    ContextInfo.std_dev_mult = 2 # 标准差倍数

def handlebar(ContextInfo):
    # 1. 获取当前主图的品种代码
    stock_code = ContextInfo.stockcode + '.' + ContextInfo.market
    
    # 2. 获取历史数据
    # 获取足够的历史数据以确保计算均线时有值,这里取过去 50 根 K 线
    # 注意:get_market_data_ex 返回的是字典 {code: dataframe}
    data_dict = ContextInfo.get_market_data_ex(
        ['close'], 
        [stock_code], 
        period=ContextInfo.period, 
        count=50, 
        dividend_type=ContextInfo.dividend_type
    )
    
    if stock_code not in data_dict:
        return

    df = data_dict[stock_code]
    
    # 确保数据量足够计算
    if len(df) < ContextInfo.period:
        return

    # 3. 编写自定义计算逻辑 (利用 Pandas)
    # 计算 N 日移动平均线 (中轨)
    df['MA'] = df['close'].rolling(window=ContextInfo.period).mean()
    
    # 计算 N 日标准差
    df['STD'] = df['close'].rolling(window=ContextInfo.period).std()
    
    # 计算上轨和下轨
    df['Upper'] = df['MA'] + (df['STD'] * ContextInfo.std_dev_mult)
    df['Lower'] = df['MA'] - (df['STD'] * ContextInfo.std_dev_mult)

    # 获取当前 K 线对应的计算结果(最新的一行数据)
    # iloc[-1] 代表取最后一行,即当前 bar 的值
    current_ma = df['MA'].iloc[-1]
    current_upper = df['Upper'].iloc[-1]
    current_lower = df['Lower'].iloc[-1]

    # 4. 绘图输出 (Visualization)
    # 参数说明: paint(指标名称, 数值, 位置索引, 线型, 颜色)
    # 位置索引 -1 表示在主图绘制
    
    # 绘制中轨 (黄色)
    ContextInfo.paint('My_MA', current_ma, -1, 0, 'yellow')
    
    # 绘制上轨 (青色)
    ContextInfo.paint('My_Upper', current_upper, -1, 0, 'cyan')
    
    # 绘制下轨 (品红)
    ContextInfo.paint('My_Lower', current_lower, -1, 0, 'magenta')

    # 5. 进阶:在图表上标记信号
    # 例如:当收盘价突破上轨时,在图上写字
    current_close = df['close'].iloc[-1]
    if current_close > current_upper:
        ContextInfo.draw_text(True, current_upper, '突破')

关键函数详解

1. ContextInfo.paint()

这是将你的逻辑可视化的核心函数。

  • 用法ContextInfo.paint(name, value, index, line_style, color, limit)
  • 参数
    • name: 指标名称(显示在左上角)。
    • value: 当前 K 线需要绘制的数值。
    • index: -1 表示画在主图(和 K 线叠加),0 或其他正数表示画在副图(独立窗口)。
    • line_style: 0 为曲线,42 为柱状线。
    • color: 颜色字符串(如 'red', 'green', 'white', 'yellow')。

2. 数据获取与 Pandas

QMT 的 get_market_data_ex 返回的是 Pandas DataFrame 格式,这使得计算非常方便:

  • rolling(window=N).mean():计算移动平均。
  • rolling(window=N).std():计算标准差。
  • 你可以使用任何数学公式,例如 (High + Low + Close) / 3 计算典型价。

如何在 QMT 中运行

  1. 打开 QMT 客户端,进入【模型研究】或【策略编辑器】。
  2. 新建一个 Python 策略
  3. 将上述代码复制粘贴到编辑器中。
  4. 点击工具栏的【运行】或【编译】。
  5. 在行情图上,该策略会根据你的逻辑画出三条线。

常见问题 (Q&A)

Q: 我可以使用第三方库来计算指标吗?
A: 可以。QMT 内置了 talib 库,这是金融领域标准的计算库。例如计算 RSI 可以直接调用 talib.RSI(...),无需自己手写公式。

Q: 如何将指标画在副图(K线图下方)而不是主图上?
A:ContextInfo.paint 函数中,将第三个参数 index 设置为 0(或者不填,默认通常是副图,但建议显式指定)。如果填 -1 则是主图叠加。

Q: 为什么我的指标线是直的或者没有显示?
A: 请检查 get_market_data_ex 中的 count 参数。如果获取的历史数据长度不足以计算指标(例如计算 20 日均线但只获取了 10 根 K 线),结果将是 NaN,导致无法绘图。

Q: 如何只在特定条件下画线?
A: paint 函数在每个 handlebar 周期都会被调用。如果你只想在特定条件下显示,可以结合 ContextInfo.draw_iconContextInfo.draw_text 来标记特定点,而不是画连续的线。对于 paint,如果传入 NaN 值,通常会断开连线。