3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 QMT(迅投量化交易系统)中,基于基本面财报数据的选股策略非常常见。利用 ContextInfo.get_financial_data API,开发者可以方便地提取股票的资产负债表(ASHAREBALANCESHEET)、利润表(ASHAREINCOME)、现金流量表(ASHARECASHFLOW)以及主要财务指标(PERSHAREINDEX)。
get_financial_data 支持按公告期(announce_time)或报告期(report_time)提取数据。为避免未来函数,在历史回测中建议使用默认的公告期(announce_time)。
表名.字段名(例如 ['ASHAREINCOME.net_profit_incl_min_int_inc', 'CAPITALSTRUCTURE.total_capital'])。['600000.SH', '000001.SZ']。'YYYYMMDD'。'announce_time'(公告期,默认)或 'report_time'(报告期)。以下策略演示如何在 QMT 中提取净利润与总股本,计算每股收益(EPS),并在 handlebar 中按财务因子筛选股票池:
#encoding:gbk
import pandas as pd
import numpy as np
def init(ContextInfo):
# 1. 初始化股票池(以沪深300为例)
ContextInfo.stocks = ContextInfo.get_stock_list_in_sector('沪深300')
ContextInfo.set_universe(ContextInfo.stocks)
ContextInfo.set_account('6000000001')
# 2. 设置调仓周期控制变量
ContextInfo.trade_bar = 0
ContextInfo.hold_count = 10 # 持仓前10只股票
def handlebar(ContextInfo):
# 每20个Bar(约一个月)调仓一次
if ContextInfo.trade_bar % 20 != 0:
ContextInfo.trade_bar += 1
return
ContextInfo.trade_bar += 1
# 获取当前Bar的日期
timetag = ContextInfo.get_bar_timetag(ContextInfo.barpos)
# 转换为 YYYYMMDD 格式
current_date = timetag_to_datetime(timetag, '%Y%m%d')
# 提取过去一年的财务数据
start_date = str(int(current_date) - 10000) # 一年前
# 需要获取的字段:利润表.净利润 和 股本表.总股本
field_list = ['ASHAREINCOME.net_profit_incl_min_int_inc', 'CAPITALSTRUCTURE.total_capital']
try:
# 获取财务数据,返回 Panel 或 DataFrame
fin_data = ContextInfo.get_financial_data(field_list, ContextInfo.stocks, start_date, current_date, report_type='announce_time')
factor_scores = {}
for stock in ContextInfo.stocks:
# 提取单只股票的数据
if isinstance(fin_data, dict) or hasattr(fin_data, 'items'):
df = fin_data.get(stock)
else:
df = fin_data
if df is not None and not df.empty:
# 获取最新一期的净利润与总股本
latest_net_profit = df['ASHAREINCOME.net_profit_incl_min_int_inc'].iloc[-1]
latest_capital = df['CAPITALSTRUCTURE.total_capital'].iloc[-1]
if latest_capital > 0:
eps = latest_net_profit / latest_capital
factor_scores[stock] = eps
if not factor_scores:
return
# 3. 按因子值(EPS)排序,选择前 N 只股票
sorted_stocks = sorted(factor_scores.items(), key=lambda x: x[1], reverse=True)
target_stocks = [stk for stk, score in sorted_stocks[:ContextInfo.hold_count]]
# 4. 调仓逻辑:卖出非目标股,买入目标股
account = ContextInfo.accountID if hasattr(ContextInfo, 'accountID') else '6000000001'
# 简单按等权重调仓(示例使用 order_target_percent)
target_weight = 1.0 / ContextInfo.hold_count
for stock in target_stocks:
order_target_percent(stock, target_weight, 'FIX', ContextInfo.get_market_data(['close'], [stock])['close'].iloc[-1], ContextInfo, account)
except Exception as e:
print(f"提取财务数据或调仓失败: {e}")
report_type='announce_time',确保回测使用的是财报实际披露日的数据,而非财报截止日的数据。