Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
ricequant avatar

Rq Earnings Analysis

  • 1 installs
  • 43 repo stars
  • Updated June 23, 2026
  • ricequant/ricequant-skills

Generate structured Chinese earnings analysis reports from Ricequant JSON datasets via the earnings-analysis report template and generator script.

About

rq-earnings-analysis packages a Ricequant-oriented earnings report workflow for developers and small research stacks automating equity write-ups. The SKILL content defines a full Chinese-language report skeleton—from executive summary through market expectations, management wording, balance-sheet quality, updated investment thesis, valuation, and risk—filled by scripts such as earnings-analysis/scripts/generate_report.py reading a --data-dir of JSON files. Documented inputs include company_info, industry tiers, historical_financials with revenue and profit lines, ROE history, market cap and PE/PB/dividend yield series, and price_window bars for event-window reaction. Agents use it when turning standardized quantitative extracts into citable research memos during diligence or when validating finance-side assumptions before building trading tools, dashboards, or content products. It is template-plus-generator rather than a live market MCP; practitioners must supply correct Ricequant exports.

  • Markdown report template with placeholders: executive summary, financial quality, thesis update, valuation, risks
  • Data contract for generate_report.py: company_info, industry, historical_financials, roe_history, valuation factors, pri
  • Derives YoY/QoQ metrics, margins, cash conversion, leverage, and post-earnings price reaction from JSON inputs
  • Documents dividend_yield bps-to-percent conversion for display
  • Bilingual finance workflow aimed at Ricequant / A-share style identifiers (order_book_id, quarters)

Rq Earnings Analysis by the numbers

  • 1 all-time installs (skills.sh)
  • Ranked #909 of 1,106 Finance & Trading skills by installs in the Skillselion catalog
  • Security screen: MEDIUM risk (skills.sh audit)
  • Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/ricequant/ricequant-skills --skill rq-earnings-analysis

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs1
repo stars43
Security audit1 / 3 scanners passed
Last updatedJune 23, 2026
Repositoryricequant/ricequant-skills

What it does

Generate structured Chinese earnings analysis reports from Ricequant JSON datasets via the earnings-analysis report template and generator script.

Files

SKILL.mdMarkdownGitHub ↗

RQ 股票研究 - 财报分析

核心原则

  • 所有内容必须遵循三阶段流程:数据采集 -> 报告生成 -> HTML 渲染
  • assets/template.md 是唯一报告模板来源;Python 只做数据归一化、指标计算、占位符填充和结构校验
  • Python 只输出结构化 facts / tables / signal rules,不在代码里硬写观点性结论
  • RQData CLI 是财务、估值、价格、公告和一致预期的主源;web_search 只补充 CLI 无法直接提供的实时外部语境
  • 最新财报季度必须从真实 financial 数据中按 info_date <= report-date 自动识别,不能硬写季度
  • “超预期/低于预期”判断必须明确口径,优先使用财报前一致预期和高度相关的卖方点评
  • 研报必须做相关性过滤;行业周报、策略报告不能冒充公司点评
  • 缺失数据时必须明确写“无数据 / 未提供”,不能留空

数据源分工

RQData CLI 负责

  • 公司信息、行业归属、历史财务、ROE、估值与股息率
  • 财报前后价格反应、成交额变化、基准超额收益
  • 一致预期、目标价、卖方研报
  • 正式公告、业绩说明会、财报原文链接

web_search 负责

  • 财报电话会安排、管理层最新外部表态
  • 财报后行业或政策语境
  • RQData CLI 未直接提供、但会影响财报解读的实时背景信息

web_search 禁止替代的内容

  • 财务数字、估值指标、价格数据
  • 正式公告、财报披露日、分红、交易所披露
  • 一致预期和结构化卖方预测

web_search 使用规则

详细字段、来源等级、落盘示例和 fallback 规则见 references/web_search.md

允许补充的内容:

  • 管理层动态、财报电话会、IR 活动安排
  • 行业景气、政策变化、监管动态
  • 财报后几天内的重要公司新闻或权威媒体解读

落盘要求:

  • 所有 web_search 结果必须先写入 web_search_findings.json
  • 只写结构化记录,不把自然语言笔记直接塞进报告
  • 每条记录都必须保留来源、链接、发布时间、检索时间、相关性说明和置信度

硬性规则

以下任一条违反,视为输出失败:

  • [MUST-1] 所有财务数字必须来自 RQData CLI
  • [MUST-2] web_search 不得替代财报、估值、价格、公告和一致预期主源
  • [MUST-3] 金额类数据必须按可读口径展示;原始“元”金额在正文中应换算为“亿元”
  • [MUST-4] 必须保留正式公告原文链接;若原文提取失败,也必须保留失败状态和原文链接
  • [MUST-5] “超预期 / 符合预期 / 低于预期”必须给出口径,不能空喊观点
  • [MUST-6] 每个关键数据点或关键结论都要标 数据来源:XXX,置信度X
  • [MUST-7] 图表若未生成,必须由等价表格或趋势表完成降级,不能让关键章节失真
  • [MUST-8] 低置信度外部信息不得改写核心财务判断
  • [MUST-9] 最终输出必须严格来自模板,不得在脚本中自由拼写整篇报告

确信度评级

  • 5:RQData CLI、交易所公告、上市公司官网、官方监管披露
  • 4:政府 / 监管 / 行业协会 / 官方机构、权威财经媒体
  • 3:一般媒体或二手整理,但来源清晰且与其他来源一致
  • 2:单一来源、细节不完整、时点未充分验证
  • 1:推断、估算窗口、未验证信息

使用规则:

  • 混合结论的置信度取关键来源中的最低值
  • 推断或估计信息不得标成高置信度
  • 低置信度信息只能作为补充背景,不能成为财报结论唯一依据

图表 / 图片需求

当前脚本以趋势表降级交付,但本 skill 仍必须定义最终报告达标所需的图表需求。

  • 图表名称:收入与净利润趋势图
  • 图表目的:展示近 8 个季度累计与单季收入、净利润变化
  • 使用的数据文件:historical_financials.json
  • 关键字段:quarterrevenuenet_profit
  • 建议图表类型:双轴折线或柱线组合
  • 回答问题:增长趋势是否延续,单季拐点是否出现
  • 放置位置:## 财报概览
  • 若图表缺失:保留累计趋势表和单季趋势表
  • 图表名称:盈利能力与质量图
  • 图表目的:展示毛利率、ROE、现金转化率和资产负债率变化
  • 使用的数据文件:historical_financials.jsonroe_history.json
  • 关键字段:gross_profitrevenuereturn_on_equity_weighted_averagecash_from_operating_activitiestotal_assetstotal_liabilities
  • 建议图表类型:折线图或分组柱状图
  • 回答问题:财务质量是在改善还是恶化
  • 放置位置:## 财务质量与资产负债表
  • 若图表缺失:保留财务质量表和 ROE 取值表
  • 图表名称:预期修正与价格反应图
  • 图表目的:展示财报前后预期变化与 1D / 3D / 5D 股价反馈
  • 使用的数据文件:consensus.jsonprice_window.jsonbenchmark_window.json
  • 关键字段:comp_con_*con_targ_priceclose
  • 建议图表类型:对比柱图 + 收益曲线
  • 回答问题:市场是否把这次财报解读为正面还是负面
  • 放置位置:## 市场预期、卖方反馈与价格反应
  • 若图表缺失:保留预期对比表、价格反馈看板和超额收益表

目标产出

  • 报告长度:8-12 页
  • 输出文件:
  • Markdown 报告
  • HTML 报告(若本地已安装渲染器)
  • 输出目录必须由 --data-dir / --output 指定,不能写死固定路径

目录结构

earnings-analysis/
├── SKILL.md
├── scripts/
│   ├── extract_announcements.py
│   └── generate_report.py
├── assets/
│   └── template.md
└── references/
    ├── data_contract.md
    └── web_search.md

输入文件契约

原始数据目录由 --data-dir 指定,脚本会按下列文件名查找输入:

  • company_info.json
  • industry.json
  • historical_financials.json
  • roe_history.json
  • market_cap.json
  • pe_ratio.json
  • pb_ratio.json
  • dividend_yield.json
  • price_window.json
  • benchmark_window.json
  • consensus.json
  • research_reports.json
  • announcement_raw.json
  • announcement_extracts.json(可选)
  • web_search_findings.json(可选)

完整字段说明见 references/data_contract.md

工作流

步骤 1:准备参数

REPORT_DATE="${REPORT_DATE:-2026-04-07}"
ORDER_BOOK_ID="${ORDER_BOOK_ID:-600519.XSHG}"
PRICE_WINDOW_START="$(python3 - <<PY
from datetime import date, timedelta
report_date = date.fromisoformat("${REPORT_DATE}")
print((report_date - timedelta(days=45)).isoformat())
PY
)"
CONSENSUS_START="$(python3 - <<PY
from datetime import date, timedelta
report_date = date.fromisoformat("${REPORT_DATE}")
print((report_date - timedelta(days=90)).isoformat())
PY
)"
FACTOR_DATE="$(python3 - <<PY
import json
import subprocess
from datetime import date, timedelta

def has_non_empty_factor(day: str) -> bool:
    payload = json.dumps({
        "order_book_ids": ["${ORDER_BOOK_ID}"],
        "factor": "market_cap",
        "start_date": day,
        "end_date": day,
    }, ensure_ascii=False)
    rows = json.loads(subprocess.check_output(
        ["rqdata", "stock", "cn", "financial-indicator", "--payload", payload, "--format", "json"],
        text=True,
    ))
    return any(isinstance(row, dict) and row.get("market_cap") not in (None, "", "null") for row in rows)

cursor = date.fromisoformat("${REPORT_DATE}")
for _ in range(15):
    if has_non_empty_factor(cursor.isoformat()):
        print(cursor.isoformat())
        break
    cursor -= timedelta(days=1)
else:
    raise SystemExit("最近 15 个自然日都未找到非空 market_cap 因子日期")
PY
)"
HISTORY_START_QUARTER="$(python3 - <<PY
from datetime import date
report_date = date.fromisoformat("${REPORT_DATE}")
print(f"{report_date.year - 2}q1")
PY
)"
HISTORY_END_QUARTER="$(python3 - <<PY
from datetime import date
report_date = date.fromisoformat("${REPORT_DATE}")
print(f"{report_date.year}q4")
PY
)"

DATA_DIR="${DATA_DIR:-$HOME/rq_equities_reports/earnings_analysis}"
OUTPUT_MD="${OUTPUT_MD:-$DATA_DIR/earnings_analysis_${ORDER_BOOK_ID}_${REPORT_DATE}.md}"

步骤 2:采集公司、财务、估值与价格数据

mkdir -p "$DATA_DIR"

rqdata stock cn instruments --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"]
}" --format json > "$DATA_DIR/company_info.json"

rqdata stock cn industry --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"date\": \"$REPORT_DATE\",
  \"level\": 0,
  \"source\": \"citics_2019\"
}" --format json > "$DATA_DIR/industry.json"

rqdata stock cn financial --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"fields\": [\"revenue\", \"net_profit\", \"gross_profit\", \"cash_from_operating_activities\", \"total_assets\", \"total_liabilities\"],
  \"start_quarter\": \"$HISTORY_START_QUARTER\",
  \"end_quarter\": \"$HISTORY_END_QUARTER\",
  \"statements\": \"all\"
}" --format json > "$DATA_DIR/historical_financials.json"

rqdata stock cn financial-indicator --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"factor\": \"return_on_equity_weighted_average\",
  \"start_date\": \"$CONSENSUS_START\",
  \"end_date\": \"$FACTOR_DATE\"
}" --format json > "$DATA_DIR/roe_history.json"

rqdata stock cn financial-indicator --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"factor\": \"market_cap\",
  \"start_date\": \"$FACTOR_DATE\",
  \"end_date\": \"$FACTOR_DATE\"
}" --format json > "$DATA_DIR/market_cap.json"

rqdata stock cn financial-indicator --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"factor\": \"pe_ratio\",
  \"start_date\": \"$FACTOR_DATE\",
  \"end_date\": \"$FACTOR_DATE\"
}" --format json > "$DATA_DIR/pe_ratio.json"

rqdata stock cn financial-indicator --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"factor\": \"pb_ratio\",
  \"start_date\": \"$FACTOR_DATE\",
  \"end_date\": \"$FACTOR_DATE\"
}" --format json > "$DATA_DIR/pb_ratio.json"

rqdata stock cn financial-indicator --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"factor\": \"dividend_yield\",
  \"start_date\": \"$FACTOR_DATE\",
  \"end_date\": \"$FACTOR_DATE\"
}" --format json > "$DATA_DIR/dividend_yield.json"

rqdata stock cn price --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"start_date\": \"$PRICE_WINDOW_START\",
  \"end_date\": \"$REPORT_DATE\",
  \"fields\": [\"close\", \"volume\", \"total_turnover\"],
  \"adjust_type\": \"post\"
}" --format json > "$DATA_DIR/price_window.json"

rqdata index price --payload "{
  \"order_book_ids\": [\"000300.XSHG\"],
  \"start_date\": \"$PRICE_WINDOW_START\",
  \"end_date\": \"$REPORT_DATE\",
  \"fields\": [\"close\"]
}" --format json > "$DATA_DIR/benchmark_window.json"

步骤 3:采集市场预期、研报与公告

rqdata stock cn consensus --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"start_date\": \"$CONSENSUS_START\",
  \"end_date\": \"$REPORT_DATE\",
  \"report_range\": 3
}" --format json > "$DATA_DIR/consensus.json"

TARGET_FISCAL_YEAR="$(python3 - "$DATA_DIR/historical_financials.json" "$REPORT_DATE" <<'PY'
import json
import sys
from datetime import date, datetime
from pathlib import Path

def parse_iso_date(value):
    if not value:
        return None
    for fmt in ("%Y-%m-%d", "%Y-%m-%d %H:%M:%S"):
        try:
            return datetime.strptime(str(value)[:19], fmt).date()
        except ValueError:
            continue
    return None

rows = json.loads(Path(sys.argv[1]).read_text())
report_date = date.fromisoformat(sys.argv[2])
best = None
for row in rows:
    info_date = parse_iso_date(row.get("info_date"))
    quarter = row.get("quarter")
    if not info_date or info_date > report_date or not quarter:
        continue
    if best is None or quarter > best:
        best = quarter
print(best[:4] if best else report_date.year)
PY
)"

rqdata stock cn research-reports --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"fiscal_year\": \"$TARGET_FISCAL_YEAR\",
  \"start_date\": \"$CONSENSUS_START\",
  \"end_date\": \"$REPORT_DATE\",
  \"date_rule\": \"create_tm\"
}" --format json > "$DATA_DIR/research_reports.json"

ANNOUNCEMENT_START="$(python3 - <<PY
from datetime import date, timedelta
report_date = date.fromisoformat("${REPORT_DATE}")
print((report_date - timedelta(days=45)).isoformat())
PY
)"

rqdata stock cn announcement --payload "{
  \"order_book_ids\": [\"$ORDER_BOOK_ID\"],
  \"start_date\": \"$ANNOUNCEMENT_START\",
  \"end_date\": \"$REPORT_DATE\"
}" --format json > "$DATA_DIR/announcement_raw.json"

步骤 4:提取公告原文片段

python3 earnings-analysis/scripts/extract_announcements.py \
  --stock "$ORDER_BOOK_ID" \
  --data-dir "$DATA_DIR" \
  --report-date "$REPORT_DATE"

要求:

  • 若公告源站可读,会生成 announcement_extracts.json
  • announcement_extracts.json 保留 raw_sectionssummaries、失败状态和原文链接
  • 年报 / 中报正文优先抽取 company_intromanagement_discussionrisk_warningoutlook
  • 若源站阻断或 PDF 不可读,也不能静默丢失

步骤 4.5:当前 LLM 回写 announcement_extracts.json summary

  • 直接读取 records[].raw_sections.*
  • 回写 records[].summaries.*
  • 不额外创建 announcement_summaries.json
  • summaries.* 必须是客户可读表述,不得直接复制 raw_sections.* 原文、不允许粘贴 PDF 抽取碎片
  • 这一步必须由当前 LLM 完成;generate_report.py 不负责代写公告正文描述
  • 若年报 / 中报已有可用 raw_sections.*,但 summaries.* 仍为空或只是原文截断,视为 workflow 未完成,不进入成稿阶段

步骤 5:补充 web_search 实时信息

仅当需要补充财报电话会、管理层外部表态、行业或政策语境时,才执行此步骤。

  • 检索结果必须先写入 web_search_findings.json
  • 只能补充 RQData CLI 直接缺失的信息
  • 不得把新闻稿当作财务主数据

步骤 6:生成结构化 Markdown 草稿

python3 earnings-analysis/scripts/generate_report.py \
  --stock "$ORDER_BOOK_ID" \
  --data-dir "$DATA_DIR" \
  --report-date "$REPORT_DATE" \
  --output "$OUTPUT_MD"

说明:

  • 该脚本生成结构化事实草稿,包含表格、信号、研报摘录、公告原文链接和可选外部实时补充信息
  • 不应在 Python 里写“因此看多 / 看空”这类分析句
  • 若已产出 announcement_extracts.json,报告只消费其中 summaries
  • 不允许在报告生成阶段根据 raw_sections 现写客户可读公告摘要;summaries 缺失时只能明确提示缺失

步骤 7:渲染 HTML

脚本会优先尝试本地安装的 rq-report-renderer,若不可用则回退到仓库内 report-renderer/scripts/render_report.py;两者都不可用时保留 Markdown 并打印警告。

阶段门控

阶段 1:数据采集完成标准

  • 财务、价格、估值、一致预期、研报和公告原始文件齐全
  • 最新财报季度已按 info_date <= report-date 自动识别
  • 若使用 web_searchweb_search_findings.json 已结构化落盘

阶段 2:研究核查完成标准

  • 已核查财报季度、披露日、价格窗口、预期快照和相关公告
  • 已核查 announcement_extracts.json -> summaries.* 为当前 LLM 回写的客户可读摘要,不是原文截断
  • 已确认卖方研报相关性,不包含行业周报 / 策略报告污染
  • 公告原文提取成功或失败状态都已保留

阶段 3:成稿完成标准

  • 模板占位符全部替换
  • 关键章节完整
  • 关键结论后有来源和置信度
  • 公告章节中的文字描述仅来自 announcement_extracts.json -> summaries.*
  • 图表未生成时,表格降级仍能覆盖趋势、质量和价格反应

模板规则

  • 报告必须严格基于 template.md 生成
  • 占位符采用 [[TOKEN]] 语法,不使用 Jinja
  • 当前模板仅允许以下占位符:
  • [[REPORT_DATE]]
  • [[COMPANY_NAME]]
  • [[STOCK_CODE]]
  • [[LATEST_QUARTER]]
  • [[EVENT_DATE]]
  • [[EXEC_SUMMARY]]
  • [[INFO_PANEL]]
  • [[EARNINGS_OVERVIEW]]
  • [[EXPECTATION_AND_REACTION]]
  • [[ANNOUNCEMENT_SECTION]]
  • [[FINANCIAL_QUALITY]]
  • [[THESIS_UPDATE]]
  • [[VALUATION_SECTION]]
  • [[RISK_SECTION]]
  • [[APPENDIX]]

报告质量要求

  • 完整包含模板中的主章节
  • 关键结论必须基于真实财报、预期和价格反应数据
  • “超预期 / 符合预期 / 低于预期”必须给出口径
  • research_reports.json 中的 summary 必须作为卖方文字解释层输出
  • 公告原文链接必须保留
  • 公告正文描述必须先由当前 LLM 回写到 announcement_extracts.json -> summaries.*
  • dividend_yield 原始值单位为 bps,报告中必须换算为百分比
  • 若最新财报季度、关键财务指标或价格窗口缺失,生成器应直接失败
  • 若财报前后一致预期字段在 *_t 为空、但在更靠后的 forecast slot 非空,生成器必须继续核查并读取实际可用口径,不能机械把财报后预期写成“无数据”
  • 若使用 web_search,必须保留来源名称、链接、发布时间和检索时间

阶段验收清单

  • [ ] 数据采集 -> 报告生成 -> HTML 渲染三阶段都按顺序执行
  • [ ] RQData CLIweb_search 的边界没有混用
  • [ ] 财报原文、预期对比、价格反应都有真实数据支撑
  • [ ] announcement_extracts.json -> summaries.* 已由当前 LLM 回写成客户可读内容,而不是原文截断
  • [ ] 卖方研报做过相关性过滤
  • [ ] 公告原文链接和提取状态都保留
  • [ ] 图表未生成时,表格降级仍覆盖核心问题
  • [ ] Markdown / HTML 报告达到 8-12 页目标质量

常见错误

  • 使用仓库级 utils/detect_latest_quarter.py
  • financial-indicator 误写成 fields + start_quarter/end_quarter
  • 财报后分析却没有财报前预期口径
  • 看到 consensus*_t 为空,就直接把财报后预期写成“无数据”,没有继续核查 *_t1 / *_t2
  • 把行业周报、策略报告直接当成公司财报点评写进正文
  • web_search 替代财报、估值、价格、公告和一致预期主源

Related skills

FAQ

Is Rq Earnings Analysis safe to install?

skills.sh reports 1 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.