🚀 AI 一键生成 qmt 策略代码

QMT 策略可视化:如何使用 paint 函数绘制包含多条曲线的自定义指标?

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

问题描述

如何在策略的回测图表中画出我自己的技术指标,并且这个指标包含快线和慢线两条曲线?

解决方案

在 QMT 平台中,要在回测图表上绘制自定义技术指标(如快线和慢线),主要使用 ContextInfo.paint() 函数。

该函数可以在每一根 K 线(Bar)上绘制数值,从而连接成曲线。

核心步骤

  1. 获取数据:在 handlebar 函数中,使用 ContextInfo.get_market_data_ex() 获取当前 K 线及之前的历史收盘价。
  2. 计算指标:根据获取的数据计算快线(例如 5 日均线)和慢线(例如 10 日均线)的数值。
  3. 绘制曲线:调用 ContextInfo.paint() 将计算出的数值输出到图表上。

代码实现

以下是一个完整的策略示例代码。该策略会在主图上绘制一条 5周期快线(红色) 和一条 10周期慢线(绿色)

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

def init(ContextInfo):
    """
    初始化函数
    """
    # 定义快线和慢线的周期
    ContextInfo.fast_period = 5
    ContextInfo.slow_period = 10
    
    print("策略初始化完成,准备绘制双均线指标")

def handlebar(ContextInfo):
    """
    K线逐根运行函数
    """
    # 获取当前主图的品种代码
    stock_code = ContextInfo.stockcode
    
    # 获取当前 K 线的时间戳(毫秒)
    current_timetag = ContextInfo.get_bar_timetag(ContextInfo.barpos)
    
    # 将时间戳转换为字符串格式,用于获取数据
    # 注意:get_market_data_ex 的 end_time 需要字符串格式
    end_time_str = timetag_to_datetime(current_timetag, '%Y%m%d%H%M%S')
    
    # 获取历史数据
    # 我们需要获取足够的数据来计算慢线,这里多取一点作为缓冲
    count = ContextInfo.slow_period + 5
    
    # 使用 get_market_data_ex 获取数据
    # 注意:period='follow' 跟随主图周期,dividend_type='follow' 跟随主图复权
    data_map = ContextInfo.get_market_data_ex(
        ['close'], 
        [stock_code], 
        period='follow', 
        end_time=end_time_str, 
        count=count, 
        dividend_type='follow', 
        fill_data=False, 
        subscribe=True
    )
    
    # 检查数据是否获取成功
    if stock_code in data_map:
        df = data_map[stock_code]
        
        # 确保数据长度足够计算慢线
        if len(df) >= ContextInfo.slow_period:
            # 计算快线 (例如 MA5)
            # 取最后 fast_period 行的收盘价求平均
            fast_value = df['close'].iloc[-ContextInfo.fast_period:].mean()
            
            # 计算慢线 (例如 MA10)
            # 取最后 slow_period 行的收盘价求平均
            slow_value = df['close'].iloc[-ContextInfo.slow_period:].mean()
            
            # --- 绘图部分 ---
            
            # 绘制快线
            # 参数说明: 
            # 1. 指标名称 (显示在图例中)
            # 2. 数值
            # 3. 索引位置 (-1 表示当前 Bar)
            # 4. 线型 (0 表示曲线)
            # 5. 颜色 ('red')
            ContextInfo.paint("快线_MA5", fast_value, -1, 0, 'red')
            
            # 绘制慢线
            ContextInfo.paint("慢线_MA10", slow_value, -1, 0, 'green')

            # 可以在这里添加简单的交易逻辑演示(可选)
            # if fast_value > slow_value:
            #     ContextInfo.paint("多头排列", 1, -1, 0, 'nodraw') # 仅在左上角显示数值不画线

函数详解:ContextInfo.paint

ContextInfo.paint(name, value, index, line_style, color, limit)

  • name (string): 指标名称,会显示在图表的左上角数据区。
  • value (number): 当前 K 线对应的指标数值。
  • index (number): 绘制的位置索引。通常填 -1,表示在当前运行到的 K 线位置(ContextInfo.barpos)进行绘制。
  • line_style (number): 线型。
    • 0: 曲线(最常用,连接各个点)。
    • 42: 柱状线(类似成交量柱)。
  • color (string): 颜色。支持 'red', 'blue', 'green', 'yellow', 'white', 'cyan', 'magenta', 'brown'
  • limit (string, 可选): 控制参数。
    • 'noaxis': 画线但不影响坐标轴缩放(例如在主图画一个很小的值,不让K线被压缩)。
    • 'nodraw': 不在图上画线,只在左上角显示数值。

注意事项

  1. 主图与副图
    • 如果你的指标数值是价格相关的(如均线、布林带),直接运行即可,它会默认叠加在主图 K 线上。
    • 如果你的指标是震荡指标(如 MACD、RSI,数值范围 0-100 或围绕 0 轴),在策略编辑器中,请将策略的**“显示位置”设置为“副图”**,否则会压缩主图 K 线的显示比例。
  2. 运行模式:该绘图函数在“回测模式”和“实盘/模拟运行模式”下均有效。
  3. 性能paint 函数在每一根 K 线都会被调用。在编写复杂逻辑时,请确保计算过程高效,避免拖慢回测速度。

Q&A

Q: 如何让两条线显示在副图(Sub-chart)而不是主图上?
A: 代码本身不需要修改。在 QMT 的【策略编辑器】界面右侧的【基本信息】栏中,找到【位置】选项,将其从“主图”或“主图叠加”修改为**“副图”**。保存并运行后,指标就会显示在 K 线图下方的独立区域。

Q: 我可以画柱状图吗?比如 MACD 的红绿柱?
A: 可以。将 ContextInfo.paint 的第 4 个参数 line_style 设置为 42 即可绘制柱状线。

Q: 为什么我的线画出来是断断续续的?
A: 确保 handlebar 在每一根 K 线都计算并调用了 paint。如果只在特定条件下(如 if condition: 内部)调用 paint,那么不满足条件时就不会有点,导致线条中断。必须保证每根 Bar 都有返回值。