3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化投资中,基本面选股是构建长期稳健策略的重要基石。杜邦分析法(DuPont Analysis)通过将净资产收益率(ROE)拆解为产品净利率、资产周转率和权益乘数,能全面评估企业的盈利能力、营运能力和财务杠杆。
本文将指导您如何使用国信证券 QMT (Quantitative Trading System) Python API 中的 get_financial_data 接口获取核心财务数据,并构建一个简单的杜邦分析选股打分模型。
根据QMT API文档,我们需要从不同的财务报表中获取以下字段:
| 指标名称 | 英文表名.字段名 | 对应报表 | 说明 |
|---|---|---|---|
| 净利润 | ASHAREINCOME.net_profit_incl_min_int_inc |
利润表 | 包含少数股东损益的净利润 |
| 资产总计 | ASHAREBALANCESHEET.tot_assets |
资产负债表 | 期末总资产 |
| 所有者权益合计 | ASHAREBALANCESHEET.total_equity |
资产负债表 | 净资产 |
| 营业收入 | ASHAREINCOME.revenue_inc |
利润表 | 营业收入 |
QMT 提供了 ContextInfo.get_financial_data 接口,支持按**报告期(report_time)或公告期(announce_time)**获取历史财务数据。
ContextInfo.get_financial_data(fieldList, stockList, startDate, endDate, report_type='announce_time')
表名.字段名。['600000.SH', '000001.SZ']。'20230101'。'announce_time'(按公告期,避免未来函数),选股模型中推荐使用。以下是一个完整的QMT策略示例。该模型在初始化时设定股票池,在 handlebar 中获取最新的财务数据,计算杜邦三因子并进行打分排序,最终筛选出综合得分最高的股票。
#coding:gbk
import pandas as pd
import numpy as np
def init(ContextInfo):
# 1. 设定股票池(以沪深300部分成分股为例)
ContextInfo.stock_list = ['600000.SH', '600036.SH', '600276.SH', '601318.SH', '000001.SZ', '000333.SZ', '000858.SZ', '002594.SZ']
ContextInfo.set_universe(ContextInfo.stock_list)
# 2. 设定选股参数
ContextInfo.start_date = '20230101'
ContextInfo.end_date = '20231231'
def handlebar(ContextInfo):
# 仅在最后一根Bar运行选股逻辑
if not ContextInfo.is_last_bar():
return
# 定义需要获取的财务字段
fields = [
'ASHAREINCOME.net_profit_incl_min_int_inc', # 净利润
'ASHAREBALANCESHEET.tot_assets', # 总资产
'ASHAREBALANCESHEET.total_equity', # 净资产
'ASHAREINCOME.revenue_inc' # 营业收入
]
# 获取财务数据 (返回 Panel 或 Dict 结构)
print("正在获取财务数据...")
fin_data = ContextInfo.get_financial_data(
fields,
ContextInfo.stock_list,
ContextInfo.start_date,
ContextInfo.end_date,
report_type='announce_time'
)
# 存储每只股票的杜邦指标
dupont_results = []
for stock in ContextInfo.stock_list:
try:
# 提取单只股票的财务DataFrame
df = fin_data[stock] if isinstance(fin_data, dict) else fin_data.major_xs(stock)
if df.empty:
continue
# 取最新一个报告期的数据
latest_data = df.iloc[-1]
net_profit = latest_data['ASHAREINCOME.net_profit_incl_min_int_inc']
total_assets = latest_data['ASHAREBALANCESHEET.tot_assets']
total_equity = latest_data['ASHAREBALANCESHEET.total_equity']
revenue = latest_data['ASHAREINCOME.revenue_inc']
# 杜邦公式拆解计算
# 1. 净资产收益率 ROE = 净利润 / 净资产
roe = net_profit / total_equity if total_equity > 0 else 0
# 2. 销售净利率 = 净利润 / 营业收入
net_profit_margin = net_profit / revenue if revenue > 0 else 0
# 3. 资产周转率 = 营业收入 / 总资产
asset_turnover = revenue / total_assets if total_assets > 0 else 0
# 4. 权益乘数 = 总资产 / 净资产
equity_multiplier = total_assets / total_equity if total_equity > 0 else 0
dupont_results.append({
'stock': stock,
'ROE': roe,
'Margin': net_profit_margin,
'Turnover': asset_turnover,
'Leverage': equity_multiplier
})
except Exception as e:
print("获取股票 %s 财务数据失败: %s" % (stock, str(e)))
# 构建分析表格
result_df = pd.DataFrame(dupont_results)
if result_df.empty:
print("未获取到有效财务数据")
return
# 4. 杜邦打分模型:对各项指标进行百分比排名打分
result_df['score_roe'] = result_df['ROE'].rank(pct=True)
result_df['score_margin'] = result_df['Margin'].rank(pct=True)
result_df['score_turnover'] = result_df['Turnover'].rank(pct=True)
# 财务杠杆(权益乘数)并非越高越好,这里给予适度权重或不纳入高分项,此处主要以盈利和营运效率为主
result_df['total_score'] = result_df['score_roe'] * 0.4 + result_df['score_margin'] * 0.3 + result_df['score_turnover'] * 0.3
# 排序并输出前3名优质基本面股票
selected_stocks = result_df.sort_values(by='total_score', ascending=False).head(3)
print("\n====== 杜邦分析选股打分结果 ======")
print(selected_stocks[['stock', 'ROE', 'Margin', 'Turnover', 'total_score']])
get_financial_data 时,参数 report_type 务必设为 'announce_time'(公告日期)。如果设为 'report_time'(报告期),在回测时会提前使用尚未公布的财报数据,导致回测业绩虚高。try...except 异常捕获,确保单只股票数据异常不影响整个选股模型的运行。get_industry_name_of_stock 接口,在同行业内部进行打分排序。