问题描述
解决方案
在 QMT 中绘制 PE Band(市盈率通道)的核心逻辑是利用历史的 每股收益(EPS) 乘以设定的 PE 倍数(如 20倍、30倍),从而计算出对应的理论股价并绘制成线。
为了获得平滑且准确的曲线,建议使用 EPS (TTM)(滚动12个月每股收益)数据。QMT 的多因子库中直接提供了 Per_Share_Analysis.EPSTTM 因子,这是实现该功能最简便的方法。
实现步骤
- 初始化 (
init):设定需要绘制的 PE 倍数列表(如 20, 30, 40)。 - 处理 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')
注意事项与数据补充
-
数据下载(非常重要):
该代码使用了 多因子数据 (get_factor_data)。在运行策略之前,您必须确保本地有相应的数据。- 请在 QMT 客户端顶部菜单点击 【数据管理】 -> 【数据下载】 -> 选择 【多因子数据】。
- 勾选您需要的时间段和股票池,点击下载。如果没有下载该数据,策略将画不出线。
-
运行模式:
- 该策略适合在 【模型研究】 的回测模式或 【模型交易】 的主图显示中使用。
- 在主图叠加运行时,请确保选择的是日线或以上周期,因为财务因子数据通常是按日更新的。
-
负值处理:
- 如果公司亏损(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' 等颜色。