Skip to content
White's Tech Notes
Go back

配額有限的批次:便宜必要的工作要排在昂貴輪詢前面

Engineering PracticesEdit page

問題

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. 拆成兩輪:先抓完全部月營收(每檔 1 次,整個 watchlist 一小時內做得完),再抓季報。
  2. 季報「齊全」門檻改用法定期限(latest_available_quarter)。
  3. 下一季在法定期限前的「提前輪詢」每檔每天最多一次:抓回來沒有目標季,就寫 fetch_empty_marker 的 <dataset>_early key,當天跳過。用獨立 key,不跟既有的「30 天空資料 marker」混用。
  4. 順手修了 latest_available_quarter 在 1/1–3/31 回傳「兩年前 Q3」的 bug(應為前一年 Q3),它同時是回測的 look-ahead cutoff。

同一天第二輪起呼叫量從 ~977 降到 ~106。

關鍵洞察

  • 有配額的批次工作,便宜且必要的資料要排在昂貴且多半空手的輪詢前面;混在同一個逐項迴圈裡,昂貴的那一半會把清單尾端餓死。
  • 「提前抓看看有沒有公布」是投機性工作,一定要節流(每天一次),不然它會在整個等待期間每小時吃滿配額。
  • 「排程每步都印完成」不代表資料有進來——要直接數 DB 裡最新一期涵蓋幾檔。


Previous Post
Claude Code mod:用「最近畫過才 tick」省重畫,會讓 pane 永久凍結
Next Post
Browser agent: upload a local file when file_upload fails and CSP blocks localhost