🚀 AI 一键生成 qmt 策略代码
立即体验

qmt 平台如何编写多因子打分选股策略?(成长+估值因子实战)

qmt | 发布时间: 2026/7/30
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: qmt 选股策略:结合成长因子与估值因子的打分模型

Question: 如何在 qmt 中使用 get_factor_data 构建多因子综合打分选股策略?

解决方案

qmt 选股策略:结合成长因子与估值因子的打分模型

在量化投资中,多因子综合打分模型是一种经典的选股方法。通过组合不同维度的因子(如成长能力因子与估值因子),可以有效兼顾公司的成长性与估值安全边际。本文将介绍如何在 QMT 平台中使用 ContextInfo.get_factor_data() 接口获取因子数据,并构建一个多因子打分选股策略。


1. 策略核心逻辑

  1. 定义股票池与因子
    • 估值因子:市盈率 Valuation_and_Market_Cap.PE(指标越低得分越高)。
    • 成长因子:净利润增长率 Growth.NetProfitGrowRate(指标越高得分越高)。
  2. 因子数据获取
    • 在每日/每月定时任务中,通过 get_factor_data 批量获取股票池中最新交易日的因子数据。
  3. 标准化与综合打分
    • 对因子进行排序打分(Ranking)或 Z-Score 标准化。
    • 综合得分 = $0.5 \times \text{估值得分} + 0.5 \times \text{成长得分}$。
  4. 调仓执行
    • 选取综合得分最高的前 N 只股票(如前 5 只),使用 passorder 进行目标持仓调整。

2. QMT 完整 Python 策略源码

#encoding:gbk
import pandas as pd
import numpy as np

def init(ContextInfo):
    # 1. 设置股票池(以沪深300成份股或指定股票池为例)
    ContextInfo.stock_pool = ['600000.SH', '000001.SZ', '000002.SZ', '600519.SH', '002415.SZ']
    ContextInfo.set_universe(ContextInfo.stock_pool)
    
    # 2. 账号与运行设置
    ContextInfo.account = '6000000248'
    ContextInfo.set_account(ContextInfo.account)
    ContextInfo.hold_count = 3  # 目标持仓股票数
    
    # 3. 设置定时器:每月或每周执行一次多因子选股(此处演示每日10点运行)
    ContextInfo.run_time("factor_selection_logic", "1nDay", "2023-01-01 10:00:00", "SH")

def factor_selection_logic(ContextInfo):
    print("=== 开始执行多因子打分选股 ===")
    stock_list = ContextInfo.stock_pool
    
    # 1. 确定数据获取的时间范围(当前交易日)
    bar_date = timetag_to_datetime(ContextInfo.get_bar_timetag(ContextInfo.barpos), '%Y%m%d')
    if not bar_date:
        bar_date = '20230501'  # 默认回测/运行日期
        
    # 2. 获取估值因子(PE)与成长因子(净利润增长率)
    field_pe = 'Valuation_and_Market_Cap.PE'
    field_growth = 'Growth.NetProfitGrowRate'
    fields = [field_pe, field_growth]
    
    # 调用 QMT 因子接口
    factor_data = ContextInfo.get_factor_data(fields, stock_list, bar_date, bar_date)
    
    if factor_data.empty if isinstance(factor_data, pd.DataFrame) else not factor_data:
        print("未能获取到因子数据")
        return
        
    # 3. 提取与处理因子数据
    df_factors = pd.DataFrame(index=stock_list)
    
    # 假设返回为 Dict 或 DataFrame 结构提取数据
    try:
        if isinstance(factor_data, dict):
            for code in stock_list:
                if code in factor_data:
                    df_factors.loc[code, 'PE'] = factor_data[code].get(field_pe, np.nan).values[-1]
                    df_factors.loc[code, 'Growth'] = factor_data[code].get(field_growth, np.nan).values[-1]
        elif isinstance(factor_data, pd.DataFrame):
            df_factors['PE'] = factor_data[field_pe]
            df_factors['Growth'] = factor_data[field_growth]
    except Exception as e:
        print(f"解析因子数据异常: {e}")
        return

    # 清理缺失值
    df_factors = df_factors.dropna()
    if df_factors.empty:
        print("有效因子数据为空")
        return

    # 4. 因子打分计算 (Percentile/Rank 打分)
    # PE越低越好,排名越小越好;Growth越高越好,排名越大越好
    df_factors['PE_Score'] = df_factors['PE'].rank(ascending=False)  # 低PE给高分
    df_factors['Growth_Score'] = df_factors['Growth'].rank(ascending=True)  # 高成长给高分
    
    # 综合打分 (权重可自定义,如各占 50%)
    df_factors['Total_Score'] = 0.5 * df_factors['PE_Score'] + 0.5 * df_factors['Growth_Score']
    
    # 按总分从高到低排序,选出前 N 只
    selected_stocks = df_factors.sort_values(by='Total_Score', ascending=False).head(ContextInfo.hold_count).index.tolist()
    print(f"今日选股结果: {selected_stocks}")
    
    # 5. 执行调仓交易
    execute_trade(ContextInfo, selected_stocks)

def execute_trade(ContextInfo, target_stocks):
    # 简单目标持仓调整:对选中股票按目标比例下单
    weight = 1.0 / len(target_stocks) if target_stocks else 0
    for stock in target_stocks:
        # 使用 order_target_percent 进行目标比例调仓
        order_target_percent(stock, weight, 'LATEST', 0, ContextInfo, ContextInfo.account)

def handlebar(ContextInfo):
    pass

3. QMT 因子调用的关键注意事项

  1. 数据补充:使用 get_factor_data 接口前,请确保在 QMT 客户端的 菜单 -> 操作 -> 数据管理 -> 补充数据 -> 多因子数据 中提前下载了对应品种的因子数据。
  2. 因子表名格式:因子字段需要附带表名全称,例如:
    • 估值类:Valuation_and_Market_Cap.PE
    • 成长类:Growth.NetProfitGrowRate
  3. 下单调仓逻辑:在盘中实盘交易时,推荐使用 order_target_percentpassorder(设置 quickTrade=1)实现快速且准确的持仓比例调仓。