3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化投资中,基本面选股是构建长期稳健投资组合的核心。**杜邦分析法(DuPont Analysis)是一种经典的财务分析体系,它将净资产收益率(ROE)**拆解为三个核心驱动因素:
$$\text{ROE} = \text{净利润率(盈利能力)} \times \text{总资产周转率(营运能力)} \times \text{权益乘数(财务杠杆)}$$
通过这种拆解,量化交易者可以甄别出企业高 ROE 的真实含金量(是靠高利润、高周转还是高负债驱动)。本文将详细介绍如何在国信证券 QMT 平台中利用 get_financial_data 接口获取相关财务指标,并实现一个杜邦分析选股策略。
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{资产负债率}}$$
init 函数中设置股票池(如沪深300成分股)并订阅财务数据。handlebar 中,利用 get_financial_data 获取指定报告期内的 equity_roe、net_profit 和 gear_ratio。以下是基于 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)
get_financial_data 接口前,必须在 QMT 客户端点击 操作 -> 数据管理 -> 补充数据 -> 财务数据,下载对应市场和年份的财务历史数据,否则接口将返回空值。report_time(报告期):按财报所属季度(一季报、半年报、三季报、年报)对齐,适合历史回测,能真实反映企业经营周期。announce_time(公告期):按财报实际发布日期对齐,能有效避免未来函数,适合实盘交易防范“提前获知未公布财报”的逻辑错误。ContextInfo.is_suspended_stock() 进行过滤。