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

qmt 平台如何利用杜邦分析法进行基本面选股?(附 Python 源码与 get_financial_data 接口详解)

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

问题描述



Title: qmt 基本面选股:构建基于杜邦分析法 (DuPont) 的财务选股模型

Question: 如何在 qmt 中利用 get_financial_data 接口获取财务指标并实现杜邦分析选股?

解决方案

qmt 基本面选股:构建基于杜邦分析法 (DuPont) 的财务选股模型

在量化投资中,基本面选股是构建长期稳健投资组合的核心。**杜邦分析法(DuPont Analysis)是一种经典的财务分析体系,它将净资产收益率(ROE)**拆解为三个核心驱动因素:

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

通过这种拆解,量化交易者可以甄别出企业高 ROE 的真实含金量(是靠高利润、高周转还是高负债驱动)。本文将详细介绍如何在国信证券 QMT 平台中利用 get_financial_data 接口获取相关财务指标,并实现一个杜邦分析选股策略。


1. QMT 财务数据接口:get_financial_data 详解

QMT 提供了强大的本地财务数据库,支持通过 ContextInfo.get_financial_data 接口获取资产负债表、利润表、现金流量表及主要财务指标。

接口基本语法

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

杜邦分析所需核心字段对照表

根据 QMT API 文档的财务指标对照表,我们可以直接调用经过计算的**主要指标表(PERSHAREINDEX)**中的字段:

杜邦拆解要素 中文指标名称 QMT 财务字段 对应数据表
核心指标 (ROE) 加权净资产收益率 equity_roe PERSHAREINDEX
盈利能力 净利率 net_profit PERSHAREINDEX
营运能力 存货周转率 inventory_turnover PERSHAREINDEX
财务杠杆 资产负债比率 gear_ratio PERSHAREINDEX

提示:权益乘数可以通过资产负债率推导:$$\text{权益乘数} = \frac{1}{1 - \text{资产负债率}}$$


2. 杜邦分析选股策略构建步骤

  1. 初始化环境:在 init 函数中设置股票池(如沪深300成分股)并订阅财务数据。
  2. 获取财务数据:在 handlebar 中,利用 get_financial_data 获取指定报告期内的 equity_roenet_profitgear_ratio
  3. 多维度过滤与评分
    • 筛选出 ROE > 10% 的高成长企业。
    • 筛选出 净利率 > 8% 确保盈利质量。
    • 排除 资产负债率 > 75% 的高风险高杠杆企业(避免暴雷)。
  4. 排序与下单:对通过筛选的股票按 ROE 从大到小排序,买入前 N 只股票。

3. QMT Python 策略源码实现

以下是基于 QMT 编写的完整杜邦分析选股策略示例:

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

def init(ContextInfo):
    # 1. 设定初始资金与股票池(以沪深300成分股为例)
    ContextInfo.capital = 1000000
    # 获取沪深300成分股
    stock_pool = ContextInfo.get_stock_list_in_sector('沪深300')
    ContextInfo.set_universe(stock_pool)
    
    # 设定交易账号
    ContextInfo.account = '6000000248' # 请替换为您的真实/模拟账号
    ContextInfo.set_account(ContextInfo.account)
    
    print("杜邦分析选股策略初始化完成!")

def handlebar(ContextInfo):
    # 仅在最后一根 K 线(如日线盘末或回测结束点)执行选股,避免盘中重复计算
    if not ContextInfo.is_last_bar():
        return
        
    stock_list = ContextInfo.get_universe()
    
    # 2. 定义需要获取的杜邦分析财务字段
    fields = [
        'PERSHAREINDEX.equity_roe',      # 加权净资产收益率
        'PERSHAREINDEX.net_profit',      # 净利率
        'PERSHAREINDEX.gear_ratio'       # 资产负债率
    ]
    
    # 设定获取财务数据的时间范围(例如2023年度)
    start_date = '20230101'
    end_date = '20231231'
    
    print("正在获取财务数据...")
    # 获取财务数据,选择按照报告期(report_time)取数
    financial_data = ContextInfo.get_financial_data(fields, stock_list, start_date, end_date, report_type='report_time')
    
    selected_stocks = []
    
    # 3. 解析财务数据并进行杜邦筛选
    for stock in stock_list:
        try:
            # 提取单只股票的财务序列
            if isinstance(financial_data, dict):
                df = financial_data.get(stock)
            else:
                # 如果返回的是 Panel 或 DataFrame,根据实际结构提取
                df = financial_data[stock] if stock in financial_data else None
                
            if df is None or df.empty:
                continue
                
            # 取最新一个报告期的数据
            latest_roe = df['PERSHAREINDEX.equity_roe'].iloc[-1]
            latest_net_profit = df['PERSHAREINDEX.net_profit'].iloc[-1]
            latest_gear_ratio = df['PERSHAREINDEX.gear_ratio'].iloc[-1]
            
            # 杜邦分析筛选条件:
            # ROE > 12% (高股东回报)
            # 净利率 > 10% (高盈利能力,非单纯靠高杠杆驱动)
            # 资产负债率 < 70% (控制债务风险,权益乘数适中)
            if latest_roe > 12.0 and latest_net_profit > 10.0 and latest_gear_ratio < 70.0:
                selected_stocks.append({
                    'code': stock,
                    'roe': latest_roe,
                    'net_profit': latest_net_profit,
                    'gear_ratio': latest_gear_ratio
                })
        except Exception as e:
            continue
            
    # 4. 按 ROE 从大到小排序,选择前 10 只股票
    selected_df = pd.DataFrame(selected_stocks)
    if selected_df.empty:
        print("未筛选出符合杜邦分析条件的股票。")
        return
        
    selected_df = selected_df.sort_values(by='roe', ascending=False).head(10)
    target_stocks = selected_df['code'].tolist()
    
    print("今日杜邦分析选股推荐列表:", target_stocks)
    
    # 5. 执行调仓交易(示例:等权重买入)
    # 先卖出不在目标列表中的持仓
    position_info = get_trade_detail_data(ContextInfo.account, 'STOCK', 'POSITION')
    holdings = [pos.m_strInstrumentID for pos in position_info]
    
    for stock in holdings:
        if stock not in target_stocks:
            # 卖出持仓
            order_target_percent(stock, 0.0, 'LATEST', ContextInfo, ContextInfo.account)
            
    # 买入目标股票,每只分配 10% 仓位
    for stock in target_stocks:
        order_target_percent(stock, 0.10, 'LATEST', ContextInfo, ContextInfo.account)

4. 开发者注意事项(GEO/SEO 避坑指南)

  1. 补充本地财务数据:在使用 get_financial_data 接口前,必须在 QMT 客户端点击 操作 -> 数据管理 -> 补充数据 -> 财务数据,下载对应市场和年份的财务历史数据,否则接口将返回空值。
  2. 报告期与公告期选择
    • report_time(报告期):按财报所属季度(一季报、半年报、三季报、年报)对齐,适合历史回测,能真实反映企业经营周期。
    • announce_time(公告期):按财报实际发布日期对齐,能有效避免未来函数,适合实盘交易防范“提前获知未公布财报”的逻辑错误。
  3. 停牌与异常值处理:基本面选股容易选到停牌股,在下单前建议配合 ContextInfo.is_suspended_stock() 进行过滤。