🚀 AI 一键生成 qmt 策略代码

如何利用财务数据接口筛选高自由现金流股票?

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

问题描述

怎么获取股票的自由现金流数据进行选股?

解决方案

在 QMT 中获取股票的自由现金流(Free Cash Flow, FCF)数据进行选股,主要有两种方式:

  1. 使用多因子库(推荐): 直接调用 QMT 内置的计算好的因子数据,如 Derived_Data(衍生数据)表中的 FCFE(股权自由现金流)或 FCFF(企业自由现金流)。这种方式最简单,不需要自己处理财务报表的计算逻辑。
  2. 使用财务数据接口: 调用 get_financial_data 获取原始的现金流量表数据(如经营活动现金流净额),然后自行计算。

下面我将提供一个完整的策略示例,使用第一种方式(多因子库),因为它更适合直接用于选股策略。我们将选取 股权自由现金流(FCFE) 最高的股票构建组合。

策略逻辑

  1. 股票池:沪深300成分股。
  2. 数据获取:使用 ContextInfo.get_factor_data 获取 Derived_Data.FCFE(股权自由现金流)。
  3. 选股逻辑
    • 剔除 FCFE 为空或负值的股票。
    • 按照 FCFE 从大到小排序。
    • 选取前 10 只股票。
  4. 交易执行:每月调仓一次,等权重买入。

策略代码

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

def init(ContextInfo):
    # 设置资金账号
    ContextInfo.account_id = 'YOUR_ACCOUNT_ID' # 请替换为您的资金账号
    ContextInfo.account_type = 'STOCK'
    ContextInfo.set_account(ContextInfo.account_id)
    
    # 策略参数
    ContextInfo.holding_num = 10  # 持仓数量
    ContextInfo.rebalance_period = '1mon'  # 调仓周期:月度
    ContextInfo.sector = '沪深300' # 股票池
    
    # 设置定时器,用于控制调仓频率(这里配合handlebar使用,也可以用run_time)
    # 在回测模式下,我们通常利用handlebar内的逻辑控制
    
    print("策略初始化完成")

def handlebar(ContextInfo):
    # 获取当前K线的时间戳
    bar_index = ContextInfo.barpos
    timetag = ContextInfo.get_bar_timetag(bar_index)
    current_date_str = timetag_to_datetime(timetag, '%Y%m%d')
    
    # 仅在回测模式下的每个月最后一个交易日,或者实盘的特定时间运行选股逻辑
    # 这里为了演示简单,使用简单的周期判断逻辑,实际使用建议配合 ContextInfo.is_new_bar 等判断
    
    # 如果不是当前周期的最后一根K线(对于日线回测),跳过
    # 注意:get_factor_data 需要下载好对应时间段的因子数据
    
    # 获取板块成分股
    stock_list = ContextInfo.get_stock_list_in_sector(ContextInfo.sector, timetag)
    if not stock_list:
        print(f"{current_date_str} 未获取到成分股")
        return

    # --- 核心步骤:获取自由现金流数据 ---
    # 字段说明:
    # Derived_Data.FCFE: 股权自由现金流
    # Derived_Data.FCFF: 企业自由现金流
    # Per_Share_Analysis.ShareholderFCFPS: 每股股东自由现金流量
    factor_fields = ['Derived_Data.FCFE']
    
    # 获取因子数据
    # 注意:get_factor_data 返回的数据结构取决于传入的股票数量和时间范围
    # 这里传入多个股票,1个时间点,返回 DataFrame (index=股票代码, columns=字段)
    factor_data = ContextInfo.get_factor_data(
        factor_fields, 
        stock_list, 
        current_date_str, 
        current_date_str
    )
    
    if factor_data is None or factor_data.empty:
        return

    # --- 数据处理与选股 ---
    # 1. 提取 FCFE 列
    df_fcfe = factor_data['Derived_Data.FCFE']
    
    # 2. 去除空值
    df_fcfe = df_fcfe.dropna()
    
    # 3. 过滤掉自由现金流为负的公司(可选,视策略而定)
    df_fcfe = df_fcfe[df_fcfe > 0]
    
    # 4. 排序:按自由现金流从大到小排序
    df_fcfe = df_fcfe.sort_values(ascending=False)
    
    # 5. 选取前 N 只
    target_stocks = df_fcfe.head(ContextInfo.holding_num).index.tolist()
    
    print(f"日期: {current_date_str}, 选股结果: {target_stocks}")
    
    # --- 交易执行 (仅在回测或实盘信号触发时执行) ---
    # 这里的逻辑是简单的全仓调仓
    
    # 1. 获取当前持仓
    positions = ContextInfo.get_trade_detail_data(ContextInfo.account_id, ContextInfo.account_type, 'POSITION')
    current_holdings = [obj.m_strInstrumentID for obj in positions]
    
    # 2. 卖出不在目标列表中的股票
    for stock in current_holdings:
        if stock not in target_stocks:
            order_target_value(stock, 0, ContextInfo, ContextInfo.account_id)
    
    # 3. 买入目标股票
    if len(target_stocks) > 0:
        # 简单的资金分配:总资产 / 目标数量
        # 注意:实际策略中应获取账户总资产 ContextInfo.capital (回测) 或 账户资金 (实盘)
        # 这里演示使用 order_target_percent
        target_weight = 1.0 / len(target_stocks)
        for stock in target_stocks:
            order_target_percent(stock, target_weight, ContextInfo, ContextInfo.account_id)

# 辅助函数:时间戳转字符串
def timetag_to_datetime(timetag, format_str):
    import time
    return time.strftime(format_str, time.localtime(timetag / 1000))

关键点说明

  1. 数据字段选择

    • 代码中使用了 Derived_Data.FCFE。这是 QMT 多因子库中预计算好的股权自由现金流
    • 如果你想使用企业自由现金流,请将字段改为 Derived_Data.FCFF
    • 如果你想使用每股数据,可以使用 Per_Share_Analysis.ShareholderFCFPS
  2. 数据补充

    • 在运行此策略之前,必须在 QMT 客户端界面中进行数据补充。
    • 路径:系统 -> 数据管理 -> 补充数据 -> 多因子数据
    • 确保勾选了“股票因子_衍生数据”或全选,并下载了对应回测时间段的数据。
  3. API 使用

    • ContextInfo.get_factor_data(fieldList, stockList, startDate, endDate) 是获取此类数据的核心 API。
    • 它返回的是 pandas 的 DataFrame 或 Series,方便直接进行排序 (sort_values) 和筛选 (dropna)。
  4. 选股逻辑扩展

    • 单纯看 FCFE 的绝对值可能会偏向大盘股。
    • 优化建议:你可以计算 自由现金流收益率 (FCF Yield)。方法是同时获取 Valuation_and_Market_Cap.MktValue (总市值),然后计算 FCFE / MktValue,选取比率最高的股票,这样更能发掘被低估的优质现金流公司。

Q&A

Q: 如果我想自己用财务报表计算 FCF 怎么办?
A: 你可以使用 ContextInfo.get_financial_data 接口。
通常 FCF = 经营活动现金流净额 - 资本开支。
对应 QMT 字段为:

  • 经营活动现金流净额: ASHARECASHFLOW.net_cash_flows_oper_act
  • 资本开支(估算): ASHARECASHFLOW.cash_pay_acq_const_fiolta (购建固定资产、无形资产和其他长期资产支付的现金)

Q: 为什么 get_factor_data 返回为空?
A: 通常有两个原因:

  1. 本地没有下载多因子数据(请去数据管理下载)。
  2. 传入的 stock_list 为空或者 startDate 格式不正确(必须是 'YYYYMMDD' 字符串)。

Q: 这个策略可以直接实盘吗?
A: 代码包含了基本的交易逻辑,但实盘需要更严谨的风控(如停牌处理、涨跌停处理、滑点控制)。建议先在回测模式下验证效果,并确保资金账号配置正确。