🚀 AI 一键生成 joinquant 策略代码
立即体验

joinquant 历史财报分析:watch_date 与 stat_date 参数详解与避坑指南

joinquant | 发布时间: 2026/7/23
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: joinquant 历史财报分析:watch_date 与 stat_date 参数避坑

Question: 使用 get_history_fundamentals 查询财务数据时,watch_date 和 stat_date 有什么区别?

解决方案

joinquant 历史财报分析:watch_date 与 stat_date 参数详解与避坑指南

在 JoinQuant(聚宽)量化交易平台中使用 get_history_fundamentals API 进行多报告期财务数据查询时,watch_datestat_date 是控制时间维度的两大关键参数。搞清二者的区别对于规避未来函数准确提取历史财报至关重要。


一、核心区别总览

watch_datestat_date 只能二选一指定,不能同时使用。

参数名称 核心定义 适用场景 未来函数风险
watch_date 观察日期(实际看数据的时点) 回测、模拟实盘、因子选股 低(安全):仅返回在该日期及之前已发布的最新财报
stat_date 统计报告期(财报对应的季度/年份) 财报专题研究、历史报表对比 :直接按报告期查询,若在未披露前使用会引入未来数据

二、参数详细解析与使用逻辑

1. watch_date(观察日期)

  • 含义:模拟真实交易者在某个具体日期(如 2023-05-01)站立的时间点。
  • 逻辑:系统会自动检索在该日期(包含当天)已经发布的最新财报数据。如果某家上市公司尚未披露该期财报,则返回其上一期已披露的数据。
  • 优势:完美规避财报披露延迟带来的未来函数,适合在策略回测中调用。
# 获取 2023-05-01 时点能够看到的最新 4 个季度的财报数据
df = get_history_fundamentals(
    security=['000001.XSHE'],
    fields=[income.total_operating_revenue, balance.cash_equivalents],
    watch_date='2023-05-01',
    count=4,
    interval='1q'
)

2. stat_date(统计日期 / 报告期)

  • 含义:财报所属的会计周期,格式如 '2022q4''2023q1''2022'(需配合 stat_by_year=True)。
  • 逻辑:直接按指定的报告期拉取数据。无论该财报实际是在何时发布的,只要指定了 stat_date,就会精准定位到该报告期。
  • 风险警告:上市公司的财报披露通常有滞后期(如年报/一季报在 4 月底前披露完毕)。如果在 2023-01-15 的回测逻辑中使用了 stat_date='2022q4',由于此时 2022 年四季报尚未披露,就会引入未来函数,导致回测失真。
# 精准查询 2022q1 及其之前的 4 个季度财报数据
df = get_history_fundamentals(
    security=['000001.XSHE'],
    fields=[income.total_operating_revenue],
    stat_date='2022q1',
    count=4,
    interval='1q'
)

三、常见的“坑”与避坑指南

坑 1:在策略回测中使用 stat_date 导致回测虚高

  • 错误写法:在每日调仓逻辑中使用 stat_date=context.current_dt.strftime('%Yq%q')
  • 避坑方式:策略回测和实盘中务必使用 watch_date,并将其设置为 context.previous_datecontext.current_dt

坑 2:同时指定 watch_date 和 stat_date

  • 错误写法:同时传入两个参数。
  • 避坑方式:API 明确要求二者只能指定一个。若要根据发布时间确定切片,传 watch_date;若要分析固定报告期,传 stat_date

坑 3:年度数据与季度数据混淆

  • 避坑方式:若要获取年度数据(如年报),需设置 stat_by_year=True,此时 interval 必须为 '1y'stat_date 必须为年份字符串(如 '2022'),不能传入 '2022q4'

四、总结推荐示例

因子回测策略中的标准安全调用方式:

from jqdata import *

def market_open(context):
    # 推荐使用 watch_date 传入上一交易日或当前日期,确保零未来函数
    df = get_history_fundamentals(
        security=['000001.XSHE', '600000.XSHG'],
        fields=[balance.cash_equivalents, income.total_operating_revenue],
        watch_date=context.previous_date,
        count=4,
        interval='1q'
    )
    # 按股票代码分组处理
    mean_revenue = df.groupby('code')['total_operating_revenue'].mean()