🚀 AI 一键生成 qmt 策略代码

如何在 QMT 平台中计算并绘制市场腾落指标 (Advance-Decline Line)?

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

问题描述

帮我编写一个计算沪深300指数腾落指标(ADL)的 Python 脚本。

解决方案

这是一个计算沪深300指数腾落指标(ADL)的 QMT Python 策略脚本。

策略说明

腾落指标 (ADL - Advance-Decline Line) 是一种市场广度指标,用于衡量参与市场涨跌的股票数量。

  • 计算公式:$今日ADL = 昨日ADL + (今日上涨家数 - 今日下跌家数)$
  • 逻辑
    1. init 中初始化 ADL 累加器。
    2. handlebar 中,获取当前 K 线时间点的沪深300成分股。
    3. 批量获取这些成分股的行情数据(当前收盘价和前一日收盘价)。
    4. 统计上涨家数和下跌家数,计算净值并累加到 ADL。
    5. 使用 paint 函数在副图绘制曲线。

策略代码

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

def init(ContextInfo):
    """
    初始化函数
    """
    # 定义目标指数代码:沪深300
    ContextInfo.index_code = '000300.SH'
    
    # 初始化 ADL 累积值,从0开始
    ContextInfo.adl_value = 0
    
    # 设置副图显示的指标名称和颜色
    # 注意:paint函数会自动处理绘图,这里主要用于逻辑初始化

def handlebar(ContextInfo):
    """
    K线周期运行函数
    """
    # 获取当前K线的位置
    barpos = ContextInfo.barpos
    
    # 获取当前K线的时间戳(毫秒)
    timetag = ContextInfo.get_bar_timetag(barpos)
    
    # 1. 获取该时间点沪深300的成分股列表
    # 注意:使用 timetag 可以获取历史时刻真实的成分股,避免幸存者偏差
    stock_list = ContextInfo.get_sector(ContextInfo.index_code, timetag)
    
    if not stock_list:
        return

    # 2. 批量获取成分股的行情数据
    # 我们需要比较今日收盘价和昨日收盘价,所以 count=2
    # period='1d' 表示日线,dividend_type='front' 使用前复权价格
    data_map = ContextInfo.get_market_data_ex(
        fields=['close'],
        stock_code=stock_list,
        period='1d',
        count=2,
        dividend_type='front',
        fill_data=True,  # 填充停牌数据
        subscribe=False
    )
    
    up_count = 0   # 上涨家数
    down_count = 0 # 下跌家数
    
    # 3. 遍历所有成分股计算涨跌
    for stock in stock_list:
        if stock in data_map:
            df = data_map[stock]
            
            # 确保有足够的数据进行比较(至少需要两天的数据)
            if len(df) >= 2:
                # 获取今日收盘价和昨日收盘价
                # iloc[-1] 是最新一根K线(当前bar),iloc[-2] 是前一根
                close_today = df.iloc[-1]['close']
                close_prev = df.iloc[-2]['close']
                
                # 判断涨跌
                if close_today > close_prev:
                    up_count += 1
                elif close_today < close_prev:
                    down_count += 1
                # 平盘(close_today == close_prev)不计入
    
    # 4. 计算当期净腾落值
    net_change = up_count - down_count
    
    # 5. 累加到 ADL
    # 注意:如果是第一根K线,ADL就是当天的净值,之后累加
    ContextInfo.adl_value += net_change
    
    # 6. 绘图输出
    # 在副图绘制 ADL 指标线
    ContextInfo.paint('ADL', ContextInfo.adl_value, -1, 0, 'yellow')
    
    # 可选:绘制一条0轴参考线
    ContextInfo.paint('Zero', 0, -1, 0, 'gray', 'noaxis')

使用方法与注意事项

  1. 运行模式

    • 请在 QMT 的 “模型研究”“策略编辑器” 中新建一个 Python 策略。
    • 将上述代码复制进去。
    • 点击 “运行”“回测”
    • 重要:请确保运行周期选择 “日线 (1d)”,因为 ADL 通常是基于日线级别的统计指标。
  2. 数据准备

    • 运行前,请确保已下载 沪深300指数 以及 其成分股 的日线历史数据。
    • 如果数据不全,get_market_data_ex 可能无法获取足够的历史价格,导致计算结果为 0。
  3. 显示位置

    • 在策略编辑器的“基本信息”中,将 “位置” 设置为 “副图”,这样 ADL 曲线会显示在 K 线图的下方。
  4. 逻辑解释

    • ContextInfo.get_sector(..., timetag):这是关键步骤。它确保了在回测历史时间点(比如2020年)时,使用的是当时(2020年)的沪深300成分股,而不是现在的成分股,从而保证了回测的准确性。
    • count=2:我们需要“今天”和“昨天”的数据来判断涨跌,所以一次性取2根K线。

常见问题 (Q&A)

Q: 为什么 ADL 曲线的数值很大或者是负数?
A: ADL 是一个累积指标,其绝对数值的大小取决于计算的起始时间点。绝对值本身没有意义,有意义的是曲线的走势和形态(例如与指数价格的背离)。

Q: 为什么第一根 K 线的 ADL 值不是 0?
A: 脚本逻辑是 ContextInfo.adl_value += net_change。在图表的第一根 K 线,它会计算当天的 (涨-跌),所以值是当天的净变化量,不一定是 0。

Q: 如何计算其他指数(如中证500)的 ADL?
A: 只需将 init 函数中的 ContextInfo.index_code = '000300.SH' 修改为 '000905.SH' (中证500) 或其他指数代码即可。