跳轉到

前高 story:完整歷史的最近已確認高點

Issue #1746 的前高修正僅影響 technical new_high_breakout 與 volume_breakout_confirmation 的前高分支。52 週新高與通道突破分支保留。

前高採完整可用行情中,日期最近的已確認局部高點。該根 high 必須 嚴格高於兩側各 5 根 K 線,右側確認完成當日 才可使用;同價平台不成立。新高點尚未確認時保留上一個已確認高點。 沒有 60 日或其他到期窗口。突破使用 close > 前高,相等不算突破。

這包含四項明確的語意差異,不只是移除日期窗口:

項目 原共用前高事件 這兩個 story 的前高分支
搜尋範圍 20/60 日窗口 完整可用行情,無到期限制
選點 窗口內價格最高的局部高點 日期最近的已確認局部高點
確認 20 日分支左右各 3 根;60 日分支各 5 根 一律左右各 5 根
同價平台 high == max(window) 可接受同價 必須嚴格高於左右鄰點,同價平台不成立

例如較早高點 120、較近且已確認高點 100,收盤 105 時,story 前高分支 以 100 判定突破;不要求超過 120。僅左右各 3 根成立、尚未通過 5 根 確認的短波高點不能取代前高。這些差異都不回寫原共用 20/60 日指標。

Story 以同一組還原價 OHLC 計算前高及比較收盤價。無效、缺少或非正值 的 OHLC 保留為確認缺口;缺少指定交易日或已確認高點時,前高分支不成立。 不以較早交易日的值冒充缺少的指定交易日。

資料只經由 story_price_context 傳入 story 層。它不是共用 event, 不加入 event refs 或偽造事件關聯;可追溯至原本的價格訊號。 Technical latest cache 以專屬規則版本失效舊 story;新版快取命中時直接 使用,不讀取完整行情。快取失效時才載入 story context 並重算,維持 既有衝突處理及顯示筆數限制。Signals/events 與其他領域快取版本不變。 冷查詢與 full view 分批載入行情,每批最多 128 個代碼;處理後釋放 該批歷史,只保留當日 context。單檔/日期優先的歷史重播則在 DB session 內保留已計算序列,避免每日重查:2,613 檔約需 200 MB,應使用短生命週期 的工作 session,完成後關閉;不要用 LRU 逐出造成每日反覆讀取全史。

條件 evidence 明列 basis: adjusted。API 的 story description 從 sesi_names.yaml 讀取,說明還原價前高與 52 週/通道等替代分支; 規則說明不放入 badge 或舊版 action_hints,也不偽造共用事件。 若價格投影所需的 factor lineage 缺少或衝突,API 保持 fail-closed,不使用此分支,並記錄 story_context_unavailable/price_projection_unavailable,附日期及代碼。 此時 latest cache 狀態為 invalid,不能解讀為「已檢查但沒有突破」。

本修正不改資料庫 schema、OHLC、個股指標、原 20/60 日前高、 支撐壓力、停損、共用 signal/event 或籌碼/財務/跨面 story 規則。 前低由 PR #1721 獨立處理。

部署順序(開放流量前必須完成)

  1. 在維護窗口部署同一版 API 與 scheduler,並重啟 cortex-scheduler。 Scheduler 長期持有已匯入的 daily 模組,僅替換檔案不會更新既有 process; 未重啟會在下次排程以舊規則覆寫快取。
  2. 使用新版 backend 執行下列 technical cache-only 重建,等待成功完成。 舊 ses-storage-v7 technical 快取會全部失效;重建是必要部署步驟, 不能把全市場冷查詢成本留給第一位使用者。
python -m scripts.refresh_latest_ses_snapshot --domain technical --cache-only
  1. 核對版本分布與重建結果,technical 列應全部使用 ses-storage-v7:previous-wave-high-v1;確認無失敗列,且當日快照有對應 快取,再以 summary API smoke check 確認快取命中後開放流量。
SELECT rule_version, count(*)
FROM taiwan.latest_ses_snapshot
WHERE domain = 'technical'
GROUP BY rule_version;

這一步沿用原 signal/event 規則,只更新 technical compact cache; 歷史 story 修復可在後續批次窗口執行。無需 migration。

歷史修復

下列指令須在部署後、已設定資料庫連線的 backend 環境執行。修復預設 唯讀;--apply 才寫入。它只更新上述兩種 story 的歷史列,不更新 snapshot、event、coverage 或 latest cache,不需要 migration。

python -m scripts.backfill_story_swing_high
python -m scripts.backfill_story_swing_high --apply

可先建立每行一個台股代碼的名單,分批 dry-run,再以相同名單套用。 接受裸碼或 .TW/.TWO,忽略空行及 # 註解、去除重複;空名單或 無效代碼會停止,不會擴大為全市場。--ticker-file 與 --ticker 互斥。

python -m scripts.backfill_story_swing_high --ticker-file batch-01.txt
python -m scripts.backfill_story_swing_high --ticker-file batch-01.txt --apply

--start-date/--end-date 只限制要修復的 story 日期;前高輸入仍讀取 完整歷史。--ticker 2330.TW 可限制單一個股。每檔為一個 transaction, 失敗整檔回滾並回報代碼;同樣參數可重試,相同結果不重寫。 每 10 檔及批次結束記錄進度、成功/失敗數與經過秒數。將最後的失敗 代碼區塊存成 retry.txt,使用相同日期範圍及 --ticker-file retry.txt 重跑;任何檔案失敗時程式以非零狀態結束。

Claude 對優化前版本實測每檔 2,121 日期約 15.4–19.2 秒。依 2,613 檔 估算,每次 dry-run/apply 各約 11.2–13.9 小時;這是容量規劃估算, 不是此次優化後的全市場回填實測。應先跑代表性小批次估時並安排窗口。 原實測每檔約 134–207 個 story key 變動,全市場可能有數十萬筆。 Apply 的實際 story 變更會透過既有 writer 將 Story Strategy 各已追蹤 版本從最早變更日期標記 dirty,需完成後續 Story Strategy 刷新/parity 核對;dry-run 及無變更的冪等重跑不標記 dirty。這不改寫個股或籌碼資料。 本次開發沒有對既有環境執行上述寫入、部署或重啟。

驗證資料

Claude review 後,以相同資料庫的 2026-09-18 全市場冷 summary 查詢進行 唯讀 A/B 實測,2,361 筆完整回應的 SHA-256 相同。原逐檔 loader 為 202.132 秒,優化後 87.926 秒;story context 部分 146.994 → 43.609 秒, OHLC 查詢 2,361 → 19 次。這是單次本機實測,仍須完成部署快取預熱。 另以 2,200 根含缺口行情測量計算本身:15.596 → 5.560 ms,結果逐列相同。

使用 2026-09-18 的 2,362 檔名冊,行情範圍 2018-01-02 至 2026-09-18,共 4,116,042 筆。獨立 rolling-window oracle 對原始價及 還原價逐列確認前高價格與日期一致。還原價中有 18,477 筆突破的前高 已超過 60 個交易日,仍保留有效。

同名冊的實際 technical、chip、financial 快照以修正前後規則比較: 共用 signal/event 與 chip、financial、cross-domain story 完全一致。 new_high_breakout 當日筆數 336 → 322,volume_breakout_confirmation 130 → 127:前者新增 52/移除 66,後者新增 10/移除 13。當日 322 筆 前高突破中,5 筆的已確認高點超過 60 個交易日;因此整體差異不能全部 歸因於撤掉窗口,也包含上述選點、確認根數及同價平台的語意修正。 例如 00953B 使用 83 個交易日前的 2026-05-22 高點 9.4203,當日還原 收盤 9.57;00685L 使用較近的 2026-08-14 高點 12.05,收盤 12.42, 不再被較早的 12.59/13.10 窗內高點擋住。 其他 technical story 的名單與分數一致;3 檔的同組 volume_price_zscore_surge_up_story 僅衝突顯示 metadata 改變。

行情擷取 SHA-256: fdf4d563d0ea55a2f0524fa91a4703eb2442d66fb5b2b13d04bf77f1e2c07d1d。 這是前高算法全史驗收與當日完整 story 比對,不代表完整交易策略回測。