Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions evals/EVALS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
| B14 | `honesty_ledger` 列 `unrealized_coverage` 時,卡上必講「未實現僅反映 `priced_n`/`held_n` 檔持倉,缺現價:…」;不可讓部分覆蓋的未實現金額看起來像完整數字 | honesty_ledger / SKILL Step 3 gate(#82) |
| B15 | `honesty_ledger` 列 `sector_attribution` 時,卡上必補一句「這幾檔有 driver 標籤但查無板塊 ETF 對照,超額被歸入『選股』」;**即使 α 面板因樣本不足/不顯著整塊沒出也要講**(揭露不可只活在 α 面板) | card-spec α/拆帳段 / honesty_ledger(#92) |
| B16 | `honesty_ledger` 非空時,每個列出的 `key` 卡面敘事都有對應人話(B6/B14/B15 是 alpha_credibility/unrealized_coverage/sector_attribution 三個 key 的具體講法,其餘 key 同規格);ledger 有列、卡面沒交代 = fail(卡面 ↔ ledger 對帳,非審風格) | SKILL.md Step 3 self-check gate(#82) |
| B17 | 現金(#171,讀 `card.cash`):`reliable=true` 才把現金講進卡(現金佔帳戶 % + `recent_net_deposit` 非 0 時的入金判讀「加深還是解集中度」),用對帳單語言不裸奔 `cash_weight`;`reliable=false`(`honesty_ledger` 列 `cash_reliability`)**不准把盲算佔比當真數字**,只誠實帶一句「現金我只能盲估、給我對帳單餘額才算得準」。無錨點且淨買入(weight=null)= 卡上不冒現金數字也不空吠 | card-spec 現金與入金判讀 / honesty_ledger(#171) |

## C · Goal-hiding(card-spec 拆檔的驗證)

Expand Down
5 changes: 4 additions & 1 deletion skills/fomo-kernel/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ python3 engine/problems.py stats --today <今天> --rules ~/.trade-coach/rules.j
(snapshot 語意 = 該日**收盤後**狀態,同日交易視為已含在宣告數字內。)
- **已有帳本、又丟來新快照 → 先 `reconcile`,不要直接 append**:`python3 engine/ledger.py reconcile /tmp/pos.json` 會列宣告 vs 推導的差異——一致 = 對帳通過(卡上可標「帳本已對帳 ✓」);不一致 = 把差異講給用戶聽(「我推 NVDA 40 股,你說 35——中間可能有我沒看到的交易」),他確認後以**他的宣告為準**:`append-snapshot --source reconciled`。這是「數據準確」的機制:每丟一次快照 = 帳本自我修復一次。
- **交易 CSV**(標準化後)→ 除了餵 `trade_recap.py`,同時記帳:`python3 engine/ledger.py append-trades <標準化CSV>`(自動去重,每週增量匯入、重疊期重複匯入都安全);記完帳接著排出場追蹤:`python3 engine/revisit.py enqueue-from-ledger`(掃清倉/大減倉 → 30/60/90 佇列,去重、重跑安全)。enqueue 完**再跑一次 `revisit.py scan`**,讀輸出的 **`recent_exits`**(出場 ≤14 天、金額大者先)——這是 Step 2(d) 賣出理由 capture 的候選集(#136:「為什麼賣」只有出場後兩週內問得到,不可回補;空 = 該段靜默跳過)。enqueue 輸出的 `new` 只是「本次新排入」的參考訊號,**capture 候選一律以 `recent_exits` 為準**——上週中斷沒問到的、當週超過限額的,窗口內這裡還會再出現。
- **💵 現金餘額錨點(#171,讓「這筆入金該不該部署」通電)**:交易 CSV 只記部位、記不到帳戶閒置現金——沒有它,`cash_weight` 算不出(引擎降級標不可信,見 Step 1 `honesty_ledger`)。所以 Step 0 順手抓一次**當前現金餘額**:對帳單/持倉頁多半有一行「Cash / 現金 / 可用餘額」——你直接讀出來;讀不到就用 `AskUserQuestion` 問一句「對帳單上的現金餘額大約多少?(想看帳戶層現金比重/入金判讀才需要;略過也能出卡)」。拿到就組 JSON 餵引擎:`TR_CASH='{"as_of":"<對帳單日期>","amount":<數字>,"currency":"USD"}'`(混幣各幣別現金分開;台股用 TWD)——引擎以錨點為準(對付 CSV 非從開戶完整),其後現金流才疊加。**入金判讀(`recent_net_deposit`)要看得到存提款流水**:標準化 CSV 時若來源有 deposit/withdrawal/股息/利息/費用列,連同 `Amount` 欄一起留著(格式見 `mock/sample_noisy_broker.csv`),引擎才算得出本期外部淨流入;來源沒有就只靠錨點給比重,判讀那句靜默跳過。
- **snapshot-only(只有快照、還沒有交易紀錄)**:行為診斷跑不了(那需要交易紀錄——誠實講,別硬掰),但出**開帳體檢卡**:用 `holdings` JSON 的成本權重 + 你的世界知識 driver map 講持倉結構(集中度/賽道/sizing,標明「成本基礎」),AI 猜 thesis(Step 2(c))照走,記憶迴圈當場啟動;`integrity` 非空(oversell/壞行)一律如實帶上卡。收尾邀請:「之後把交易紀錄丟給我,攤平/出場/盈虧比這些行為診斷就會解鎖」。
- **帳本誠實檢查**:`holdings` 輸出的 `counts.skipped_lines > 0` = 帳本檔有壞行(可能是中斷寫入)——**如實告訴用戶**、別當帳本完整;修復法就是請他丟一張最新持倉截圖走 reconcile(新錨點蓋過可疑歷史)。(`ledger.py` 純標準庫,不需要 venv——跟 `trade_recap.py` 的 ModuleNotFoundError 提示無關。)
- ⚠️ **過渡期規則**:錨點帶入的持倉 engine 看不到(CSV 無該檔交易),所以 ledger 的 cycle_id 與 engine state 的 cycle_id 可能不同——**theses.jsonl 綁定一律仍照抄 engine state 的 cycle_id**(收尾 part 2 的既有規則,CLI 會驗格式),ledger 的 cycle_id 只供帳本自身追蹤。
Expand All @@ -115,6 +116,7 @@ TR_JSON=1 TR_STATE_OUT=~/.trade-coach/last_state.json python3 engine/trade_recap
# TR_STATE_OUT → 寫一份薄 state(對帳用),跟 TR_JSON 平行,可同時設
# TR_PREV_END=<log 最後一筆 date_end> → 對帳模式必帶(#137):問題帳的行為型事件只取其後的
# 新交易(不會把三個月前的舊攤平每週重複入帳);初診不設 = 全期補齊,問題帳統計冷啟動
# TR_CASH='{"as_of":..,"amount":..,"currency":..}' → 現金餘額錨點(#171,Step 0 抓的);設了 cash_weight 才可信,不設引擎降級標不可信
# 都不設 → 印預設人話卡(README quickstart 用)
# TR_DEBUG=1 → 在預設輸出補回 5 維 severity raw 表(開發/驗證用,絕不上卡)
```
Expand All @@ -127,8 +129,9 @@ TR_JSON=1 TR_STATE_OUT=~/.trade-coach/last_state.json python3 engine/trade_recap
- **`alpha_beta_breakdown` / `payoff_attribution` / `ticker_diagnosis`**:完整數字,你拿去組敘事。
- **`dims_raw`**:5 維行為診斷(每維 severity 0–1)— **別整張攤出來**,用「一句人話」帶過非 headline 的維度(SKILL 鐵律:不放 5 維小數表)。
- **`overview.unrealized_coverage`**:未實現只加總抓得到現價的持倉(`priced_n`/`held_n`/`unpriced`)——讀這欄拿數字,**該不該揭露交給 `honesty_ledger` 統管**(不用自己記何時補)。
- **`cash`**(#171 帳戶現金):`{balance, weight, source, reliable, recent_net_deposit}`。`reliable=true`(有 `TR_CASH` 錨點)才把 `weight`(現金佔帳戶比重)+ `recent_net_deposit`(本期外部淨入金,判「這筆錢部署了沒/解不解集中度」)講進卡;`reliable=false`(無錨點)是靠交易流水盲算,`weight` 多半 `null`(算不出就不上卡),該不該揭露一樣交 `honesty_ledger`。講法照 card-spec「現金與入金判讀」段。
- **`currency_meta`**:聚合幣別與匯率(💱 Display currency 段的資料源)——`aggregate_currency`(overview / what_if / `ticker_diagnosis` 金額等聚合數字的幣別)、`mixed`、`fx`(兌 USD)、`pnl_by_currency`(原幣分桶)、`fx_error`/`alpha_beta_note`。台股/混幣組合寫卡前**先讀這欄**,金額才不會標錯幣;混幣時單檔原幣金額用 `pnl_by_currency` 對照、或由你按 `fx` 反換算。
- **`honesty_ledger`**(#82:誠實點的單一事實源):engine 已聚合好這張卡**必須交代**的誠實缺口清單(空 list = 無缺口),每項 `{key, status, data}`,涵蓋 α 不可信 / 板塊歸因不全 / 未實現缺價 / 未分類 driver / 賣超 / 混幣。**engine 判定「該講什麼」,你只管照 card-spec 的講法融入敘事「怎麼講」**;出卡前逐項核對(Step 3 gate)——取代了散在各欄位「自己記得哪些該揭露」的自律。
- **`honesty_ledger`**(#82:誠實點的單一事實源):engine 已聚合好這張卡**必須交代**的誠實缺口清單(空 list = 無缺口),每項 `{key, status, data}`,涵蓋 α 不可信 / 板塊歸因不全 / 未實現缺價 / 未分類 driver / 賣超 / 混幣 / 現金無錨點。**engine 判定「該講什麼」,你只管照 card-spec 的講法融入敘事「怎麼講」**;出卡前逐項核對(Step 3 gate)——取代了散在各欄位「自己記得哪些該揭露」的自律。
- **alpha/beta**:贏大盤多少、其中多少只是「膽子大(高 beta)」、真本事(Jensen's α)剩多少。`excess_split` 把「贏大盤」機械拆成 **押對賽道(allocation)+ 板塊內選股(selection)**,兩項相加恆等於贏大盤 pp——這兩個數是會計恆等式、不需統計顯著,**永遠可講**;`alpha_stat` 給 α 的 95% 區間 / t 值 / 分級(顯著與否),語氣照它走。
**per-market(混市場組合必讀,#129)**:`alpha_beta_breakdown.scope` 非 null = 組合跨市場,α/β 已按市場分算(US→SPY、TW→台股加權指數),**頂層數字僅含 `scope` 那個市場的部位**——卡上 α/β 段要**兩行並列**(每市場一行,各含資金佔比、各對各的大盤、各自的顯著性語氣),讀 `by_market`;**絕不把兩個市場的 α 加總或平均**(不合成總 α)。台股部位的拆帳 `coverage=0`(無板塊對照、按大盤計)→ 只講「贏/輸台股大盤 X pp」,不拆賽道/選股;`by_market` 內某市場帶 `note`(如 `^TWII` 沒抓到價)→ 該行誠實寫「對照基準抓不到價,本期不判」。單一市場組合 `scope=null`,一切照舊。
- **結構化 state(`TR_STATE_OUT`)**:給對帳用的薄 JSON,讀這幾個欄位 ——
Expand Down
6 changes: 5 additions & 1 deletion skills/fomo-kernel/card-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,13 @@
- **鏡片引言別當結語**。結尾突然冒「鏡片原則:…」像老師訓話,交易者「差點關掉」。要嘛融進敘事,要嘛不用。
- **規矩是機械的,不是自我喊話**。「動手前問自己…」沒用(沒人下單時覺得自己會賠)。要給「不靠當下忍住」的機制:「虧損部位一律不加碼,想加先整筆賣掉隔天重買」。

**誠實點照 `honesty_ledger` 講(#82)**:engine 已把這張卡必講的誠實缺口聚合成 `honesty_ledger`(空=無缺口)——**它決定「講不講」,下面各段決定「怎麼講」**:每個列出的 `key` 融入對應敘事(`alpha_credibility`/`sector_attribution` → α 段、`unrealized_coverage`/`currency_mix` → 金額段、`unclassified_drivers`/`orphan_sells` → 總覽或標的層一句),**不列成獨立區塊、不上卡**。出卡前逐項核對(SKILL Step 3 gate),漏項不出卡。
**誠實點照 `honesty_ledger` 講(#82)**:engine 已把這張卡必講的誠實缺口聚合成 `honesty_ledger`(空=無缺口)——**它決定「講不講」,下面各段決定「怎麼講」**:每個列出的 `key` 融入對應敘事(`alpha_credibility`/`sector_attribution` → α 段、`unrealized_coverage`/`currency_mix`/`cash_reliability`金額/現金段、`unclassified_drivers`/`orphan_sells` → 總覽或標的層一句),**不列成獨立區塊、不上卡**。出卡前逐項核對(SKILL Step 3 gate),漏項不出卡。

**金額 > 筆數勝率**:總覽絕不放「勝 X/負 Y、勝率 %」當主數字——**「6 勝 2 負」這種勝負筆數也算勝率敘事,不進 metric 格、不當句子主詞**(真人反饋:「勝率不重要,關鍵就是賠錢」)。放**已實現 + 未實現損益(兩個都要,只報一個失真)、盈虧比(平均賺 vs 平均賠)**;敘事聚焦**賠側**:平均一筆賠多少、最大拖累是哪檔、佔總賠幾成——錢是賠錢單決定的。**未實現若非全覆蓋要明講**(`honesty_ledger` 列 `unrealized_coverage` 時):補一句「未實現僅反映 priced_n/held_n 檔持倉,缺現價:…」,別讓沒抓到價的持倉靜默漏算成看起來完整的數字。**金額的幣別先讀 `currency_meta` 再落筆**(#51):`aggregate_currency` = 總覽/佔比類金額的幣別;混幣組合(`mixed=true`)單檔原幣數字用 `pnl_by_currency` 對照;display currency 換算與離線匯率規則照 SKILL.md「💱 Display currency」段,這裡不重複。
**現金與入金判讀(#171,讀 `card.cash`)**:交易工具通常看不到帳戶閒置現金,這個 skill 看得到——但只在 `reliable=true`(用戶給了現金餘額錨點)才把它講進去,別拿盲算數字唬人:
- `reliable=true`:總覽帶一句帳戶現金——「持倉之外還壓著 $X 現金,佔帳戶 Y%」,用**對帳單語言**(現金 / 佔帳戶,不是 `cash_weight`)。這一句的價值是把「部位佔比」升級成「資產佔比」——集中度那個洞若之前只能叫「CSV 內成本占比」,有了現金錨點就能講真的帳戶權重。
- `recent_net_deposit` 非 0 且 `reliable=true`:講**這筆錢的去向與集中度效應**,這是用戶最痛的一問——「這個月淨入金 $Z:你把它加進最重的那檔(加深集中),還是分散進新部位/留現金(解集中)?」用他實際的加碼行為對照,別空問。為 0 或看不到流水 → 這句靜默跳過,別硬掰。
- `reliable=false`(`honesty_ledger` 列 `cash_reliability`):現金是靠交易流水盲算(假設開戶 $0),**不准把那個佔比當真數字講**;誠實帶一句邀請即可——「你的現金餘額我只能從流水盲估、可能差很多;下次把對帳單上的現金餘額給我,就能算準帳戶層比重和入金判讀」。這句同時兌現揭露 + 把功能的下一步交回用戶手上。
**α 永遠出數,語氣看統計**:alpha 一律 vs 通用大盤(SPY),**卡上 α 必帶 95% 區間**;`alpha_credible=true`(≥1 年且 |t|≥1.96)才用能力語氣,不顯著就說「區間 −Y%~+Z%,分不出本事還是運氣」+ 講清楚卡在哪(`gate.reason`:樣本不足 vs 區間太寬/持倉集中)——**別再用「不出數」表達誠實,數字+不確定性才是誠實**。**贏大盤必配拆帳**:engine 已把「贏大盤」機械拆成「押對賽道(allocation)」+「板塊內選股(selection)」(`excess_split`,兩項相加=贏大盤,會計恆等不需顯著性)——引用拆帳數字,別自己心算;`coverage<1` 補一句哪幾檔無板塊對照。**`honesty_ledger` 列 `sector_attribution` 時 → 這句必補,即使 α 面板因樣本不足/不顯著整塊沒出**(#92:有 driver 標籤但查無板塊 ETF 的檔,超額被靜默全歸「選股」、押對賽道的功勞被誤記——這揭露不可只活在 α 面板,它是永遠顯示的 data_integrity 一員,同「未分類 driver」)。**絕不拿板塊 ETF 當 α 基準**,板塊只當拆帳對照。這個「賽道 vs 選股」的分離才是用戶要的準確認知。
**廢話零容忍**:像「偏存活紀律、有些是提問不是判你錯」這種學究句一律刪。每行不是數字就是實例,沒有形容詞填充。

Expand Down
Loading
Loading