quant-lit進階課程 ▸ Lesson 3

進階課程 · Lesson 3

Lesson 3:資料陷阱與時間戳記

來源:Codex 製作

學習目標

1. Point-in-time 原則

若策略在時間 t 決策,只能使用 available_at <= t 的資訊。資料表至少要區分:

回測的 join 應優先按 available_at 向後匹配,而不是按「財報屬於哪一季」或「事件日期」直接合併。pandas.merge_asof(..., direction="backward") 可表達「只取決策時間以前最近一筆」,但仍要先確認欄位語意與排序。

2. Survivorship bias(倖存者偏誤)

錯誤做法:以今天仍在 S&P 500 的公司名單回測 2010 年策略。這會排除破產、下市、被併購或退出指數的公司,也把後來成功入選的公司提前放回過去。

正確做法:

倖存者偏誤不只發生在股票:加密貨幣交易對、基金、交易所、策略排行榜都會把失敗者從資料中消失。

3. Look-ahead bias(前視偏誤)

常見來源:

最簡單的人工測試是「截斷資料」:只保留到某日,重新計算該日以前的 features。若過去數值因加入未來資料而改變,就有洩漏風險。Freqtrade 官方亦提供 lookahead-analysis,用基準回測與切片回測比較指標及訊號差異。

4. Selection bias(選擇偏誤)

測試 500 個規則後只展示 Sharpe 最高者,表面上只有一個回測,實際上做了 500 次選擇。即使每個規則本身沒有程式錯誤,最佳結果仍會被幸運噪音抬高。必須記錄所有研究嘗試,而不是只保存最後版本。

5. Corporate action(公司行動)

Stock split(股票分割)會按比例降低每股價格並增加股數,持有人總市值不因分割本身改變。若直接用 raw close 計算報酬,分割日可能看起來像巨大崩跌。

但「一律使用 adjusted close」也不夠:

研究資料應同時保存 raw OHLCV、adjustment factor 與 corporate-action event table,並明確記錄用途。

6. 時區、DST 與 bar timestamp

「09:30」必須附時區。美股使用 America/New_York,不能用固定 UTC offset 代替,因 daylight saving time(夏令時間)會改變 UTC 對應。

還要確認 vendor 的 bar timestamp 表示:

若 09:30 標記的是 09:30–09:31 的完成 bar,其 high/low/close 最早在 09:31 才完整可知。把它當成 09:30 即時資訊會提前一分鐘。

7. 交易日曆與缺資料

OHLC 基本條件:

high >= max(open, close, low)
low  <= min(open, close, high)
volume >= 0
timestamp unique and increasing

8. Data contract(資料契約)

每個資料集至少記錄:

vendor/endpoint:
symbol definition:
timezone:
bar timestamp semantics:
frequency:
session calendar:
raw or adjusted:
corporate-action method:
revision policy:
known missing intervals:
retrieval timestamp:
checksum/version:

沒有 data contract,就很難重現同一個回測。

Python 實作

執行:

python .\code\data_quality_audit.py

範例會故意放入重複 timestamp、OHLC 不一致與負 volume,確認稽核器能抓出錯誤。再將錯誤修正,應得到零項 issue。

第 3 課通關檢查

面對任何 feature,逐欄問:

  1. 這個值何時發生?
  2. 何時首次發布?
  3. 我的策略何時能取得?
  4. 後來是否修訂?
  5. 回測 join 使用哪一個時間?
  6. 選股 universe 是否為當時版本?
  7. 價格與股數是否一致處理 corporate action?

七題說不清楚,先停止策略優化,回頭修資料。

上一課Lesson 2