3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
你好!你遇到的这个问题是量化新手在使用聚宽财务数据时非常常见的一个“坑”。聚宽的数据并没有错,而是统计口径与普通炒股软件不同。
聚宽的财务数据默认是“单季度”的:
在 JoinQuant 中,indicator 表和 income 表的数据默认都是单季度数据。当你查询 statDate='2020-06-30'(即 2020q2)时,你获取到的 inc_net_profit_year_on_year 是2020年第二季度单季相比于2019年第二季度单季的同比增长率。
炒股软件的数据通常是“累计”的:
同花顺、东方财富等软件上显示的中报(半年报)净利润同比增长率,是**上半年累计(Q1 + Q2)**相比于去年上半年累计的同比增长率。
以你提到的“和佳医疗 (300273.XSHE)”为例:
这就是为什么你看到的数据与炒股软件相差甚远的原因。
既然聚宽提供的是单季度数据,我们需要自己将 Q1 和 Q2 的净利润相加,计算出上半年的累计净利润,然后再计算同比增长率。
以下是完整的 Python 实现代码,你可以直接在聚宽的“研究”模块中运行:
from jqdata import *
import pandas as pd
# 1. 定义查询对象,只查代码和净利润
q = query(income.code, income.net_profit)
# 2. 分别获取 2020年和2019年 Q1、Q2 的单季度净利润
df_2020q1 = get_fundamentals(q, statDate='2020q1')
df_2020q2 = get_fundamentals(q, statDate='2020q2')
df_2019q1 = get_fundamentals(q, statDate='2019q1')
df_2019q2 = get_fundamentals(q, statDate='2019q2')
# 3. 合并并计算 2020年上半年(中报)累计净利润
df_2020 = pd.merge(df_2020q1, df_2020q2, on='code', suffixes=('_q1', '_q2'))
df_2020['net_profit_2020_h1'] = df_2020['net_profit_q1'] + df_2020['net_profit_q2']
# 4. 合并并计算 2019年上半年(中报)累计净利润
df_2019 = pd.merge(df_2019q1, df_2019q2, on='code', suffixes=('_q1', '_q2'))
df_2019['net_profit_2019_h1'] = df_2019['net_profit_q1'] + df_2019['net_profit_q2']
# 5. 将两年中报数据合并到一张表
df_total = pd.merge(df_2020, df_2019, on='code')
# 6. 过滤掉去年同期净利润为负或为0的标的(避免计算增长率时出现异常或失去意义)
df_total = df_total[df_total['net_profit_2019_h1'] > 0]
# 7. 计算累计净利润同比增长率 (%)
df_total['inc_rate_h1'] = (df_total['net_profit_2020_h1'] - df_total['net_profit_2019_h1']) / df_total['net_profit_2019_h1'] * 100
# 8. 筛选同比增长率大于 20% 的标的,并按增长率降序排列
result = df_total[df_total['inc_rate_h1'] > 20].sort_values(by='inc_rate_h1', ascending=False)
# 9. 映射股票名称以便查看
result['name'] = result['code'].map(lambda x: get_security_info(x).display_name)
# 打印前20条结果
print(result[['code', 'name', 'inc_rate_h1']].head(20))
在量化回测中,使用单季度数据(如聚宽默认提供的)往往比使用累计数据更能真实反映企业近期的经营拐点。但如果你需要复刻传统基本面选股策略中的“中报/年报累计增长”,请务必像上面这样手动将单季度数据进行累加计算。