籌碼資料逐來源提供
籌碼日資料讀取指定交易日的原始來源。法人、融資融券、外資期貨等可獨立提供;不需要等待夜間快照、日報或 LLM 完成。數字缺值使用 null,真實的零保留 0。個股籌碼總覽的缺省日期採該股已有任一日來源的最新日期,所有日維度整組只讀該日;尚未到達的來源維持 null,不以舊日資料補值。
日期與狀態
本文所有籌碼端點未指定日期(latest)時,都使用「不晚於台北今日以前最近官方交易日(包含今日)、該端點自己的日來源已有資料的最新一日」:大盤日報/快讀看回應 sources 列出的 8 個大盤日來源,個股看該股法人或融資券,排行榜看各自的來源表,籌碼焦點看全市場個股法人或融資券。新日完全沒有來源時仍顯示前一個有資料日(含分析);新日任一來源開始進入後整份切到新日,未到欄位為 null,分析未齊時為 null。同一回應的日資料只能同一天,不得混入前日數字、收盤價或分析。明確指定日期一律精確查詢該日,不回退。官方日曆不可用時回應 503,不以星期幾推測交易日。MAS 整合分析另依下方「MAS 分析日期」核對跨維度日期。
集保股權分散是週資料,允許使用查詢日以前最近的週觀測,並保留實際 data_date。歷史圖表與前期比較欄位保留其歷史用途,不能填入當日 current。
各籌碼摘要/日報以 sources 呈現來源:
| 欄位 | 型別 | 說明 |
|---|---|---|
status |
string | available 已有資料;partial 僅部分欄位;pending_source 等待來源;no_data 已完成但沒有該筆;not_applicable 當日兩交易所融資融券整批資料已入庫、該股票不在公布名單(數值維持 null);source_error 抓取失敗 |
data_date |
ISO date 或 null | 原始觀測日期;無資料時 null |
updated_at |
ISO timestamp 或 null | 來源更新時間;不代表其他來源已完成 |
整體衍生分析另以 analysis_status: available | pending_source 表示。原始來源已有資料不代表完整分析已可使用。每個有效來源保持獨立,重試失敗不抹掉同日已取得的有效值。
TWSE/TPEx 融資回應若有正確明細表頭但資料為空,仍屬尚未發布;空表缺失或錯誤的表頭、非陣列資料則屬格式錯誤。
來源明確回應尚無目標日資料時為 pending_source,不因排程曾記錄 failed 就推斷來源故障。網路、格式或保存錯誤需保留錯誤分類;個股融資依所屬交易所的結果判斷,另一交易所或市場總額失敗不連坐。既有市場 no_data 若只是空回應紀錄,也呈現等待;沒有發布完成證據時,不按時鐘或重試時段推斷為最終無資料。
個股摘要
GET /api/chip/summary/{ticker}?trade_date=YYYY-MM-DD
ticker必填、台灣公開股票代號;trade_date選填日期,不可為無效字串。- 未指定
trade_date時,選該股法人或融資券任一來源已有列的最新日期;五個日維度(外資、投信、自營商、融資、融券)只讀該日,部分新日來源到達時其餘欄位為null,不得與前一日來源混合。 - 明確指定
trade_date時維持精確日期讀取;當日部分來源缺少時對應欄位為null,不以其他日期填補。 ownership為週資料,不參與日資料日期選擇。未指定日期時取官方交易日以前最新一期;指定日期時取該日以前最新一期,並在sources.ownership.data_date保留實際日期。(大盤完整日報的週集保以所選籌碼日期為上限:只有官方日 8 個大盤日來源全未到、新一期集保已入庫時會顯示上一期,追蹤於 #2099。)- 保留
ticker、trading_date、margin、short、foreign、trust、dealer、big_holders_400、retail、data_freshness、meta。 - 每個 FlowSignal 保留
current/previous/change/change_pct/flow_zscore,皆可為 null;缺值時direction=unknown、magnitude=none,不能推論為持平。 comparison_period沿用daily_balance/daily_flow/weekly。- 新增
sources:institutional、margin、short、ownership;新增analysis_status。 - 明確指定日期而未取得融資資料時,即使前一天有資料,
margin.current仍為 null。缺省日期在新日完全沒有來源時停留於前一個有資料日;任一新日來源到達後切換到新日,其他欄位仍為 null。 - 部分 TDCC 級距缺失時,該級距總計為 null,避免把部分加總當作完整數字。
回應範例(節錄,既有七個維度仍存在):
{
"ticker": "2330.TW",
"trading_date": "2026-10-28",
"foreign": {"current": -3175021, "previous": -1618431, "change": -1556590, "change_pct": null, "direction": "decrease", "magnitude": "none", "flow_zscore": null, "comparison_period": "daily_flow"},
"margin": {"current": null, "previous": null, "change": null, "change_pct": null, "direction": "unknown", "magnitude": "none", "flow_zscore": null, "comparison_period": "daily_balance"},
"sources": {
"institutional": {"status": "available", "data_date": "2026-10-28", "updated_at": "2026-10-28T08:30:01Z"},
"margin": {"status": "pending_source", "data_date": null, "updated_at": null}
},
"analysis_status": "pending_source",
"meta": {"bias": null, "confidence": null}
}
有效股票但當日來源尚未到:200 nullable shell。未知股票:404 {"detail":"No chip summary found for ..."}。無效代號或日期:422 FastAPI validation response;日曆無法讀取:503 {"detail":"Official Taiwan trading calendar unavailable"}。
大盤與其他讀取路徑
GET /api/chip-recap/latest、/api/chip-recap/{date}、/api/recaps/chip/daily/latest、/api/recaps/chip/daily/{date}:讀取所選日的官方法人金額、市場融資融券/借券與期貨;latest 的所選日為上述大盤日來源的最新日。Unified route 保留summary_jsonwrapper;原欄位不改名。- 原始總額無值為 null。
group_flow_summary、stock_event_summary、風險與多空排名等衍生段落在未完成/失效時為 null。週集保排名獨立更新,只使用查詢日以前最新一個全市場週期,不混入停牌或下市股票的舊週資料。 sources含institutional_foreign/trust/dealer/total、margin、short、borrow_sell、futures,完整日報另有ownership。GET /api/chip-recap/pulse/latest、/pulse/{date}、/api/market-pulse/latest、/api/daily-market/latest沿用各自外層結構,傳遞缺值及來源狀態;latest 的籌碼日期與/api/chip-recap/latest相同,daily-market的連買連賣區塊也讀同一日。不能把 null 總額轉成零或中性。GET /api/agent/chip/{ticker}:沿用個股籌碼總覽的最新來源日期,避免法人與融資券跨日混合;新日已有部分原始來源但分析未齊時,signals/events/stories/relations、籌碼結構/狀態/敘事與判斷為 null,不回退前日分析。POST /api/v1/mas/analyze的target=chip:未指定trading_date時同樣使用最新來源日期;新日已有部分來源但分析未完成時回409,新日完全無來源時可用前一個有資料日。明確指定時仍精確讀取。target=orchestrator未指定日期時要求技術與籌碼匹配分析日,財務快照可早於分析日但不能晚於;明確指定日期時,所需快照都須符合指定日。- 當沖、法人(含三法人同買同賣、翻多翻空、連買連賣與其選項)、融資排行榜的預設日期為各自來源表不晚於官方交易日的最新一日;上市、上櫃分批到時任一批到就換日,未到的那批當天不在榜上,不以前一日資料補位。併接的收盤價只取排名日當天,沒有就
null;翻多翻空只納入排名日當天有法人列的股票。當沖market=all需兩交易所齊才排名,只到一邊時回新一日的pending_source與來源狀態。原本為清單的排行榜維持清單型別。 - 個股綜合訊號與籌碼焦點會遮蔽尚未完成的籌碼分析,技術與財務維度維持原有規則。個股綜合訊號未帶
qryDate時,籌碼維度使用該股最新來源日;籌碼焦點使用全市場個股法人或融資券的最新來源日。 - 籌碼焦點在排名取樣前逐股核對當日輸入及分析證據,已完成的個股不等待市場日報、期貨或其他股票。
- 要求尚未完成資料的 LLM 日報與 MAS 籌碼分析回應
409,不對缺值產生報告;MAS 缺省籌碼日期在新日已有任一原始來源後不得回退舊日分析,新日完全沒有來源時則使用前一個有資料日。技術/財務分析不依賴籌碼來源。bundle 日報在週末/休市日使用最近官方交易日,交易日資料未到仍回應409。 /api/chip-recap/{date}/groups與/api/chip-recap/{date}/stocks維持清單契約,尚未完成回應[];完成狀態由 recap 的analysis_status提供。- 融資維持率估值可採當日以前最近的價格,回傳
price_date_min/price_date_max/prior_price_stocks說明估值日期;這不會把前日價格填入當日個股原始價格。
法人摘要缺值契約
GET /api/institutional/stock/{ticker}/summary 的 foreign/trust/dealer/total_net_today、*_net_5d、*_net_20d 及三個 *_streak_days 都允許 null。今日欄位與三個 *_streak_days 取該股法人最新一列的日期(不晚於官方交易日);latest_date 保留該實際日期。有效股票沒有原始資料時回應 200 nullable shell,未知股票/錯誤市場別名仍為 404。
5/20 日欄位仍屬歷史觀測窗口:筆數不足或該法人有缺值時為 null;全部必要法人值未齊時不顯示完整總額。真實零值維持 0。Web 型別與 Mobile DTO/domain 必須接受上述 nullable 欄位;不能把解碼失敗或 null 轉成零。
MAS 分析日期
POST /api/v1/mas/analyze 的 trading_date 選填 ISO 日期。指定日期時,所需籌碼、技術與財務快照都讀取該日,不以最新快照重新標上歷史日期;部分必要資料缺失或日期不符時回應 409,目標完全沒有快照則保留 404,都不啟動 LLM。JSON 與 SSE 使用相同檢查。
未指定日期的 target=chip 使用個股最新來源日:新日完全沒有來源時可使用前一個有資料日;任一新日來源到達後切到新日,分析未齊則回應 409,不得回退舊日分析。target=orchestrator 要求技術與籌碼日期一致且籌碼分析已完成,並以該日為分析日;財務快照可早於分析日但不得晚於,日期不符或必要資料未齊時回應 409。要固定分析某個歷史日,呼叫端須明確傳入該日期,結果及快取也使用該日期。獨立技術/財務 target 保留各自最新快照日期,且不讀取無關的籌碼來源。
計算與重試
同日完整分析須有個股當日法人與正數價格。融資融券須為當日完整資料,或能證明不適用;不適用時維持 null、略過槓桿分析,法人分析可正常產生。兩交易所各自以完整回應原子提交,兩者當日分區皆存在才能將缺列判為不適用;欄位不完整仍為等待。無當日價格的股票不屬於當日可估值分析母體,快照、日報與完成判斷共用此母體;舊日輸入不補到當日。需要歷史窗的指標仍可讀歷史觀測作計算基礎。缺必要輸入的個股不產生完整快照/SES。
夜間快照及日報完成後寫入完成收據,記錄日報所用大盤輸入的內容指紋。大盤分析只核對大盤實際讀取的資料:各股三大法人淨額、融資券當日與前日餘額、收盤價與融資日期,以及大盤籌碼指標與官方三大法人淨額(買賣金額由讀取端即時讀原始表)。這些值直接與已保存的快照及日報比對,也與收據記錄的版本比對:任一異動都會使大盤分析失效,並由下一次排程重新產生。因此某檔計算失敗時不會沿用舊快照;快照事後被單獨重算成新值、日報尚未重建時,也不會把舊日報當成最新。集保(週資料)、法人買賣量、成交量等大盤未讀取的欄位不影響大盤分析;相同數值的重試也不會僅因 updated_at 改變而使分析失效。
個股完成判斷只核對該股票的當日輸入與證據,不看集保(週資料,#2069),也不依賴全市場收據或其他股票/期貨來源。
新快照的證據保存日資料指紋,涵蓋當日法人明細、融資、技術快照與原始 OHLC,能偵測淨額相同但買賣量改變的修訂,以及價格修訂。集保寫入、修訂或晚到,都不會讓個股分析失效,chip-highlights 也不會因此變空。
2069 之前寫入的快照,證據只有混入集保的舊指紋,因此只比對三大法人淨額、融資券當日與前日餘額、收盤價與融資日期,直到該快照被重寫。這段期間,法人買賣量、OHLC 開高低量等其他日資料欄位若被修訂,個股核對偵測不到。
集保背景重算
集保只影響兩樣東西:快照中的兩個籌碼訊號(大戶集中、散戶分散),以及快照記錄的集保週。個股頁的大戶持股與首頁的集保排行直接讀集保表,不經過快照。
快照證據另外保存集保指紋。背景重算拿它與每檔「應有的集保週」比對:
- 執行時機:集保 retry 期間(週五 20:00 起每 30 分鐘一次,最長 60 小時),以及 scheduler 啟動時。
- 檢查範圍:集保週當日與最新籌碼日兩個日期。
- 只要有 eligible 股票落後,就把該日整天重算一次。重算與每日籌碼鏈共用同一把 lock,不會同時執行。
重算完成前,個股頁照常顯示,只有上述兩個訊號仍是上一週的結果。
同一份落後清單在完整處理後仍沒有進展時,會記錄失敗並發送通知。之後該日期不再重算,直到清單改變或 scheduler 重啟。
2069 之前的快照證據沒有集保指紋,背景重算只能比對集保週日期。同一週的集保內容若被修訂,要等快照重寫後才偵測得到。
法人連買連賣
每日法人來源提交後,沿既有計算器逐股更新連買連賣;同日來源已成功的重試也會執行此後續計算。每股只需自己的當日三法人淨額齊備,不等待另一交易所、融資或市場日報。歷史 catchup 不逐日重建整張衍生表,較舊日期的工作也不能覆寫較新榜單。
投影保存該股票截至目標日最近 60 筆法人淨額的內容指紋。API 在排名 LIMIT 前檢查當日來源及指紋;來源修訂、刪除或必要值缺失時,重算完成前不提供失效分析。同值重抓不會只因時間戳改變而失效;預設日期為不晚於官方交易日的最新投影日,該日沒有有效投影時維持空清單,不以更早的投影補位。來源版本讓已快取的回應在資料異動後重新核對。
既有歷史大盤摘要
採用舊資料相容核對,不要求部署時重算全部歷史日報。沒有市場完成收據、且快照尚未帶有新個股內容指紋的舊日報,依原日報的股票範圍(當日快照與股票表的交集,包含無成交股)驗證 n_stocks,不直接套用新版只含當日正數價格的數量。
這不是略過來源檢查:可估值股票仍須通過當日法人、融資與價格比對;額外的無成交股票,須比對當日法人、融資,以及原計算使用的不晚於該日的最近價格。集保不屬於大盤輸入,不參與舊日報核對。只有籌碼欄位皆空的既有 ^TWII 指數占位列可不要求法人來源。這保留舊日報原本的估值語意,不把舊價格寫入當日原始欄位。
已有完成收據、混入新版快照,或來源/輸出內容不一致時,不套用上述相容規則。#2065 之前寫入的收據記錄整列來源指紋,讀取時沿用原本的整列比對(忽略集保),直到排程重新產生該日。新寫入與新收據繼續使用嚴格的當日可估值範圍。原先就不完整、或來源後來確實修訂的歷史日,仍須循既有歷史重建流程處理;本 PR 不宣稱已修復這些資料,也不自動執行歷史重建。
2026-10-29 唯讀核對現有 143 個摘要日期:27 日通過,116 日(約 81.1%)存在來源/輸出差異,衍生摘要保持 pending。這不是整份歷史日報都不可讀:各指定日的原始來源仍獨立提供,個股分析亦獨立核對。跨股票保存的族群總額、排名與風險不能在排除一檔後直接當成重算完成;本 PR 不新增部分母體分析契約,也不把全歷史重建變成部署前置。
大盤回應與完成判斷使用 Redis 快取,先讀固定大小的資料版本表。migration 174 的交易內 statement triggers 涵蓋新增、更新、刪除及清空;來源異動後下一次請求重新核對內容,快取命中不掃描全市場。migration 須隨既有部署流程先套用。
部署順序與 CI
必須先成功套用 174_progressive_chip_cache_versions.sql,再讓新版 API/scheduler 執行。缺少版本登錄時會明確報錯,不能把未登錄的來源放進不會失效的快取。
- SIT 沿用
.github/workflows/deploy-sit.yml的既有自動順序:停止服務與寫入 →apply_pending_migrations.sh apply→ 重建服務。migration 失敗時維持停止;本 PR 不新增人工部署 gate。 - 使用本機/手動 compose 的環境沒有 migration entrypoint,API 又會從掛載的原始碼自動 reload。因此不能先把新程式拉進正在使用的掛載目錄,再補 migration。應從尚未提供給服務的新版 checkout 套用 migration,成功後才切換程式;或依既有停機流程先停止服務,再更新程式、套用 migration、啟動服務。
從待部署 checkout 的 repository root,使用既有 ledger runner(目標容器與資料庫由操作者明確設定):
PG_CONTAINER="$TARGET_PG_CONTAINER" DB_USER="$TARGET_DB_USER" DB_NAME="$TARGET_DB_NAME" \
LOCK_TIMEOUT=5s STATEMENT_TIMEOUT=600s \
investment-agent/backend/scripts/apply_pending_migrations.sh apply
Runner 只在 SQL 成功後記錄 migration;不可用 seed-through 取代執行,也不要直接執行 SQL 後手動補 ledger。這裡記錄部署順序,不代表共享環境已套用。
本 PR 新增 migration 174,並在既有 schema-parity CI job 加入籌碼 PostgreSQL 回歸。既有測試 gate、部署 trigger 與失敗處理保留;並非「未修改 CI/CD」。
Frontend Action Items
前端保留 sources/analysis_status,呈現實際來源日期及等待/失敗狀態。所有 nullable 數字顯示缺值,禁止 Number(null)、缺值補 0 或預設中性。未完成分析時遮蔽舊日報、訊號、成本區及相關推薦;原始數據仍獨立顯示。資料尚在等待時繼續既有刷新週期,讓新來源到達後更新。