問題
stock-analyzer 的 fetch-financials 每小時排程都印「完成 84/294 檔,請於下個整點重跑」,看起來正常。
但 10/29 查 DB,298 檔裡有 106 檔還沒有 9 月營收——9 月營收 10/10 就公布了,落後 19 天。
原因
- 季報的「需要抓」判斷用的是「上一季」(Q3),但 Q3 法定公告期限是 11/14。10 月時幾乎每檔都被判成落後。
- 290 檔 × 3 張季報 ≈ 每小時 977 次呼叫,FinMind 配額只有 600/hr。
- 月營收和季報寫在同一個逐檔迴圈裡,照 watchlist 順序跑;每小時都在同一段撞配額,watchlist 後段的股票永遠輪不到抓月營收。
- FinMind 對未公布的季報照樣回舊資料(到 Q2),所以每小時都「有抓到東西」,不會報錯。
解法
- 拆成兩輪:先抓完全部月營收(每檔 1 次,整個 watchlist 一小時內做得完),再抓季報。
- 季報「齊全」門檻改用法定期限(
latest_available_quarter)。 - 下一季在法定期限前的「提前輪詢」每檔每天最多一次:抓回來沒有目標季,就寫
fetch_empty_marker的<dataset>_earlykey,當天跳過。用獨立 key,不跟既有的「30 天空資料 marker」混用。 - 順手修了
latest_available_quarter在 1/1–3/31 回傳「兩年前 Q3」的 bug(應為前一年 Q3),它同時是回測的 look-ahead cutoff。
同一天第二輪起呼叫量從 ~977 降到 ~106。
關鍵洞察
- 有配額的批次工作,便宜且必要的資料要排在昂貴且多半空手的輪詢前面;混在同一個逐項迴圈裡,昂貴的那一半會把清單尾端餓死。
- 「提前抓看看有沒有公布」是投機性工作,一定要節流(每天一次),不然它會在整個等待期間每小時吃滿配額。
- 「排程每步都印完成」不代表資料有進來——要直接數 DB 裡最新一期涵蓋幾檔。