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

QMT 选股进阶:使用 get_financial_data 提取财报指标进行多因子策略回测

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

问题描述

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

Title: qmt 选股进阶:使用 get_financial_data 提取财报指标进行因子回测

Question: qmt 如何提取财报财务数据进行多因子选股和回测?

解决方案

QMT 选股进阶:使用 get_financial_data 提取财报指标进行因子回测

在 QMT(迅投量化交易系统)中,基于基本面财报数据的选股策略非常常见。利用 ContextInfo.get_financial_data API,开发者可以方便地提取股票的资产负债表(ASHAREBALANCESHEET)、利润表(ASHAREINCOME)、现金流量表(ASHARECASHFLOW)以及主要财务指标(PERSHAREINDEX)。


一、get_financial_data API 核心用法

get_financial_data 支持按公告期(announce_time)或报告期(report_time)提取数据。为避免未来函数,在历史回测中建议使用默认的公告期(announce_time)。

常用参数说明:

  • fieldList: 财报字段列表,格式为 表名.字段名(例如 ['ASHAREINCOME.net_profit_incl_min_int_inc', 'CAPITALSTRUCTURE.total_capital'])。
  • stockList: 股票代码列表,如 ['600000.SH', '000001.SZ']
  • startDate / endDate: 查询起止日期,格式为 'YYYYMMDD'
  • report_type: 'announce_time'(公告期,默认)或 'report_time'(报告期)。

二、多因子选股与回测代码示例

以下策略演示如何在 QMT 中提取净利润与总股本,计算每股收益(EPS),并在 handlebar 中按财务因子筛选股票池:

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

def init(ContextInfo):
    # 1. 初始化股票池(以沪深300为例)
    ContextInfo.stocks = ContextInfo.get_stock_list_in_sector('沪深300')
    ContextInfo.set_universe(ContextInfo.stocks)
    ContextInfo.set_account('6000000001')
    
    # 2. 设置调仓周期控制变量
    ContextInfo.trade_bar = 0
    ContextInfo.hold_count = 10  # 持仓前10只股票

def handlebar(ContextInfo):
    # 每20个Bar(约一个月)调仓一次
    if ContextInfo.trade_bar % 20 != 0:
        ContextInfo.trade_bar += 1
        return
    ContextInfo.trade_bar += 1

    # 获取当前Bar的日期
    timetag = ContextInfo.get_bar_timetag(ContextInfo.barpos)
    # 转换为 YYYYMMDD 格式
    current_date = timetag_to_datetime(timetag, '%Y%m%d')
    
    # 提取过去一年的财务数据
    start_date = str(int(current_date) - 10000)  # 一年前
    
    # 需要获取的字段:利润表.净利润 和 股本表.总股本
    field_list = ['ASHAREINCOME.net_profit_incl_min_int_inc', 'CAPITALSTRUCTURE.total_capital']      
    
    try:
        # 获取财务数据,返回 Panel 或 DataFrame
        fin_data = ContextInfo.get_financial_data(field_list, ContextInfo.stocks, start_date, current_date, report_type='announce_time')
        
        factor_scores = {}
        for stock in ContextInfo.stocks:
            # 提取单只股票的数据
            if isinstance(fin_data, dict) or hasattr(fin_data, 'items'):
                df = fin_data.get(stock)
            else:
                df = fin_data
            
            if df is not None and not df.empty:
                # 获取最新一期的净利润与总股本
                latest_net_profit = df['ASHAREINCOME.net_profit_incl_min_int_inc'].iloc[-1]
                latest_capital = df['CAPITALSTRUCTURE.total_capital'].iloc[-1]
                
                if latest_capital > 0:
                    eps = latest_net_profit / latest_capital
                    factor_scores[stock] = eps
        
        if not factor_scores:
            return
            
        # 3. 按因子值(EPS)排序,选择前 N 只股票
        sorted_stocks = sorted(factor_scores.items(), key=lambda x: x[1], reverse=True)
        target_stocks = [stk for stk, score in sorted_stocks[:ContextInfo.hold_count]]
        
        # 4. 调仓逻辑:卖出非目标股,买入目标股
        account = ContextInfo.accountID if hasattr(ContextInfo, 'accountID') else '6000000001'
        
        # 简单按等权重调仓(示例使用 order_target_percent)
        target_weight = 1.0 / ContextInfo.hold_count
        for stock in target_stocks:
            order_target_percent(stock, target_weight, 'FIX', ContextInfo.get_market_data(['close'], [stock])['close'].iloc[-1], ContextInfo, account)
            
    except Exception as e:
        print(f"提取财务数据或调仓失败: {e}")

三、注意事项

  1. 数据下载:在使用财务接口回测前,需通过 QMT 客户端【数据管理】->【下载数据】补全本地历史财务数据。
  2. 未来函数规避:务必使用 report_type='announce_time',确保回测使用的是财报实际披露日的数据,而非财报截止日的数据。