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

如何在 QMT 中计算基本面因子 IC/Rank-IC 并构建多因子选股模型?(附 Python 源码)

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

问题描述

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

Title: QMT 基本面因子 IC/Rank-IC 评估与多因子选股模型

Question: 如何使用 QMT 财务接口计算基本面因子的 IC 值并构建多因子组合?

解决方案

在量化选股体系中,基本面因子(如 ROE、市盈率 PE、净利润增长率等)是构建阿尔法策略的核心。评估因子有效性的标准指标是 信息系数(Information Coefficient, IC)秩信息系数(Rank-IC)。同时,通过 QMT 的 get_financial_data 接口,我们可以高效获取历史财务数据并构建多因子组合。


一、核心概念与计算原理

  1. IC 值(Normal IC):因子值与标的下一期收益率之间的皮尔逊相关系数(Pearson Correlation)。
  2. Rank-IC 值:因子值的秩(排名)与标的下一期收益率的秩之间的斯皮尔曼相关系数(Spearman Correlation),对异常值更鲁棒。
  3. 多因子组合构建:根据历史 IC/Rank-IC 的均值或 IR(IC/IC标准差)为各因子分配权重,打分后选出得分最高的股票组合。

二、QMT 获取财务数据关键接口

QMT 提供了 get_financial_data 函数来拉取财务报表及指标数据:

# 示例:拉取净资产收益率与净利润
fieldList = ['PERSHAREINDEX.s_fa_roe', 'ASHAREINCOME.net_profit_incl_min_int_inc']
stockList = ['600000.SH', '000001.SZ']
startDate = '20230101'
endDate = '20231231'

df_finance = ContextInfo.get_financial_data(fieldList, stockList, startDate, endDate, report_type='announce_time')

三、QMT 完整实现代码(包含 IC 计算与选股)

以下示例展示如何在 QMT 策略中提取选股池股票的基本面因子,计算因子与收益的相关性并进行打分选股:

#encoding:gbk
import pandas as pd
import numpy as np
from scipy.stats import spearmanr, pearsonr

def init(ContextInfo):
    # 1. 设置股票池(以沪深300成份股为例)
    ContextInfo.stock_pool = ContextInfo.get_stock_list_in_sector('沪深300')
    ContextInfo.set_universe(ContextInfo.stock_pool)
    ContextInfo.set_account('6000000001')
    
    # 2. 定期调仓标记
    ContextInfo.trade_bar = 0
    ContextInfo.hold_count = 10  # 持仓10只股票

def handlebar(ContextInfo):
    # 每20个Bar(如日线20个交易日)进行一次因子评估与重新调仓
    if ContextInfo.trade_bar % 20 != 0:
        ContextInfo.trade_bar += 1
        return
    
    ContextInfo.trade_bar += 1
    stocks = ContextInfo.get_universe()
    if not stocks:
        return
    
    # 1. 获取行情数据计算未来收益率
    close_data = ContextInfo.get_market_data(['close'], stock_code=stocks, period='1d', count=21)
    if close_data.empty:
        return
    
    # 计算近20日收益率作为收益率响应标的
    returns = (close_data['close'].iloc[-1] - close_data['close'].iloc[0]) / close_data['close'].iloc[0]
    
    # 2. 获取基本面因子数据(例如:ROE 与 每股收益 EPS)
    # 字段格式:表名.字段名
    fields = ['PERSHAREINDEX.s_fa_roe', 'PERSHAREINDEX.s_fa_eps_basic']
    end_date = ContextInfo.get_bar_timetag(ContextInfo.barpos)
    # 转换时间格式为 YYYYMMDD
    str_end_date = timetag_to_datetime(end_date, '%Y%m%d')
    str_start_date = timetag_to_datetime(end_date - 30 * 86400 * 1000, '%Y%m%d')
    
    try:
        fin_df = ContextInfo.get_financial_data(fields, stocks, str_start_date, str_end_date)
    except Exception as e:
        print("获取财务数据失败:", e)
        return
    
    # 提取最新的基本面因子截面数据
    factor_roe = {}
    factor_eps = {}
    for stk in stocks:
        if stk in fin_df:
            df_stk = fin_df[stk]
            if 'PERSHAREINDEX.s_fa_roe' in df_stk.columns and not df_stk.empty:
                factor_roe[stk] = df_stk['PERSHAREINDEX.s_fa_roe'].iloc[-1]
            if 'PERSHAREINDEX.s_fa_eps_basic' in df_stk.columns and not df_stk.empty:
                factor_eps[stk] = df_stk['PERSHAREINDEX.s_fa_eps_basic'].iloc[-1]
                
    df_factors = pd.DataFrame({'ROE': factor_roe, 'EPS': factor_eps, 'Return': returns}).dropna()
    if len(df_factors) < 10:
        return
    
    # 3. 计算 IC 与 Rank-IC
    ic_roe, _ = pearsonr(df_factors['ROE'], df_factors['Return'])
    rank_ic_roe, _ = spearmanr(df_factors['ROE'], df_factors['Return'])
    
    ic_eps, _ = pearsonr(df_factors['EPS'], df_factors['Return'])
    rank_ic_eps, _ = spearmanr(df_factors['EPS'], df_factors['Return'])
    
    print(f"[因子评估] ROE IC: {ic_roe:.4f}, Rank-IC: {rank_ic_roe:.4f}")
    print(f"[因子评估] EPS IC: {ic_eps:.4f}, Rank-IC: {rank_ic_eps:.4f}")
    
    # 4. 基于因子的 Z-Score 标准化与组合打分(极简加权)
    df_factors['ROE_score'] = (df_factors['ROE'] - df_factors['ROE'].mean()) / df_factors['ROE'].std()
    df_factors['EPS_score'] = (df_factors['EPS'] - df_factors['EPS'].mean()) / df_factors['EPS'].std()
    
    # 总得分 = 0.5 * ROE + 0.5 * EPS
    df_factors['Total_Score'] = 0.5 * df_factors['ROE_score'] + 0.5 * df_factors['EPS_score']
    
    # 排序选出得分最高前 N 只股票
    target_stocks = df_factors.sort_values(by='Total_Score', ascending=False).head(ContextInfo.hold_count).index.tolist()
    
    # 5. 调仓执行:目标比例下单
    for stk in target_stocks:
        order_target_percent(stk, 1.0 / ContextInfo.hold_count, 'LATEST', ContextInfo.stockcode, ContextInfo)

四、注意事项与最佳实践

  1. 幸存者偏差与公告日对齐
    使用 get_financial_data 时,建议设置 report_type='announce_time'(默认按财报实际公告日期对齐),以防用到未公开的前瞻数据引发未来函数。
  2. 因子预处理
    在计算真正的 IC/Rank-IC 与打分前,应对财务因子进行 去极值(Winsorize)中性化(去行业与市值影响)标准化(Z-Score) 处理。
  3. 多因子权重分配
    生产环境中可根据因子近 12 或 24 个月的 Rank-IC IR(Rank-IC 均值 / Rank-IC 标准差)动态调整因子权重。