with one click
etf-tw
// 台灣 ETF 投資助理技能(包含 state-driven dashboard、orders_open lifecycle、callback/polling reconciliation、交易流程驗證、回測去重與報酬回補、worldmonitor 全球風險雷達整合)
// 台灣 ETF 投資助理技能(包含 state-driven dashboard、orders_open lifecycle、callback/polling reconciliation、交易流程驗證、回測去重與報酬回補、worldmonitor 全球風險雷達整合)
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | ETF_TW |
| version | v1.14.2 |
| description | 台灣 ETF 投資助理技能(包含 state-driven dashboard、orders_open lifecycle、callback/polling reconciliation、交易流程驗證、回測去重與報酬回補、worldmonitor 全球風險雷達整合) |
協助使用者進行台灣 ETF 投資決策、風險控制、模擬交易與流程驗證。專注於白話說明、風險透明、執行謹慎,不承諾獲利,不預測短線漲跌。
access_mode 自動選擇最佳工具(API 或 Web Scraping)orders_open.json 維護未終局委託狀態,區分 submitted / filled / cancelled / rejected/health 與 overview 具備 state reconciliation 診斷訊號job_id、output_path、work_dir(背景翻譯任務)references/live-trading-sop.md 的 Pre-flight 檢查;API 詳細用法見 docs/shioaji_api_reference.md。未取得當次明確授權,不應直接執行真實交易台灣股票市場交易時段(所有 ETF_TW 衍生效能者必須遵守):
強制行為:收到下單指令時,第一優先判斷當前是否在交易時段。若不在,直接回覆「現在非交易時段,無法下單」,不得嘗試送單。
當訊號衝突時:
ETF_TW/
├── SKILL.md # 本文件
├── data/
│ ├── etfs.json # ETF 基本資料
│ └── paper_ledger.json # 模擬交易帳本
├── scripts/
│ ├── etf_tw.py # CLI 入口(未來)
│ ├── search_candidates.py # Source-Aware 搜尋器
│ ├── translate_background.py # 翻譯 Job Launcher
│ ├── poll_order_status.py # 訂單狀態輪詢器(每 X 分鐘查一次直到成交)
│ └── provenance_logger.py # 決策溯源記錄器(append-only JSONL)
│ └── backfill_outcomes.py # 回測三合一:去重 + 報酬回補 + 情境快照
├── references/
│ ├── beginner-guide.md # 新手導引
│ ├── risk-controls.md # 風控規則詳解
│ ├── trading-workflow.md # 交易流程說明
│ ├── data-sources.md # 資料來源與更新規則
│ ├── source_health_matrix.md # Source Health Matrix 報表
│ ├── live-trading-sop.md # Live 交易標準作業程序(Shioaji 實戰萃取)
│ ├── roadmap.md # 發展路線圖
│ ├── decision-engine-v2-architecture.md # 決策引擎 v2 架構(三原則量化+LLM增強)
│ ├── market-context-pipeline-roadmap.md # 市場情境管線三階段 roadmap
│ ├── cron-path-fixes-and-script-substitutions.md # Cron 腳本替代與路徑修正備忘
│ ├── intraday-smart-scan-cron-workflow.md # 盤中智慧掃描 cron 流程
│ ├── morning-briefing-cron-workflow.md # 早班準備 cron 流程
│ ├── post-market-review-cron-workflow.md # 盤後收工 cron 流程
│ ├── weekly-deep-review-cron-workflow.md # 每週深度復盤 cron 流程
│ ├── worldmonitor-daily-patrol-cron-workflow.md # WorldMonitor 每日巡檢 cron 流程
│ ├── worldmonitor-rollout-audit-checklist.md # WorldMonitor 落地驗收缺口盤點
│ ├── order-submit-monitor-workflow.md # 下單監控完整流程
│ ├── p2-reconciliation-dashboard-hardening.md # P2 資料流審計與 dashboard 強化
│ ├── state-monitoring-audit-workflow.md # State/Dashboard/監控審計工作流
│ ├── wiki-knowledge-pipeline-architecture.md # Wiki 知識沉澱→AI Decision Bridge 完整鏈路
│ ├── graphify-cooccurrence-bias-lesson.md # Graphify ETF 共現偏差教訓
│ ├── intraday-wiki-risk-flagging.md # 盤中掃描 wiki 風險標記
│ ├── market-prediction-workflow.md # 隔日行情預測標準化流程
│ ├── portfolio-rebalancing-advice-workflow.md # 資產重配置建議流程
│ ├── system-health-check.md # 系統健康巡檢
│ ├── system-health-check-notes.md # 健康巡檢補充備忘
│ ├── fund-coverage-wiki-playbook.md # 非ETF基金全覆蓋蒐集與 Wiki 沉澱流程
│ └── undervaluation-scan-model.md # ETF 低估排行 6 因子評分模型
└── TASKS.md # 實作待辦清單
---
## 環境準備與初始化
在首次使用前,請確保執行以下步驟:
1. **建立並激活虛擬環境** (強烈推薦):
```bash
python -m venv .venv
# Windows: .venv\Scripts\activate | macOS/Linux: source .venv/bin/activate
python scripts/etf_tw.py check --install-deps
python scripts/etf_tw.py init --install-deps
python scripts/etf_tw.py portfolio
此指令會計算實現/未實現損益與總報酬。
此指令會自動補齊缺失套件、建立 assets/config.json 並初始化模擬交易帳本。為支援多代理人隔離與多帳戶路由,ETF_TW 採用結構化的實例配置標準。所有代理人實例的 instance_config.json 必須符合以下格式:
{
"agent_id": "代理人代號",
"accounts": {
"帳戶別名 (如 sinopac_01)": {
"alias": "帳戶別名",
"broker_id": "券商代號 (如 sinopac)",
"account_id": "實體帳號",
"mode": "live / paper",
"credentials": {
"api_key": "Your_API_Key",
"api_secret": "Your_Secret_Key"
}
}
},
"default_account": "預設使用的帳戶別名",
"port": 5050,
"watchlist": ["0050.TW", "..."]
}
AGENT_ID=<instance_id>;新啟動指令、cron 與 dashboard log 一律只使用 AGENT_ID。trading_mode.json 中的 default_account 欄位一致。data/broker_registry.json 中的定義(如永豐金應使用 sinopac)。instances/<agent_id>/),禁止推送到公共代碼倉庫。scripts/setup_agent.py 進行初始化,該腳本已內建標準結構生成邏輯。當用戶啟動此技能或開始新的對話時,Agent 應優先執行:
python scripts/etf_tw.py welcome
並將輸出的口語範例呈現給用戶,引導用戶開始互動。
讀取 references/beginner-guide.md,提供:
提供:
提供:
提供:
**結論**:[簡短結論]
**依據**:
- [數據點 1]
- [數據點 2]
**風險 / 限制**:
- [風險 1]
- [資料限制]
**下一步選項**:
- [選項 A]
- [選項 B]
**模式**:paper / sandbox / live
**帳戶**:[broker/account]
**下單摘要**:
- 標的:XXX
- 動作:買進 / 賣出
- 數量:XXX 股
- 價格:XXX 元
**成本估算**:
- 手續費:XXX 元
- 證交稅:XXX 元
- 總計:XXX 元
**驗證結果**:通過 / 失敗(原因)
**警告事項**:
- [警告 1]
- [警告 2]
**下一步**:
- [可執行 preview / paper trade / 需確認]
每次決策(preview_buy / hold)都會產生一筆 append-only provenance 記錄,追蹤完整生命週期: 決策產出 → T+1/T+3/T+10 review → outcome 判定(win/loss/flat)
decision_id — 唯一識別,跨系統對齊inputs_digest — 策略/持倉/市場/風險壓縮摘要(不是整包 market_cache dump)outputs — 行動/標的/價格/信心/理由review_lifecycle — T1/T3/T10 三窗格漸進式回顧outcome_final — 最終判定 + 報酬率tags — reflection 標記| 腳本 | 觸發時機 | 寫入內容 |
|---|---|---|
generate_ai_decision_response.py | 回應生成時 | 完整 provenance 記錄 |
run_auto_decision_scan.py | scan 決策時 | 完整 provenance 記錄(含 scan_result) |
ai_review_lifecycle.py | review 狀態變更時 | review_lifecycle T1/T3/T10 |
update_decision_outcomes.py | outcome 判定時 | outcome_final(win/loss/flat) |
ai_reflection_lifecycle.py | reflection 時 | tags 標記 |
provenance_logger.provenance_summary(path, limit=5) — 最近 N 筆摘要provenance_logger.find_provenance_by_decision_id(path, id) — 按 ID 查詢以下規則來自真實踩雷事件,任何 agent 使用此技能時必須遵守:
broker_order_id: null + verified: false + order_id: "" = 從未送達券商的假單broker_order_id 為空時輸出「✅ 已正式掛單」或任何成交暗示orders_open.json 或 list_trades() 驗證skills/ETF_TW/.venv/bin/python3~/.hermes/profiles/etf_master/skills/ETF_TW/.venv/bin/python3preview / candidate 只能影響研究與觀察,不能覆蓋正式送單狀態preview_only_mode 不得將正式下單降級為預演orders_open.json 或 list_trades() 驗證委託出現在掛單列表orders_open.json + positions.jsonETF_TW/private/.env 或 ETF_TW/instances/etf_master/instance_config.jsoninstances/etf_master/accounts/sinopac_01.json,此檔案不存在instance_config.json 的 api_key 已被遮蔽為 ***,不能直接讀取private/.env 的值也被 read_file 工具遮蔽;必須用 terminal 直接 Python 讀檔才能取得明文export $(cat private/.env | xargs) 再呼叫 sj.Shioaji().login()SINOPAC_ACCOUNT=0737121(在 .env 中)api.Contracts.Stocks.OTC.get('00679B')(按交易所分類查找)api.Contracts.Stocks[clean_symbol] 直接鍵值查找也可用api.Contracts.Stocks.OTC.get('00679B') 最準確00679B.TWO(櫃買),其餘多數 → .TWapi.stock_account(屬性,非方法),不需要 activate_account()api.activate_ca(ca_path=..., ca_passwd=人物ID, person_id=人物ID)sj.constant.OrderType.ROD(不是 TFTOrderType)order_lot=sj.constant.StockOrderLot.IntradayOdd,quantity 用「股」不是「張」price_type=sj.constant.StockPriceType.LMT(限價)order_cond=sj.constant.StockOrderCond.Cash(現股)api.place_order(contract, order, account=api.stock_account)trade.order.ordno 和 trade.status.id,不是 trade.status.order_id(該欄為空)api.logout() 會 segfault(exit code 139),這是已知 shioaji bug,不是真正錯誤instance_config.json 的 api_key 已被遮蔽為 ***,不能直接讀取read_file 工具也會遮蔽 API keys 為 ***open() + line.split('=', 1) 直接從 private/.env 讀取明文憑證export $(cat private/.env | xargs) 注入環境變數後再登入etf_tw.py 曾有 ETF_PATH 變數名稱錯誤(應為 ETF_CURATED_PATH),導致 check、list、search 三個指令全部 NameError 崩潰ETF_PATH → ETF_CURATED_PATH(含 ETF_PATH = 賦值行)完整鏈路地圖:
run_auto_decision_scan.py → auto_preview_candidate.json (preview-only, not_submitted:True)
→ POST /api/auto-trade/submit (4道Gate) → complete_trade.execute_trade() → ✅ 已接通
ai_decision_bridge.py → ai_decision_request/response (payload only)
→ config/generate/rerun 操作後自動觸發 _run_consensus_rescan() → ✅ 已接通
Dashboard UI → overview.html 顯示 candidate + /api/auto-trade/scan 觸發掃描 → ✅
F1 已修復:POST /api/auto-trade/submit 端點(4道Gate確認機制)
確認 {symbol} {action} {quantity}F2/F3 仍開放:
當任何決策鏈更新時,自動觸發雙鏈重新檢討(規則引擎 + AI Bridge → 共識仲裁):
POST /api/auto-trade/config → 設定存完→_run_consensus_rescan()POST /api/ai-decision/generate → AI 建議生成後→_run_consensus_rescan()POST /api/ai-decision/rerun → 全部重跑後→_run_consensus_rescan()_score_yield():殖利率維度(≥5% +2分, ≥3.5% +1分),來源優先序 watchlist yield_pct > 待補_score_momentum():動能維度(20日動能>5% +2, >1% +1, <-5% -1),RSI>75過熱-1,MACD確認+0.5_score_track_record():紀錄維度(夏普>2 +2, >0.5 +1, <-0.5 -1;1年報酬>20% +1, <-10% -1)sync_ohlcv_history.py 新增:calc_momentum()(20日漲跌幅%)、calc_sharpe()(30日年化夏普值)、calc_yield_from_close()(1年報酬率%)momentum_20d、sharpe_30d、return_1ydimension_scores: {yield, momentum, track_record} 明細問題診斷:智能體無法自主下單的根本原因不是缺少 submit 按鈕,而是三層「假智慧」:
generate_market_event_context.py 全部 hardcoded(geo_political_risk=high, global_risk_level=elevated 永遠不變)。不管川普加關稅、台積法說會、Fed 升息,輸出都一樣。generate_taiwan_market_context.py 的邏輯只是「有任何 ETF 報價為 0 → cautious,否則 → balanced」,然後疊加寫死的 event_context。沒有真實盤勢判讀。generate_ai_decision_response.py 的 _pick_candidate() 只排序 RSI 取最低的,沒有估值/殖利率/動能/產業前景,reasoning 永遠是空字串。00679B 永遠被推是因為它 RSI 最低(44.4),跟防禦型無關。結果:沒有真實政經情勢輸入,智能體沒有「理解市場為什麼會這樣」的能力,就沒有自主下單的資格。
修復路線:
generate_market_event_context.py v2:從 RSI/MACD/SMA/BB 推算 breadth → regime(不再硬編碼)generate_taiwan_market_context.py v2:量化評分(-5~+5) → regime/tilts,含 quant_indicators 區塊decide_action() v2:TOMO 三原則量化維度(_score_yield/_score_momentum/_score_track_record)sync_ohlcv_history.py 新增:momentum_20d / sharpe_30d / return_1ymarket_event_context + 有實質內容的 reasoning問題:系統有兩套決策來源(規則引擎 + AI Bridge),可能建議不同的標的或方向,自動送單時必須有明確仲裁規則。
實作位置:run_auto_decision_scan.py — resolve_consensus() 函數 + 掃描產出時嵌入 consensus 欄位
三層仲裁規則:
| 層級 | 條件 | 結果 | confidence |
|---|---|---|---|
| Tier 1 | 規則引擎和 AI Bridge 同意(同標的+同方向) | 直接執行 | high |
| Tier 2 | 不一致(不同標的 / 一方 hold / AI 質疑) | 規則引擎有否決權,降級執行 | medium/low |
| Tier 3 | 同標的但方向相反(一個買一個賣) | 鎖定,等人工確認 | low |
為什麼規則引擎優先:
consensus 欄位結構(寫入 auto_preview_candidate.json):
{
"consensus": {
"rule_engine": "buy",
"ai_bridge": "buy",
"rule_engine_symbol": "00679B",
"ai_bridge_symbol": "00679B",
"resolved": "buy", // buy | sell | hold | locked
"confidence_level": "high", // high | medium | low
"conflict": false,
"conflict_detail": null,
"tier": 1 // 1=一致, 2=不一致, 3=方向衝突
}
}
mode 標記:
mode: "preview-only"(正常)mode: "preview-low-confidence"mode: "preview-locked"未來送單端只需檢查 consensus.resolved 和 mode:
resolved: "locked" → 禁止自動送出,需人工確認mode: "preview-low-confidence" → 自動送單需二次確認resolved: "buy"/"sell" + confidence: "high" → 可自動送出目的:每日收盤後,自動串接 decision→order→fill 完整軌跡,計算滑價,產出歸檔 JSON。
4 階段架構:
決策快照 → 委託落地 → 成交回報 → EOD歸檔(含slippage)
decision_log orders_open trade_logs trade_journal/{date}.json
資料來源(唯讀、不改原始格式):
decision_log.jsonl — 決策掃描紀錄auto_preview_candidate.json — 共識仲裁結果orders_open.json — 委託紀錄(含 broker_order_id、filled_price)trade_logs.jsonl — 成交紀錄positions.json — 持倉快照橋接鍵:decision_id(新增於 execute_trade() 參數)寫入 orders_open 的 order_row
歸檔輸出:state/trade_journal/{date}.json
{
"date": "2026-04-13",
"summary": { "total_decisions": 0, "total_orders_sent": 1, "total_filled": 1, ... },
"traces": [{
"decision_id": null, // 手動單無 decision_id
"symbol": "00679B",
"action": "manual",
"order": { "order_id": "Y06QX", "filled_price": 27.12, ... },
"fill": { "filled_price": 27.12, "filled_quantity": 100 },
"slippage": null, // 建議限價 vs 成交價,手動單無建議價
"outcome": "filled-manual"
}],
"positions_eod": { "holdings": [...], "total_equity": 25402.8 }
}
CLI 使用:
.venv/bin/python scripts/trade_journal.py --backfill # 補建所有歷史歸檔
.venv/bin/python scripts/trade_journal.py --date 2026-04-13 # 指定日期
.venv/bin/python scripts/trade_journal.py --list # 列出可用歸檔
.venv/bin/python scripts/trade_journal.py --show 2026-04-13 # 查看內容
Dashboard API:
GET /api/trade-journal — 列出所有可用歸檔日期GET /api/trade-journal/{date} — 查詢指定日期歸檔POST /api/trade-journal/generate — 產出/更新歸檔(body: {"date": "2026-04-13"})~/.hermes/profiles/etf_master/skills/ETF_TW/for p in 5050 5051 5055; do lsof -ti tcp:$p | xargs -r kill; done5055;5050/5051 是舊殘留實例,看到要清掉,不可把它們當成有效 dashboard 驗證。cd ~/.hermes/profiles/etf_master/skills/ETF_TW && AGENT_ID=etf_master DASHBOARD_PORT=5055 .venv/bin/python3 -m uvicorn dashboard.app:app --host 127.0.0.1 --port 5055terminal(background=true) 直接跑 uvicorn / scripts/start_dashboard.sh 可能在工具 session 收尾時收到 SIGTERM,出現「Application startup complete」後又 exit 143 關掉;不可只看 watch pattern 就宣稱 dashboard 已啟動。execute_code 內的 subprocess.Popen(..., stdin=DEVNULL, stdout=log, stderr=STDOUT, start_new_session=True) detached 啟動,並寫 log 到 skills/ETF_TW/logs/dashboard-detached.log。GET /、GET /api/overview、GET /api/worldmonitor-status 回 200,且 5055 OPEN、5050/5051 closed 才算通過。lsof -i :5050 -i :5051 -i :5055 全盤檢查,殺掉非 5055 的重複 dashboardinstances/etf_master/state/strategy_link.jsoninstances/etf_master/state/positions.jsoninstances/etf_master/state/orders_open.jsoninstances/etf_master/state/portfolio_snapshot.jsoninstances/etf_master/state/agent_summary.jsoninstances/etf_master/state/major_event_flag.json(注意:不是 major_event_trigger.json)instances/etf_master/state/regime_bucket_stats.jsoninstances/etf_master/state/decision_quality.jsoninstances/etf_master/state/event_review_state.jsoninstances/etf_master/state/intraday_tape_context.jsoninstances/etf_master/state/market_intelligence.jsongenerate_llm_event_context.py 和 generate_llm_decision_reasoning.py 會嘗試連線 LLM APILLM_API_BASE 環境變數是否有值 (2) 空=跳過 LLM 直接 fallback (3) 或加 requests.post(..., timeout=5) 強制短 timeoutsync_news_from_local.py 必須在本機端執行(沙盒無外網)cronjob list 的 enabled=true;需同時查:
~/.hermes/profiles/etf_master/cron/runtime_state.json:若 next_run_at 停在過去日期、updated_at 很舊,代表 scheduler/runtime stale。~/.hermes/profiles/etf_master/cron/output/<job_id>/:確認是否真的有當日輸出檔,例如盤前 9b8156126bbd/YYYY-MM-DD_HH-MM-SS.md。ps aux | grep '[h]ermes' + lsof -p <gateway_pid>:確認實際 gateway 使用的 HERMES_HOME、持有的 log/state 檔與啟動時間;長跑多日的 gateway 可能仍收訊但 cron scheduler 已 stale。profiles/etf_master/logs/agent.log、errors.log、~/.hermes/logs/gateway.error.log 搜 cron.scheduler、Telegram network error、Bad Gateway、reconnect、gateway runtime lock。etf_master gateway → 驗證 runtime_state.next_run_at 推進 → 過時的盤前不要補跑,改跑當下適合的盤中/健康任務。execute_code 中 os.path.expanduser("~") 可正確解析為實際 home(如 /Users/tuchengshin/),推薦使用terminal() 的 shell 中 ~ 和 $HOME 會指向 sandbox 的 /root/,不是實際 home,導致 cd ~/.hermes/... 失敗execute_code 中用 os.path.expanduser("~/.hermes/...") 取得絕對路徑,再傳入 terminal() 的 cd 指令;或先用 find 定位絕對路徑read_file() 回傳帶行號格式(如 1|{"key":...}),直接 json.loads() 會報 JSONDecodeError。讀取 JSON state 檔案時應改用:
terminal(f"cat {path} | python3 -c \"import sys,json; print(json.dumps(json.load(sys.stdin)))\"")terminal(f"python3 -c \"import json; d=json.load(open('{path}')); print(...)\"")read_file() 的 output 呼叫 json.loads()generate_watchlist_summary.py 必須帶 --mode {am|pm} 參數,否則會報錯。盤前用 --mode am,盤後用 --mode pm。layered_review_cron_registry_live.py 屬於舊版 cron 註冊鏈,Hermes 環境下不應再依賴它做實際落地。如需在 Hermes 執行分層復盤,應改用 read_layered_review_artifacts.py 的 build_layered_review_status(state_dir) 函數直接讀取復盤狀態。market_context_taiwan.json + market_event_context.json → 體制判讀 → 優先更新使用者知識庫 ~/wiki/concepts/market-view.md 和 ~/wiki/concepts/risk-signal.md;同時 mirror 到 instances/etf_master/wiki/market-view.md 和 instances/etf_master/wiki/risk-signal.md 供 ETF_TW state-driven wiki 使用(注意:兩邊 wiki 目錄都不一定預先存在,寫入前需確認或建立)。更新時務必同步更新 timestamp,並在「訊號變動歷史」表加入今日紀錄;若舊 wiki 已有當日列,先移除舊列再插入最新列,避免同日重複。generate_decision_quality_weekly.py 的輸出位置是 profile-level wiki:~/.hermes/profiles/etf_master/wiki/decision-weekly-YYYY-WNN.md 與 ~/.hermes/profiles/etf_master/wiki/decision-quality-latest.md,不是 skills/ETF_TW/instances/etf_master/wiki/。驗證週報更新時應檢查這兩個 profile-level 檔案,並比對 size / sha256 或內容一致性。--portfolio active 不存在,會報 Error: Portfolio 'active' not foundpositions.json 讀取持倉 ticker → 轉換為 yfinance 格式(0050→0050.TW, 00679B→00679B.TWO)→ 作為 positional arguments 傳入uv run {home}/.hermes/.../stock-analysis-tw/scripts/analyze_stock.py 0050.TW 00679B.TWO --fast --state-dir ...,相對路徑 skills/stock-analysis-tw/... 在 cron 中無法解析stock-analysis-tw/scripts/analyze_stock.py 可能在 etf_master profile 未安裝(只剩 taiwan-finance/references/stock-analysis-tw.md),此時不要讓整個盤中掃描失敗;應記錄「量化診斷子步驟跳過 / script missing」,繼續執行 market context、major event、decision refresh,並在最終報告標註缺口scripts/run_intraday_quant_diagnosis.py,輸出 intraday_quant_diagnosis.jsonAGENT_ID=etf_master,否則腳本會 fallback 但反覆輸出 missing AGENT_ID warning,干擾報告解析terminal(f"cat {path} | python3 -c \"import sys,json; print(json.load(sys.stdin))\"") 回傳空字串terminal(f'python3 -c "import json; d=json.load(open(\'{path}\')); print(json.dumps(d, ensure_ascii=False, indent=2))"') 直接用 open() 讀檔execute_code 中直接 import json; json.load(open(path)) 最穩盤中掃描是「知識→行動決策鏈」的即時感知與判讀環節。每次掃描必須依序執行以下步驟:
1. 資料同步與情境更新(依序執行)
cd ~/.hermes/profiles/etf_master/skills/ETF_TW && .venv/bin/python scripts/sync_market_cache.py
cd ~/.hermes/profiles/etf_master/skills/ETF_TW && .venv/bin/python scripts/generate_intraday_tape_context.py
cd ~/.hermes/profiles/etf_master/skills/ETF_TW && AGENT_ID=etf_master .venv/bin/python scripts/run_intraday_quant_diagnosis.py
cd ~/.hermes/profiles/etf_master/skills/ETF_TW && .venv/bin/python scripts/generate_market_event_context.py
cd ~/.hermes/profiles/etf_master/skills/ETF_TW && .venv/bin/python scripts/generate_taiwan_market_context.py
2. 重大事件偵測
cd ~/.hermes/profiles/etf_master/skills/ETF_TW && .venv/bin/python scripts/check_major_event_trigger.py
3. 決策引擎刷新
cd ~/.hermes/profiles/etf_master/skills/ETF_TW && .venv/bin/python scripts/refresh_decision_engine_state.py
4. Wiki 知識更新(判讀層)
2026-04-30 實測補充:scripts/distill_to_wiki.py 只會更新個別 ETF wiki 頁面,不等於完成盤中判讀層的 market-view.md / risk-signal.md。盤中智慧掃描跑完 context / major event / decision refresh 後,仍需明確讀取 state 檔並更新這兩個判讀頁,否則 wiki 會停留在上一輪體制與風險訊號。
注意:State 檔案名稱對照
major_event_flag.json(不是 major_event_trigger.json)regime_bucket_stats.json、context_weights.json、decision_quality.json(沒有單一的 decision_engine_state.json)intraday_tape_context.jsonmarket_intelligence.json4a. 更新 market-view.md
instances/etf_master/state/market_context_taiwan.json 和 market_event_context.jsoninstances/etf_master/wiki/market-view.md(需確認目錄存在,必要時先建立)4b. 更新 risk-signal.md
instances/etf_master/wiki/risk-signal.md4c. 異動推播判斷
5. 產出格式
🔍 盤中掃描報告 HH:MM
體制:[體制狀態] | 風險:[風險溫度]
- 觀察標的:[2-3個重點ETF的即時數據]
- 異動事件:[有/無,若無則省略此行]
- 體制變動:[有/無,若無則省略此行]
全部以繁體中文輸出。報告控制在 8 行以內,只標記有變動的事項。
注意事項:
instances/etf_master/wiki/) 不一定預先存在,寫入前需確認或建立instances/etf_master/state/(不是根目錄的 state/)state_legacy_compat_link/,讀取時應以 instances/etf_master/state/ 為準sync_worldmonitor.py --mode daily,寫入 worldmonitor_snapshot.jsonsync_worldmonitor.py --mode watch,偵測 L2/L3 升級事件並 append worldmonitor_alerts.jsonl每次重大變更或定期巡檢時,依序驗證以下 9 項:
.venv/bin/python3 -c "import yfinance, pandas, numpy, shioaji, fastapi, uvicorn"curl -s http://localhost:5055/api/overview | python3 -m json.tool;驗證 /api/positions、/api/kpi、/api/intelligence、/refreshstrategy_link.json、positions.json、orders_open.json、portfolio_snapshot.json、agent_summary.json、auto_trade_state.json、auto_trade_config.json 全部有效 JSON;positions vs snapshot reconciliation 吻合etf_tw compare 0050 00878、search candidates、list universe 正常回傳backfill_outcomes.py --dry-run 通過;去重閘門正常etf_tw check 全通:修正後的變數名稱(ETF_CURATED_PATH)無殘留舊名引用本區段對齊
ETF_TW_GAP_AUDIT.md(2026-05-06)稽核結論。缺口以 P1/P2 標示。
yield_pct),實際資料尚未接線。高股息 / 收益型 ETF 評分偏弱。需選定資料源(TWSE / 投信官網 / 手動 curated)。docs/NEWS_SOURCE_POLICY.md 與 state/news_source_health.json。docs/LIVE_INTRADAY_VALIDATION_CHECKLIST.md + 小額實單授權。scripts/sync_broker_quotes.py + market cache truth_level 欄位。scripts/generate_family_portfolio_report.py + state/family_summary.json + dashboard family overview。scripts/init_paper_ledger.pyrun_auto_decision_scan.py 已內建 _session_dedup_key() + _is_duplicate_session() 閘門top_candidates[0]['symbol'])_session_dedup_key() 對 hold 回傳 None,不做去重docs/BROKER_RECONCILIATION_RULES.mdbackfill_outcomes.py位置:scripts/backfill_outcomes.py
功能:
產出(不修改原始檔案,純增量):
state/decision_outcomes_dedup.jsonl(去重 + 回補報酬)state/decision_context_history.jsonl(情境快照)yfinance Ticker 對照表:台股 ETF 用 .TW 後綴,但 TPBS(櫃買)掛牌的用 .TWO
resolve_yfinance_ticker() 優先從 market_cache 取,其次用前綴規則(006→.TWO,其餘→.TW)decision_log 去重很關鍵:掃描腳本每 30 分鐘跑一次,同日同一標的會產生 12 筆重複記錄
日期 + 標的 + 動作reference_price 不在 decision_outcomes 裡:原始 decision_outcomes.jsonl 的 reference_price 全是 null
top_candidates[0].pricehold 動作沒有 top_candidates:action=hold 的決策 top_candidates 是空列表
market_context 只留最新一份:market_context_taiwan.json 不保留歷史
etf_core 模組路徑問題:✅ 已解決
backfill_outcomes.py 透過 sys.path 正確引入 etf_core.state_ioload_jsonl / safe_append_jsonlresolve_yfinance_ticker() 改從 market_cache 動態推導 ticker,不需硬編碼對照表[驗證中],直到 Level 1 查詢確認成交。positions.json (Level 3)orders_open.json (Level 3)portfolio_snapshot.json、agent_summary.json (Level 3)此技能可被 agent 調用,用於:
注意:heartbeat 僅用於巡檢與提醒,不自動執行 live trade。
strategy_state.json、state/strategy_link.json、state/agent_summary.json 傳遞給 agentETF_TW 的 ETF 推薦層分成四個不同資料範圍,嚴禁混用:
| 層級 | 檔案 | 用途 | 是否使用者手動維護 |
|---|---|---|---|
| ETF Universe | data/etf_universe_tw.json | 台股 ETF 可交易總名錄(TWSE + TPEx,目前 338 檔) | 否 |
| Watchlist | instances/<agent>/state/watchlist.json | 使用者高觸碰關注清單與 dashboard 顯示 | 是 |
| Universe Screening | instances/<agent>/state/universe_screening.json | 由 338 檔 universe 依策略產生的短名單,供 Rule Engine / AI Bridge 參考 | 否 |
| Market Intelligence | instances/<agent>/state/market_intelligence.json | 有報價/技術指標的活躍標的資料 | 否 |
規則:
watchlist.json 不應被自動塞入 338 檔,保持使用者手動控制。universe_screening.json 是生成產物,可包含非 watchlist 標的,但只供推薦/preview 候選參考。generate_ai_decision_request.py 必須同時保留 watchlist_context 與 universe_screening_context,AI Bridge 不得只靠 wiki entity 或 18 檔 watchlist 做推薦。run_auto_decision_scan.py 可合併 watchlist + universe_screening.shortlist 評分,但重複標的必須保留 watchlist 的人工 metadata。test_decision_universe_coverage.py 必須維持:universe >= 300、screened > 100、平衡配置短名單至少 3 類、雙鏈推薦不塌縮為單一標的循環。git fetch --tags origin,再以 git tag --sort=-v:refname | head、root README.md 版本紀錄、CHANGELOG.md 最上方版本共同確認目前最新版本。SKILL.md frontmatter 的 version:,該值可能落後於 GitHub tag / CHANGELOG / README。v1.4.16 → v1.4.17,不是建立 v0.0.1 tag,也不是從 stale frontmatter v1.4.5 bump 到 v1.4.6。README.md 標題與「📦 版本紀錄」(唯一主 README)→ skills/ETF_TW/SKILL.md frontmatter → skills/ETF_TW/CHANGELOG.md 最上方條目 → 測試 → commit → push main → 建立正確版本 tag → push tag。git ls-remote origin refs/heads/main refs/tags/<tag> 確認 main/tag SHA,並用 git show origin/main:README.md 或 GitHub raw/API 確認遠端 README 已顯示新版紀錄。git tag -d <bad> + git push origin :refs/tags/<bad>,再建立正確 tag。v1.11.0(2026-05-08):ETF Universe Screening 全面上線
scripts/generate_universe_screening.py:從 338 檔 universe 依策略評分產生最多 30 檔 shortlist,寫入 state/universe_screening.jsongenerate_ai_decision_request.py 補 universe_screening_context:AI Bridge 可參考非 watchlist 標的generate_ai_decision_response.py:candidate priority 三層(watchlist → screening → market intelligence fallback)run_auto_decision_scan.py:Rule Engine 合併 watchlist + screening shortlist 評分,不修改 watchlist.jsonrefresh_monitoring_state.py / refresh_decision_engine_state.py:screening 納入 refresh pipelinetest_generate_universe_screening.py / test_decision_universe_coverage.py / test_decision_recommendation_reasonableness_matrix.py857 passedv1.10.9(2026-05-08):Hermes-only 清理驗證 + sandbox live 測試跨日修正
AGENT_ID contract 下可正常 import / dry-run / smoke test847 passed;focused tests:sandbox live 24 passed;dashboard / cron / sandbox API 21 passedv1.10.8(2026-05-07):sandbox_live 小額實單驗證框架 + gitnexus 索引設定
scripts/sandbox_live.py:guarded state helper + 候選過濾 guard + 執行層(對應 GAP AUDIT P1-D)docs/plans/2026-05-07-sandbox-live-micro-order-validation.md--host 預設改為 0.0.0.0(任何啟動方式均綁定所有介面)v1.10.7(2026-05-07):Dashboard health 假沉默修復 + scan LOCKED 早退補點
run_auto_decision_scan.py:DISABLED / LOCKED 早退也更新 last_scan_at / last_action / last_decision_summarydashboard/app.py:/health 合併 reconciliation warnings + decision engine warnings + stale_items,消除 ok:false 但 warnings:[] 的假沉默etf-tw-health-check skill 的外部依賴,改為自包含巡檢 promptv1.10.6(2026-05-06):GAP AUDIT 文件收斂
ETF_TW_GAP_AUDIT.md P1/P2 缺口分類TASKS.md 新增 GAP AUDIT 缺口追蹤區段(P1-A/B/C/D, P2-A/B)references/roadmap.md 重寫為 v1.10.3 實際狀態(已完成版本 + 已知缺口 + Phase 2-5 執行計畫)v1.10.5(2026-05-05):Cron 定義與本機 runtime state 分離
cron/jobs.json 保持為可隨 GitHub 發佈的 9 個任務定義,不再保存 next_run_at / last_status 等執行狀態cron/runtime_state.json 保存本機排程狀態並加入 .gitignore,避免 cron tick 每天污染工作樹v1.10.4(2026-05-05):TODO 收斂與 reconciliation / indicator 補齊
filled_reconciliation.py 新增成交後 positions 對齊完成條件:positions snapshot 必須晚於 fill fact;買進需看到正持倉,賣出可對齊至持倉消失sync_ohlcv_history.py 補 KD、20 日均量與量比;AI Bridge request 可攜帶 Bollinger / KD / volume metricsTASKS.md 對齊 v1.10.x 現況,已完成項標 DONE,Cathay / 盤中正式驗證 / 外部新聞源標外部阻塞v1.10.3(2026-05-05):修正健康巡檢三項異常
etf_tw.py:新增 _etf_category() fallback helper,修正 list/search/compare/category 在缺 category 欄位時 KeyError crashrun_auto_decision_scan.py:修正 _is_duplicate_session 與 _session_dedup_key symbol 來源不一致(top-level vs top_candidates[0]),解決同日同標的被重複 log 4 次的 bugtest_dedup_session_key.py(9 tests);全套 780 passedv1.10.2(2026-05-05):修正雙鏈勝率統計 — source fallback
update_chain_breakdown() 對 chain_sources=None 的老紀錄新增 fallback:依 source 欄位分桶(run_auto_decision_scan → rule_engine;generate_ai_decision_response → ai_bridge)test_update_chain_breakdown_source_fallback;全套 770 passedv1.10.1(2026-05-01):ETF universe metadata + 雙鏈決策候選語意修正
watchlist_context,watchlist 候選不再依賴 16 個 wiki entity 才能取得完整上下文generate_decision_consensus.py 改用 universe + curated 合併 catalog,修正 00939 / 00720B 被判成查無資料buy-preview、watch_only、advisory candidate;觀察模式不建立 preview,高波動警戒/逢低觀察 overlay 正確生效v1.10.0(2026-05-01):智能 multiplier 鏈完整化(E2 + F1 + F-news)
correlation_engine + compute_correlation_matrix.py,買進時 ρ>0.7 線性折扣倉位(floor 0.2)news_intelligence_report.json,high/medium 對買單做 haircut(×0.4 / ×0.7)2026-04-28-A-to-G-plan.md 加執行進度段,明確 D / E1 / G 暫緩到實單 3 個月後v1.9.0(2026-04-30):長線風控與外部能力安全前置層
status 顯示模式、帳務、對帳、資料品質、組合風控與新聞情報v1.8.2(2026-04-30):cron 缺失腳本修復 + ETF_TW 內建量化診斷
scripts/run_intraday_quant_diagnosis.py,輸出 intraday_quant_diagnosis.jsonstock-analysis-tw/scripts/analyze_stock.pystock-analysis-tw / stock-market-pro-tw 必跑依賴generate_watchlist_summary.py 補上 --mode am/pmv1.8.1(2026-04-29):live submit 盤後零股修正 + submission journal + orders_open 清理
live_submit_sop.py 優先使用 instance account credentials,env vars 僅作 fallbackStockOrderLot.Odd,盤中零股維持 IntradayOddsync_orders_open_state.py 讀取券商成交紀錄清除已成交 open ordersubmission_journal.jsonl audit trail 與 submit_response metadata contractv1.8.0(2026-04-29):v2 自動交易骨架 + live submit 安全收斂 + production replay 審計
live_submit_sop.py;未驗證 live 回報進 ghost log,不落入 orders_open.jsonUNVERIFIED 被字串包含誤判為 VERIFIED 的 ghost order 風險sell_scanner 支援 mixed lot board/odd 拆單,避免 odd lot 超量被 pre-flight gate 擋下v1.7.0(2026-04-27):正式下單安全閘門 + Dashboard 資訊架構整理
v1.3.3(2026-04-13):F1斷層修復 + 決策鏈重檢 + 推薦引擎修正
/api/auto-trade/submit 端點,4道Gate確認機制(confirmation/candidate/live_submit/large order)_run_consensus_rescan()v1.3.4(2026-04-14):TOMO 三原則量化 + AI reasoning 重寫
v1.4.1(2026-04-19):部署驗證與安全修正(實測 etf_master_wife clone 發現)
verify_deployment.sh:移除 set -e(curl 失敗不再中斷整個腳本);/api/positions → /api/overview.positions(端點不存在);交易時段閘門改用 validate-order 子指令(order 不存在);新增 DASHBOARD_PORT env var 支援多實例測試DEPLOYMENT.md:步驟七八對調(sync pipeline 先於 Dashboard 啟動);新增 Paper Mode 最小腳本表格(5 支必要 vs 11 支完整);補充 worldmonitor cron enabled:false 自動跳過說明cron/jobs.json:個人 Telegram chat_id/chat_name 移出 git 追蹤,改為 ${TELEGRAM_HOME_CHANNEL}/${TELEGRAM_CHAT_NAME} 佔位符;真實值移入 .envprivate/.env.example:補齊 AGENT_ID、Telegram Bot(4 個變數)、Shioaji(5 個變數)、worldmonitor(2 個變數)的繁中說明v1.4.0(2026-04-19):Worldmonitor 全球風險雷達整合
sync_worldmonitor.py:雙模式(daily 快照 / watch 事件監控),從 worldmonitor API 拉取全球風險信號chokepoints[].disruptionScore/status/warRiskTier(無 global_stress_level,需推算);stressScore/stressLevel(非 shipping_stress_index);minerals[].mineral/riskRatingUser-Agent: Mozilla/5.0 ETF-Master/1.0 繞過 worldmonitor middleware.ts 過濾_derive_global_stress_level()、_derive_taiwan_strait_risk()、_derive_taiwan_semiconductor_risk() 從 API 回傳推算風險等級_detect_alerts():前後快照比對,產生 L2/L3 geopolitical/supply_chain/taiwan_strait 升級事件_compute_affected_etfs():根據 ETF focus/index/name 動態比對受影響 ETFgenerate_ai_decision_request.py 新增 worldmonitor_snapshot、worldmonitor_alerts 作為第 14 個輸入源;ai_decision_bridge.py 新增 _build_worldmonitor_context()/api/worldmonitor-status(含 chokepoints 清單、shipping_stress_score);POST /api/worldmonitor/refresh 一鍵更新;收合 ▾/▸ 按鈕;↻ 更新按鈕;tooltip 說明worldmonitor_daily(每日)、worldmonitor_watch(盤中每 30 分鐘)worldmonitor_snapshot.json(atomic overwrite)、worldmonitor_alerts.jsonl(append-only L2/L3 事件)v1.3.5(2026-04-14):Phase B 宏觀指標 + Phase C LLM 增強推理
v1.3.2(2026-04-13):Live 交易 Shioaji API 實戰修正
api.Contracts.Stocks.OTC.get()(櫃買),不是 TSEapi.stock_account(屬性)、StockOrderLot.IntradayOdd(盤中零股)、OrderType.ROD、StockPriceType.LMTprivate/.env 用 Python open 讀取(read_file 會遮蔽***)trade.order.ordno 和 trade.status.idapi.logout() segfault 為已知 bugreferences/live-trading-sop.md:Live 交易標準作業程序(Pre-flight、下單流程、委託驗證、錯誤處理)docs/shioaji_api_reference.md:完整 21 節 Shioaji API 參考(登入→快速入門,含 ETF 用法與已知問題)default_broker: N/A:state 需寫入 instances/etf_master/state/ 而非 ETF_TW/state/v1.3.1(2026-04-12):Bug 修正與健康巡檢 SOP
etf_tw.py 中 ETF_PATH → ETF_CURATED_PATH 變數名稱錯誤,導致 check/list/search 三指令 NameError 崩潰v1.3.0(2026-04-12):回測基礎建設 — 去重閘門 + 報酬回補 + 情境快照
run_auto_decision_scan.py 新增 _session_dedup_key() + _is_duplicate_session() 去重閘門backfill_outcomes.py 三合一腳本:決策去重 + yfinance 報酬率回補 + 市場情境快照resolve_yfinance_ticker() 動態推導 yfinance ticker(不再硬編碼對照表)decision_outcomes_dedup.jsonl 和 decision_context_history.jsonl.bak.2026-04-12v1.2.3(2026-04-11):Decision Provenance Logger 建置
provenance_logger.py:append-only JSONL 決策溯源記錄器generate_ai_decision_response.py、run_auto_decision_scan.py、ai_review_lifecycle.py、update_decision_outcomes.py、ai_reflection_lifecycle.pyv1.2.2(2026-04-10):Hermes 移轉對齊與 cron 重建
~/.hermes/profiles/etf_master/skills/ETF_TW/ETF_TW/instances/etf_master/state/cd ~/.hermes/profiles/etf_master/skills/ETF_TW && .venv/bin/python3 -m uvicorn dashboard.app:app --host 0.0.0.0 --port 5055v1.2.1(2026-04-10):新增「血淚教訓」章節,來自舊系統遷移期真實踩雷事件
v1.2.0(2026-03-28):新增本地可視化儀表與 state-driven 架構
v1.0.1(2026-03-26):公開整理與發布版本
v1.0(2026-03-23):初始版本,提取自 agent 工作區
如有功能建議或發現問題,請透過 Hermes Agent 反饋,或更新 TASKS.md 與 roadmap.md。
主技能 ETF_TW 已吸收下列窄域技能為 references/ 知識庫文件。需要特定工作流細節時可直接查 references/:
| 原技能名稱 | references/ 檔案 | 內容 |
|---|---|---|
| etf-decision-engine-v2 | decision-engine-v2-architecture.md | 決策引擎 v2 架構(三原則量化+LLM增強) |
| etf-market-context-pipeline | market-context-pipeline-roadmap.md | 市場情境管線三階段 roadmap |
| etf-tw-cron-path-fixes | cron-path-fixes-and-script-substitutions.md | Cron 腳本替代與路徑修正 |
| etf-tw-graphify-lesson | graphify-cooccurrence-bias-lesson.md | Graphify ETF 共現偏差教訓 |
| etf-tw-health-check | system-health-check.md | 系統健康巡檢 9 項 SOP |
| etf-tw-health-check-notes | system-health-check-notes.md | 健康巡檢補充備忘 |
| 基金全覆蓋知識沉澱流程 | fund-coverage-wiki-playbook.md | 非ETF基金全覆蓋蒐集、三層 wiki 雙寫與索引更新流程 |
| etf-tw-intraday-smart-scan | intraday-smart-scan-cron-workflow.md | 盤中智慧掃描 cron 流程 | | etf-tw-intraday-wiki-risk-flagging | intraday-wiki-risk-flagging.md | 盤中掃描 wiki 風險標記 | | etf-tw-market-prediction-workflow | market-prediction-workflow.md | 隔日行情預測標準化流程 | | etf-tw-morning-briefing | morning-briefing-cron-workflow.md | 早班準備 cron 流程 | | etf-tw-order-submit-monitor | order-submit-monitor-workflow.md | 下單監控完整流程 | | etf-tw-p2-reconciliation-dashboard-hardening | p2-reconciliation-dashboard-hardening.md | P2 資料流審計與 dashboard 強化 | | etf-tw-portfolio-rebalancing-advice | portfolio-rebalancing-advice-workflow.md | 資產重配置建議流程 | | etf-tw-post-market-review | post-market-review-cron-workflow.md | 盤後收工 cron 流程 | | etf-tw-state-monitoring-audit | state-monitoring-audit-workflow.md | State/Dashboard/監控審計 | | etf-tw-undervaluation-scan | undervaluation-scan-model.md | ETF 低估排行 6 因子評分 | | etf-tw-weekly-deep-review | weekly-deep-review-cron-workflow.md | 每週深度復盤 cron 流程 | | etf-tw-wiki-knowledge-pipeline | wiki-knowledge-pipeline-architecture.md | Wiki→AI Decision Bridge 鏈路 | | etf-tw-worldmonitor-daily-patrol | worldmonitor-daily-patrol-cron-workflow.md | WorldMonitor 每日巡檢 | | etf-tw-worldmonitor-rollout-audit | worldmonitor-rollout-audit-checklist.md | WorldMonitor 落地驗收缺口盤點 |
保留的獨立子技能(具備獨立操作價值,不適合完全吸收):
etf-tw-trading-rules:交易規則知識庫(委託類型、時段、零股、交割規則)etf-tw-live-query:即時持倉與掛單查詢(live broker API 繞過 state)etf-tw-p0-remediation:P0 交易致命錯誤收斂流程(含五步驟+最小驗證)