Skip to content

feat(engine): 市場背景注入 — SPY/QQQ/VIX 週漲跌進復盤卡 (refs #37)#145

Merged
atomchung merged 2 commits into
mainfrom
feat/37-market-context
Jul 7, 2026
Merged

feat(engine): 市場背景注入 — SPY/QQQ/VIX 週漲跌進復盤卡 (refs #37)#145
atomchung merged 2 commits into
mainfrom
feat/37-market-context

Conversation

@atomchung

Copy link
Copy Markdown
Owner

這個 PR 做什麼

#129 次線執行序順序 3(#37):卡只有「你做了什麼」,沒有「市場那週在幹嘛」——虧 3% 是選錯股還是大盤本來就跌 3%?買在高點還是買在 QQQ +5% 的相對強勢週?

engine/market_context.py(新,獨立 CLI)

  • fetch 薄層:yfinance 抓日線;離線/未裝 → error 欄誠實退化,絕不 crash 主流程(對齊 fetch_fx/fetch_prices 既有模式)。
  • 計算純函式層(compute_context):吃 {symbol: [(date, close)...]},零 pandas 依賴,離線可測。
  • 語意:window_ret = 窗口前收→窗口末收;ytd_ret 錨在去年最後收盤;VIX 是水平值(last/prev/delta),不當資產報酬;缺錨 → null 不硬算;窗口內沒價的 symbol 誠實缺席。
  • 窗口由呼叫端(SKILL)決定:對帳 = 上次 log date_end → 本次;初診 = 往前 7 天。engine 不猜週期。

SKILL.md + card-spec.md

  • Step 1 順跑指令 + 三個用途:① 卡開頭〔市場那週〕一行(有數據才出,離線整行不出、不硬掰)② 歸因語境(「你砍在 SPY −4% 的恐慌週」)③ Step 2 動機輔助訊號(大漲週進場=FOMO 候選——只輔助選問誰,定性永遠來自回答)。
  • 明確 out of scope:帳戶 vs 大盤的數字級 relative perf 需要每週市值序列(engine 目前沒有)——SKILL 明令別自己算,[Phase 2] 市場背景自動注入:SPY/QQQ/VIX 週漲跌進復盤卡 #37 留 open 追蹤數字版。

測試(第八套)

窗口/YTD 錨點、VIX 水平值、缺資料誠實缺席、亂序輸入、單日窗口、CLI 參數防呆、TR_TEST_NETWORK smoke。run_all.py + CLAUDE.md 鏡像「七套→八套」同步。

掃過的範圍

測試結果

離線八套全綠;TR_TEST_NETWORK=1 smoke 過。

refs #37(語境版落地;數字級 relative perf 留 open)

🤖 Generated with Claude Code

test and others added 2 commits July 7, 2026 09:02
- engine/market_context.py (new): thin fetch layer (yfinance, honest
  degradation offline/uninstalled — error field, never crashes the main
  flow) + pure compute layer (zero-pandas, offline-testable)
  window_ret = prev-close-before-window -> last close in window;
  ytd_ret anchored at last close of prior year; VIX as level (last/prev/
  delta), never treated as an asset return
- SKILL.md Step 1: run after main engine; window = last log date_end ->
  state date_end (reconcile) or 7d back (first run); three uses — card
  header line, attribution context, Step 2 motive auxiliary signal
  (FOMO-candidate on up-week entries); account-vs-SPY numeric relative
  perf explicitly out of scope (needs weekly NAV series, #37 stays open)
- card-spec.md: 〔市場那週〕context line in template (data-present only,
  offline -> line absent, never fabricated)
- tests/test_market_context.py (new, suite 8): anchors, VIX level,
  honest-absence, unsorted input, single-day window, CLI arg guards,
  TR_TEST_NETWORK smoke; run_all.py + CLAUDE.md mirrors 七套->八套

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ardening

Codex (stub-verified findings, all adopted):
- build_output gains 'missing': partial symbol absence leaves error=None,
  callers must not assume all three benchmarks exist; SKILL/card-spec now
  say render-what-you-have, skip the absent ones
- fetch parse wrapped in error-degradation (missing Close -> error, never
  raises: the never-crash header contract); single-symbol Series shape no
  longer probed via .get(sym) (would silently query the date index)
- deterministic fake-yfinance tests: MultiIndex+NaN-column, Series shape,
  missing-Close, download-raise — fetch layer no longer covered only by
  the optional network smoke
- cross-year window semantics locked by test (window_ret and ytd_ret may
  legitimately diverge in sign — correct but unintuitive, pin it)

Gemini: two stale 七套 mirrors outside CLAUDE.md (pre_commit_test_gate.sh
comment+deny message, prd-ledger.md PR checklist) — reworded count-free
so the next suite addition cannot drift them again

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@atomchung

Copy link
Copy Markdown
Owner Author

Triad Review — PR #145(文本模式:Claude / Codex / Gemini)

審查焦點:compute 錨點語意(跨年/單日/缺錨)、yfinance 回傳形狀容錯、離線退化契約、鏡像同步。

⚠️ 單方 findings(Codex 用 stub 實測驗證,全採納;修在 05d81ba)

  1. 部分 symbol 缺席時 error=None 但 benchmarks 不齊(stub 驗證:QQQ 全 NaN → 只回 SPY/VIX)——SKILL/卡面假設三家都在會硬掰。→ 輸出加 missing 契約;SKILL/card-spec 改「有什麼講什麼,缺的略過」。
  2. fetch 形狀防禦不足:單 symbol Series 用 .get(sym) 會誤查日期 index;缺 Close 欄直接 KeyError(違反檔頭「絕不 crash」契約)。→ columns/Series 分支判斷 + 整段解析包 error 退化。
  3. fetch 層只有 optional network smoke 覆蓋 → 加 fake-yfinance deterministic tests ×4(MultiIndex+NaN 欄、Series 形狀、缺 Close、download raise)。
  4. 跨年窗口 window_ret 與 ytd_ret 可符號相反(語意正確但不直覺,兩錨不同)→ 測試鎖住防未來誤改。

Gemini findings(2/2 引文驗證屬實,已修)

  • CLAUDE.md 之外還有兩處「七套」漏網:pre_commit_test_gate.sh(註解+deny 訊息)、docs/prd-ledger.md(PR 檢查清單)→ 改成無數字措辭(「測試沒全過」「以 run_all 總結輸出為準」),下次加套件不會再 drift。
  • 另確認:SKILL 引用的輸出鍵與 engine 實際 JSON 全對齊;〔市場那週〕行不違反「不准 dashboard」禁令(總覽區塊本就是括號行格式);trade_recap 與 market_context 的 fetch 職責分離乾淨。

Claude 方

錨點語意重走一遍(跨年 min-pad、1 月初 end 的去年 12/15 錨、長假 14 天 pad)無誤;VIX 水平值不當報酬。

測試

八套全綠(market_context 套 13 測試);TR_TEST_NETWORK=1 smoke 過;live CLI 實跑驗證(7/3 休市末筆自然落 7/2)。

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.

1 participant