Skip to content

feat: 新增金融事实语义封套 FinancialFact 并接入行情/财务能力 (close #24) - #82

Open
xuilen wants to merge 3 commits into
helsome:mainfrom
xuilen:feat/financial-fact-envelope
Open

xuilen wants to merge 3 commits into
helsome:mainfrom
xuilen:feat/financial-fact-envelope

Conversation

@xuilen

@xuilen xuilen commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

改了什么 / 为什么

为关键行情、K 线、估值与财报指标增加 FinancialFact 语义封套,保留数据时点、获取时点、币种、单位、价格复权口径、财报期间及未知字段,避免把缺失元数据当作已知事实。对应 #24。

本次更新已 rebase 最新 main 并解决冲突,保留主干的 evidence 元数据、报价 provider 结果接线、canonical instrument identity 和 provenance 毫秒时间单位。

按照 review:

  1. 身份契约:fact factory 优先使用 payload 上的 canonical instrumentId;允许调用方提供已解析的 canonical fallback。两者都缺失时显式记录 instrumentId: "unknown" 与 unknown 字段,不再将 NVDA.US 之类 provider symbol 当作 canonical ID。
  2. Provenance 真实映射:market-quote.ts 在 fetched.provenance 存在时优先沿用其真实的 providerId、providerName、instrumentId 与 fetchedAt,不再固定硬编码 'longbridge' 或使用本地当前时钟冒充缓存数据的获取时点。
  3. 时效语义:新增 resolveFactTiming() 映射,delayed === true 映射为 delayed,delayed === false 映射为 live,缺失或未声明时保留 unknown,绝不猜测。

可复现测试报告

环境:Windows / Bun 1.4.2 / Node 24.20.0。无 UI 变化。

bun test packages/core packages/shared/src/capabilities
→ 148 pass / 0 fail,17 files,433 expect() calls

bun run typecheck
→ core / i18n / shared / ui / electron 全部 exit 0

git diff upstream/main HEAD --check
→ exit 0

新增测试覆盖:

  • canonical identity 回归:stamped identity、缺失 identity 显式 unknown、调用方 fallback、不覆盖已有 canonical ID,以及报价 capability 的 provenance/facts 身份一致性。
  • provenance 真实映射回归:覆盖非 Longbridge(mock massive)、delayed: true、旧缓存 fetchedAt、未声明保留 unknown,以及 delayed: false 映射为 live。
  • 保留的主干测试验证 provenance.marketTime 使用毫秒。

本次按 review 要求重跑 core + capability focused tests,不将其描述为全仓 unit tests 或真实 provider E2E。没有运行真实行情服务、交易或 UI 测试。

已知边界

  • 没有上游 canonical identity 的数据将明确标为 unknown,不根据 symbol 猜测身份。
  • 不改变原有 data/provenance 契约,facts 为可选的附加字段。
  • 没有扩大到真实 provider E2E、交易或 UI 功能。

@helsome helsome left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

测试报告格式本身合格,但这条现在有一个需要先修的主干兼容问题:刚合入的 #59 已建立 canonical instrument identity,并在行情等结构上携带 instrumentId。你当前 quoteToFacts / klineToFacts 仍直接把 provider symbol(例如 NVDA.US)写成 FinancialFact.instrumentId,会把 canonical identity 又退回 ticker/provider symbol,导致 evidence/fact 关联出现两套身份。

请先 rebase 最新 main,并让 fact factory 优先使用上游 canonical instrumentId;只有确实没有 canonical identity 时才显式 fallback/unknown,不要把 symbol 冒充 canonical id。随后用 Bun 1.4.2 重跑现有 core + capability focused tests 即可。另外你报告里的 Windows path baseline 已被刚合入的 #70 修过,rebase 后请更新这一条测试结果。无需扩大成真实 provider E2E。

@xuilen
xuilen force-pushed the feat/financial-fact-envelope branch from 985fde3 to 907310c Compare October 18, 2026 04:32

@helsome helsome left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

旧 canonical identity 阻断已修复,但新增 facts 仍未沿用 getQuoteResult 的真实 provenance。market-quote.ts:48–53 固定 provider='longbridge'、timing='live',并以当前时钟生成 retrievedAt;合法的非 Longbridge、delayed 或缓存 fetchedAt 返回会与前面 reportProvider 的真实来源矛盾。请优先映射 fetched.provenance,未知时效保留 unknown,并补非 Longbridge、delayed、旧 fetchedAt 的确定性回归。本结论为源码及 ProviderProvenance 契约核对,不声称已执行真实 provider 请求。

@xuilen

xuilen commented Oct 18, 2026

Copy link
Copy Markdown
Contributor Author

已根据 review 意见完成真实 provenance 的严格映射与确定性回归测试:

  1. Provenance 映射:market-quote.ts 在 fetched.provenance 存在时优先沿用其真实的 providerId、providerName、instrumentId 与 fetchedAt,不再固定硬编码 'longbridge' 或使用本地当前时钟冒充缓存数据的获取时点。
  2. 时效与未知判定:新增 resolveFactTiming() 映射,delayed === true 映射为 delayed,delayed === false 映射为 live,缺失或未声明时保留 unknown,绝不猜测。
  3. 确定性测试回归:在 packages/shared/src/capabilities/manifests.test.ts 中新增 3 组单测(非 Longbridge / delayed / 缓存旧 fetchedAt 映射、未声明保留 unknown、delayed: false 映射为 live)。
  4. 验证结果:
    • bun test packages/core packages/shared/src/capabilities → 148 pass / 0 fail,433 expect() calls
    • bun run typecheck → 全部工作区 exit 0
    • git diff upstream/main HEAD --check → exit 0

helsome commented Oct 18, 2026

Copy link
Copy Markdown
Owner

同步最新 main:#353 已合入(038f20cf2d87e3575ffbe5469967bdf6ef960dc8),现在已有免 API key 的 Yahoo Finance 备用数据源。请同步 main 后复用现有 provider router / market-data 接口,不再把支持范围内的行情验收统一卡在 Longbridge/Massive 凭证上。

支持范围是美股延迟报价、日/周 K 线和简要公司资料;不支持券商账户/持仓、财报、新闻、期权及分钟行情。保留实际 provider、时间与 delayed 标记,不能用缺失数据冒充 0 或“没有事件”。文档明确它是非官方、个人使用范围的接口,可能限流。

针对本 PR:请用 Yahoo 返回结果核对 FinancialFact 的 canonical instrument、实际 provider、fetchedAt 与 delayed 映射,避免免费源被标为 Longbridge 或实时数据。

参考:接入说明 · 适配器。请区分 fixture 与真实联网结果;连接卡显示 connected 本身不证明实际取数成功。此评论同步新基线,不替代原有 review 或验收结论。

xuilen and others added 3 commits October 19, 2026 15:50
定义统一的 FinancialFact 封套, 使每个金融事实(行情/K线/财务指标/估值)都携带:
- 规范化 instrumentId、metric、value、结构化 unit(currency/percent/basis-points/ratio/shares/scaled)
- 原生 currency, 以及 asOf(数据自身时间戳) 与 retrievedAt(抓取时间) 分离, 绝不用本地 Date.now() 冒充 asOf
- timing(live/delayed/eod/historical) 与 exchangeTimezone/marketSession 区分实时性
- 财务事实的 FiscalPeriod(quarter/fy/ttm/annual) 结构化解析
- raw/split-adjusted/dividend-adjusted 调整口径显式标记, 默认 unknown 而非猜测
- FX 换算 convertCurrency 保留原生 value/currency 与换算来源/汇率/汇率时点
- computeStale 按 timing 判定 stale, 供 UI/Agent 识别过期数据

将封套接入 quote/kline/financials/valuation 四个能力 manifest, 使 summary 能回答"何时/何种货币/何种口径"。缺省元数据一律显式标记 unknown, 绝不猜测。

新增 27 个单测(computeStale/convertCurrency/isPriceSeries/markUnknown/describeFact 及各 factory 映射), 全部通过。
@xuilen
xuilen force-pushed the feat/financial-fact-envelope branch from 8991827 to 9dc856a Compare October 19, 2026 08:30
@xuilen

xuilen commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

@helsome Thanks for the review!

  1. Rebase & Sync: Rebased onto upstream main (7ddc3c6, including feat(providers): add a no-key Yahoo Finance US market-data provider #353 and fix: 修复 Yahoo 行情来源、失败状态与昨收基准 #355).
  2. Provider & Timing Mapping:
    • Extracted provider-aware canonical resolution (resolveCanonicalInstrument(symbol, providerId)), correctly resolving bare symbols (e.g. AAPL under yahoo mapping to XNAS:AAPL) while preserving fallback logic.
    • Removed hardcoded 'longbridge' from market-kline.ts and company-profile.ts; accurately propagate dynamic provider provenance, cache-faithful fetchedAt, and map delayed: true -> timing: 'delayed' so free sources are never tagged as Longbridge or real-time.
  3. Deterministic Tests: Added regression tests in manifests.test.ts and instruments.test.ts verifying that Yahoo quotes and candles produce facts with provider: 'yahoo', timing: 'delayed', instrumentId: 'XNAS:AAPL', and matching timestamps.

All 1,348 shared package tests and workspace-wide bun run typecheck pass cleanly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants