Skip to content

[feat·視覺化] pnl_curve 累積損益曲線 — 「帳面總損益」從一個點延伸成一張圖 #167

Description

@atomchung

來源

owner 丟了一張券商 app 的「報酬日曆」截圖(逐日紅綠色塊網格 + 週趨勢長條)當視覺化參考,討論後拍板:整片色塊網格card-template.html 已定版的設計鐵律衝突(大區塊絕不用語義色當底,綠/紅色塊網格 = 觸犯「多色告警面板」,2026-07-04 triad review 已打過一次)。但延伸出一個更貼合的方向:同一次復盤內,把「帳面總損益」這個單點數字,延伸成一條累積損益曲線——同樣終點 +14 萬,「穩步墊高」vs「一次跳空後打平」vs「坐雲霄飛車回原點」是三種完全不同的行為診斷,比純文字描述更直觀。

資料源(已有一半)

trade_recap.py_port_daily_returns() 為了做 α/β 迴歸,已經重建了復盤期間逐日投組報酬序列(昨日持股 × 今日價),只是算完就丟進迴歸沒有以時間序列流出。

規格

  • 新 engine 函式 pnl_curve(rows, data, market=None):重用 _port_daily_returns,cumprod 成累積報酬曲線。起點錨定 cum_ret=0,終點對齊 overview.total_pnl 那個點。序列 > CURVE_MAX_POINTS(52)天 → 週頻(W-FRI)降採樣,但強制保留最後一天,終點不能漂掉。
  • 只算單一市場(混市場逐日 FX 換算複雜度先不做,沿用 dim_alpha_beta 已選好的 scope market;沒選出 scope 就誠實降級 {"note": "混市場尚未支援"},不隱性猜)。
  • data=None/樣本不足/無交易 → {"note": ...} fail-closed 降級,不硬湊假點。
  • 新增 build_card_data() 頂層欄位 pnl_curve,同步 TR_JSON_KEYS 契約(tests/test_tr_json_contract.py)。
  • 只在 HTML widget 畫(單色細線,依終點正負套 --text-success/--text-danger,不填色塊、不逐點染色——延伸現有損益數字的顏色用法,不是開新的紅綠色塊面板);純文字卡不畫,note 不轉成一句話硬補上卡(不歸 honesty_ledger 管,那是給 Claude 判斷「畫不畫」的旗標)。

事實鏈路(照 CLAUDE.md 連動)

pnl_curve()(engine)↔ build_card_data 契約 ↔ test_tr_json_contract.py TR_JSON_KEYS ↔ SKILL.md Step 1 欄位說明 ↔ card-spec.md 呈現方式段 ↔ card-template.html sparkline 版型參考。

驗收

  • 合成價格序列單元測試(tests/test_price_paths.py):起點錨定 0、終點精確等於複利到底的累積報酬、market 過濾、長序列週頻降採樣仍保留終點、無價格/樣本不足誠實降級。
  • tests/run_all.py 十套全過。
  • card-template.html 加一條 sparkline 範例(帳面總損益格底下),截圖驗過明暗雙模式。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions