🚀 AI 一键生成 qmt 策略代码

QMT 长线策略:如何构建基于历史市盈率通道 (PE Band) 的买卖模型?

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

问题描述

如何在 QMT 中画 PE Band 市盈率通道?

解决方案

在 QMT 中绘制 PE Band(市盈率通道)的核心逻辑是利用历史的 每股收益(EPS) 乘以设定的 PE 倍数(如 20倍、30倍),从而计算出对应的理论股价并绘制成线。

为了获得平滑且准确的曲线,建议使用 EPS (TTM)(滚动12个月每股收益)数据。QMT 的多因子库中直接提供了 Per_Share_Analysis.EPSTTM 因子,这是实现该功能最简便的方法。

实现步骤

  1. 初始化 (init):设定需要绘制的 PE 倍数列表(如 20, 30, 40)。
  2. 处理 K 线 (handlebar)
    • 获取当前 K 线的时间。
    • 调用 get_factor_data 获取当天的 EPSTTM 数据。
    • 计算 理论股价 = EPSTTM * PE倍数
    • 使用 paint 函数将计算结果绘制在主图上。

策略代码

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

def init(ContextInfo):
    # 1. 设置要绘制的 PE 倍数,例如 20倍, 30倍, 40倍
    ContextInfo.pe_levels = [20, 30, 40]
    
    # 2. 设置对应的线条颜色
    ContextInfo.colors = ['green', 'yellow', 'red']
    
    # 3. 设置因子名称:每股收益TTM
    # 因子库表名: Per_Share_Analysis, 字段名: EPSTTM
    ContextInfo.factor_name = 'Per_Share_Analysis.EPSTTM'

def handlebar(ContextInfo):
    # 获取当前 K 线的位置索引
    index = ContextInfo.barpos
    
    # 获取当前 K 线的时间戳
    timetag = ContextInfo.get_bar_timetag(index)
    
    # 将时间戳转换为 YYYYMMDD 格式的字符串,用于获取因子数据
    date_str = timetag_to_datetime(timetag, '%Y%m%d')
    
    # 获取当前主图的股票代码 (格式如 600000.SH)
    stock_code = ContextInfo.stockcode + '.' + ContextInfo.market
    
    # --- 获取因子数据 ---
    # 注意:get_factor_data 返回的是 pandas 数据结构
    try:
        factor_data = ContextInfo.get_factor_data(
            [ContextInfo.factor_name], 
            stock_code, 
            date_str, 
            date_str
        )
    except Exception as e:
        # 如果获取数据出错(如未下载数据),直接返回
        return

    # --- 数据解析 ---
    eps_ttm = None
    
    if factor_data is None or factor_data.empty:
        return

    # 根据返回的数据类型提取 EPS 值
    # 情况1: 返回 Series (单股单日通常返回此格式)
    if isinstance(factor_data, pd.Series):
        eps_ttm = factor_data.get(ContextInfo.factor_name)
    # 情况2: 返回 DataFrame (时间序列)
    elif isinstance(factor_data, pd.DataFrame):
        if ContextInfo.factor_name in factor_data.columns:
            eps_ttm = factor_data[ContextInfo.factor_name].iloc[0]
    
    # 如果 EPS 无效(如 NaN),则不绘制
    if eps_ttm is None or pd.isna(eps_ttm):
        return

    # --- 绘制 PE Band ---
    for i, pe in enumerate(ContextInfo.pe_levels):
        # 计算理论股价 = EPS(TTM) * PE倍数
        theoretical_price = eps_ttm * pe
        
        # 定义线条名称
        line_name = 'PE_{}X'.format(pe)
        
        # 获取颜色,循环使用
        color = ContextInfo.colors[i % len(ContextInfo.colors)]
        
        # 调用 paint 在主图绘制
        # 参数说明: paint(指标名, 数值, 索引(-1为当前), 线型(0为曲线), 颜色, 限制('noaxis'表示不影响坐标轴缩放))
        ContextInfo.paint(line_name, theoretical_price, -1, 0, color, 'noaxis')

注意事项与数据补充

  1. 数据下载(非常重要)
    该代码使用了 多因子数据 (get_factor_data)。在运行策略之前,您必须确保本地有相应的数据。

    • 请在 QMT 客户端顶部菜单点击 【数据管理】 -> 【数据下载】 -> 选择 【多因子数据】
    • 勾选您需要的时间段和股票池,点击下载。如果没有下载该数据,策略将画不出线。
  2. 运行模式

    • 该策略适合在 【模型研究】 的回测模式或 【模型交易】 的主图显示中使用。
    • 在主图叠加运行时,请确保选择的是日线或以上周期,因为财务因子数据通常是按日更新的。
  3. 负值处理

    • 如果公司亏损(EPS 为负),计算出的 PE Band 价格也会是负数,在 K 线图上会显示在 0 轴下方。这是正常的数学计算结果。

Q&A

Q: 为什么画出来的线是直的或者断断续续的?
A: 这通常是因为缺少历史因子数据。请按照上述“数据下载”步骤补充完整的历史多因子数据。

Q: 我可以使用静态 PE 而不是 TTM 吗?
A: 可以。如果想用静态 PE(基于上年度年报),可以将代码中的 Per_Share_Analysis.EPSTTM 替换为 Per_Share_Analysis.EPS。但通常 PE Band 使用 TTM 数据更能反映最新的估值水平。

Q: 如何修改线条颜色?
A: 修改 init 函数中的 ContextInfo.colors 列表即可,支持 'red', 'blue', 'green', 'yellow', 'white', 'magenta', 'cyan' 等颜色。