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

QMT 平台如何使用 get_financial_data 构建杜邦分析选股模型?(附 Python 源码)

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

问题描述

QMT 财务选股实战:使用 get_financial_data 构建杜邦分析模型
我想在QMT中提取多只股票的财务报表并进行杜邦分析,应该如何编写代码?

解决方案

在量化选股中,**杜邦分析法(DuPont Analysis)**是一种经典且极其有效的财务分析工具。它通过将净资产收益率(ROE)拆解为三个核心财务指标的乘积,帮助投资者透视企业盈利能力的驱动源泉:

$$\text{ROE} = \text{净利润率(盈利能力)} \times \text{资产周转率(营运能力)} \times \text{权益乘数(杠杆水平)}$$

在 QMT 平台中,我们可以通过 ContextInfo.get_financial_data 接口高效地提取多只股票的资产负债表和利润表数据,并在 Python 中快速构建杜邦分析模型。以下是完整的实战指南和策略源码。


一、 杜邦分析核心指标与 QMT 字段映射

为了构建杜邦分析,我们需要从 QMT 财务数据库中提取以下字段:

  1. 净利润ASHAREINCOME.net_profit_incl_min_int_inc(利润表)
  2. 营业总收入ASHAREINCOME.revenue(利润表)
  3. 资产总计ASHAREBALANCESHEET.tot_assets(资产负债表)
  4. 所有者权益合计ASHAREBALANCESHEET.total_equity(资产负债表)

杜邦拆解公式:

  • 净利润率 (Net Profit Margin) = 净利润 / 营业总收入
  • 资产周转率 (Asset Turnover) = 营业总收入 / 资产总计
  • 权益乘数 (Equity Multiplier) = 资产总计 / 所有者权益合计
  • 计算 ROE = 净利润率 * 资产周转率 * 权益乘数

二、 QMT 杜邦分析选股策略源码

请在 QMT 的 Python 策略编辑器中运行以下代码。运行前请确保已通过客户端的 “数据管理” -> “补充数据” -> “财务数据” 下载了对应股票的历史财务报表。

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

def init(ContextInfo):
    # 1. 设定初始股票池(以部分沪深300成分股为例)
    ContextInfo.stock_list = ['600000.SH', '600036.SH', '600276.SH', '600519.SH', '000001.SZ', '000858.SZ']
    ContextInfo.set_universe(ContextInfo.stock_list)
    
    # 2. 设定财务报表检索的时间范围
    ContextInfo.start_date = '20230101'
    ContextInfo.end_date = '20231231'

def handlebar(ContextInfo):
    # 仅在最后一根K线执行一次财务分析
    if not ContextInfo.is_last_bar():
        return
        
    print("====== 开始进行杜邦分析选股 ======")
    
    # 3. 定义需要获取的财务字段
    fields = [
        'ASHAREINCOME.net_profit_incl_min_int_inc', # 净利润
        'ASHAREINCOME.revenue',                     # 营业总收入
        'ASHAREBALANCESHEET.tot_assets',            # 资产总计
        'ASHAREBALANCESHEET.total_equity'           # 所有者权益合计
    ]
    
    # 4. 调用 QMT 财务接口获取数据
    # report_type='report_time' 表示按报告期取数
    fin_data = ContextInfo.get_financial_data(
        fields, 
        ContextInfo.stock_list, 
        ContextInfo.start_date, 
        ContextInfo.end_date, 
        report_type='report_time'
    )
    
    # 5. 解析财务数据并计算杜邦指标
    dupont_results = []
    
    for stock in ContextInfo.stock_list:
        try:
            # 提取单只股票的财务矩阵
            if isinstance(fin_data, dict):
                df = fin_data[stock]
            else:
                # 如果返回的是 Panel 或 MultiIndex DataFrame,进行相应转换
                df = fin_data.loc[stock] if stock in fin_data.index else None
                
            if df is None or df.empty:
                continue
                
            # 取最新一个报告期(通常是最后一行)的数据
            latest_row = df.iloc[-1]
            
            net_profit = latest_row['ASHAREINCOME.net_profit_incl_min_int_inc']
            revenue = latest_row['ASHAREINCOME.revenue']
            tot_assets = latest_row['ASHAREBALANCESHEET.tot_assets']
            total_equity = latest_row['ASHAREBALANCESHEET.total_equity']
            
            # 过滤无效或缺失数据
            if None in [net_profit, revenue, tot_assets, total_equity] or revenue == 0 or tot_assets == 0 or total_equity == 0:
                continue
                
            # 6. 杜邦公式拆解计算
            net_profit_margin = net_profit / revenue               # 净利润率
            asset_turnover = revenue / tot_assets                  # 资产周转率
            equity_multiplier = tot_assets / total_equity          # 权益乘数
            calculated_roe = net_profit_margin * asset_turnover * equity_multiplier # 杜邦计算ROE
            
            dupont_results.append({
                '股票代码': stock,
                '股票名称': ContextInfo.get_stock_name(stock),
                '净利润率(%)': round(net_profit_margin * 100, 2),
                '资产周转率(次)': round(asset_turnover, 4),
                '权益乘数': round(equity_multiplier, 2),
                '杜邦ROE(%)': round(calculated_roe * 100, 2)
            })
            
        except Exception as e:
            print(f"股票 {stock} 数据解析失败: {e}")
            
    # 7. 转换为 DataFrame 并按 ROE 降序排序
    result_df = pd.DataFrame(dupont_results)
    if not result_df.empty:
        result_df = result_df.sort_values(by='杜邦ROE(%)', ascending=False)
        print("\n杜邦分析选股结果(按ROE降序):")
        print(result_df.to_string(index=False))
        
        # 示例:筛选高ROE且低杠杆(权益乘数 < 2)的优质企业
        value_stocks = result_df[(result_df['杜邦ROE(%)'] > 15) & (result_df['权益乘数'] < 2)]
        print("\n筛选结果(ROE > 15% 且 权益乘数 < 2 的低杠杆高成长股):")
        print(value_stocks.to_string(index=False))
    else:
        print("未获取到有效的财务数据,请检查本地财务数据是否下载完整。")

三、 核心步骤与 API 参数详解

  1. get_financial_datareport_type 参数

    • 'report_time'(推荐):按照报告期(一季报、半年报、三季报、年报)对齐数据。适合进行标准的杜邦分析对比。
    • 'announce_time':按照公告日期取数。适合实盘回测,防止前瞻偏差(Look-ahead Bias)。
  2. 数据结构处理

    • 当查询多股、多时间段时,QMT 返回的数据通常是一个三维字典或 pandas.Panel 结构。代码中通过 fin_data[stock] 提取单股的时间序列 DataFrame,再通过 df.iloc[-1] 获取最新一期的财务报表数据。
  3. 量化过滤逻辑

    • 在得到杜邦拆解指标后,我们可以通过 Pandas 轻松实现多因子过滤。例如,上文源码中筛选了 “ROE > 15% 且 权益乘数 < 2” 的股票,这能帮我们剔除靠高负债(高杠杆)堆砌 ROE 的高风险企业,找出真正具有高盈利能力和高效营运能力的优质标的。