🚀 AI 一键生成 qmt 策略代码

如何使用 Python API 筛选出净资产收益率 (ROE) 高于 20% 的股票?

qmt | 发布时间: 2025/12/19
以下内容由 EasyQuant 生成。

问题描述

请帮我写一个 Python 脚本,用来筛选出最新财报净资产收益率 (ROE) 高于 20% 的所有 A 股股票。

解决方案

这是一个基于 QMT Python API 的选股脚本。该脚本会获取所有 A 股股票,并筛选出在当前回测或运行时间点,最新财报中净资产收益率 (ROE) 大于 20% 的股票。

策略逻辑说明

  1. 获取股票池:在 init 中使用 get_stock_list_in_sector('沪深A股') 获取全市场 A 股代码。
  2. 获取财务数据:在 handlebar 中(仅在最后一根 K 线执行),使用 get_financial_data 批量获取所有股票的 PERSHAREINDEX.du_return_on_equity(净资产收益率)数据。
  3. 筛选与排序:利用 Pandas 对数据进行过滤,筛选出 ROE > 20 的股票,并按 ROE 从高到低排序。
  4. 输出结果:打印符合条件的股票代码、名称及具体的 ROE 数值。

Python 策略代码

# -*- coding: gbk -*-
import pandas as pd

def init(ContextInfo):
    # 1. 获取所有沪深A股股票代码
    # 这一步在初始化时执行一次即可
    ContextInfo.stock_list = ContextInfo.get_stock_list_in_sector('沪深A股')
    print(f"策略初始化完成,获取到 A 股数量: {len(ContextInfo.stock_list)}")

def handlebar(ContextInfo):
    # 为了避免在历史回测的每一根 K 线上都打印,我们只在最后一根 K 线(最新时刻)执行筛选
    if not ContextInfo.is_last_bar():
        return

    # 2. 定义需要获取的财务字段
    # du_return_on_equity 对应主要指标中的“净资产收益率”
    field_name = 'PERSHAREINDEX.du_return_on_equity'
    field_list = [field_name]
    
    # 获取当前运行到的日期(YYYYMMDD格式)
    current_timetag = ContextInfo.get_bar_timetag(ContextInfo.barpos)
    current_date = timetag_to_datetime(current_timetag, '%Y%m%d')
    
    print(f"正在筛选 {current_date} 时刻 ROE > 20% 的股票,请稍候...")

    # 3. 批量获取财务数据
    # 参数说明:字段列表, 股票列表, 开始时间, 结束时间, 报表类型
    # report_type='announce_time' 表示按照公告日期获取当时已发布的最新数据,避免未来函数
    # 开始时间和结束时间都设为 current_date,表示获取该时间点的截面数据
    df = ContextInfo.get_financial_data(
        field_list,
        ContextInfo.stock_list,
        current_date,
        current_date,
        report_type='announce_time'
    )

    # 4. 数据处理与筛选
    # get_financial_data 返回的数据格式:
    # 当代码列表为 n,时间范围为 1 时,返回 DataFrame (Index=代码, Columns=字段)
    if df is None or df.empty:
        print("未获取到财务数据,请检查数据是否已下载补充。")
        return

    # 提取 ROE 列
    roe_series = df[field_name]
    
    # 筛选 ROE > 20 的股票
    # 注意:财务数据中可能存在 NaN (空值),Pandas 比较时会自动处理
    filtered_stocks = roe_series[roe_series > 20]
    
    # 按 ROE 从高到低排序
    filtered_stocks = filtered_stocks.sort_values(ascending=False)

    # 5. 输出结果
    print("=" * 60)
    print(f"筛选结果:共发现 {len(filtered_stocks)} 只股票 ROE > 20%")
    print(f"{'代码':<12} {'名称':<12} {'ROE(%)':<10}")
    print("-" * 60)
    
    for code, roe_value in filtered_stocks.items():
        # 获取股票名称
        name = ContextInfo.get_stock_name(code)
        print(f"{code:<12} {name:<12} {roe_value:.2f}")
        
    print("=" * 60)

使用说明

  1. 补充数据:运行此脚本前,请确保在 QMT 客户端的【数据管理】中补充了财务数据。如果没有本地数据,get_financial_data 将无法返回结果。
  2. 运行模式
    • 此脚本可以在“回测模式”或“模型研究/运行”模式下运行。
    • 如果在回测模式下,它会筛选出回测结束日期那一天符合条件的股票。
    • 如果在实时模式下,它会筛选出基于最新已公告财报符合条件的股票。
  3. 字段解释:代码中使用的 PERSHAREINDEX.du_return_on_equity 是“净资产收益率”。如果你需要“摊薄净资产收益率”或“加权净资产收益率”,可以分别替换为 PERSHAREINDEX.net_roePERSHAREINDEX.equity_roe

Q&A

Q: 为什么运行后提示“未获取到财务数据”?
A: QMT 的财务数据依赖本地数据库。请在客户端顶部菜单栏点击“数据” -> “数据管理”,勾选“财务数据”并选择对应的市场和时间段进行下载补充。

Q: report_type='announce_time' 是什么意思?
A: 这代表“按公告日期”取数。例如,某公司在 4 月 20 日发布年报,如果在 4 月 19 日运行策略,系统会取三季报的数据;在 4 月 20 日运行则取年报数据。这能确保回测时不会用到当时还未公开的“未来数据”。

Q: 如何将筛选结果直接买入?
A: 可以在 handlebar 函数的循环中添加交易逻辑。例如:

for code, roe_value in filtered_stocks.items():
    # 以最新价买入 100 股
    passorder(23, 1101, ContextInfo.accid, code, 5, -1, 100, ContextInfo)

注意:实盘交易请务必添加风控逻辑和资金判断。