3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化选股中,**杜邦分析法(DuPont Analysis)**是一种经典且极其有效的财务分析工具。它通过将净资产收益率(ROE)拆解为三个核心财务指标的乘积,帮助投资者透视企业盈利能力的驱动源泉:
$$\text{ROE} = \text{净利润率(盈利能力)} \times \text{资产周转率(营运能力)} \times \text{权益乘数(杠杆水平)}$$
在 QMT 平台中,我们可以通过 ContextInfo.get_financial_data 接口高效地提取多只股票的资产负债表和利润表数据,并在 Python 中快速构建杜邦分析模型。以下是完整的实战指南和策略源码。
为了构建杜邦分析,我们需要从 QMT 财务数据库中提取以下字段:
ASHAREINCOME.net_profit_incl_min_int_inc(利润表)ASHAREINCOME.revenue(利润表)ASHAREBALANCESHEET.tot_assets(资产负债表)ASHAREBALANCESHEET.total_equity(资产负债表)请在 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("未获取到有效的财务数据,请检查本地财务数据是否下载完整。")
get_financial_data 的 report_type 参数:
'report_time'(推荐):按照报告期(一季报、半年报、三季报、年报)对齐数据。适合进行标准的杜邦分析对比。'announce_time':按照公告日期取数。适合实盘回测,防止前瞻偏差(Look-ahead Bias)。数据结构处理:
pandas.Panel 结构。代码中通过 fin_data[stock] 提取单股的时间序列 DataFrame,再通过 df.iloc[-1] 获取最新一期的财务报表数据。量化过滤逻辑: