量化交易數據層怎麼建:從數據源、清洗到儲存的完整框架

阿翔的網格策略回測年化 38%,上線兩週後直接腰斬。

阿翔的網格策略回測年化 38%,上線兩週後直接腰斬。

他把程式從頭查了一遍,訊號邏輯沒問題,下單模組沒問題,風控參數也沒問題。花了三天才找到真正的原因:那份用來回測的歷史K線裡,有一段長達 11 小時的數據其實是複製貼上補出來的。交易所 API 那天斷線,他的抓取腳本沒有處理缺失,直接拿最後一筆有效報價往下填,填出一段完全平靜、毫無波動的假區間。策略在那段「假裝很安全」的數據裡,學到了一套現實中從不存在的規律。

問題不在策略,在量化交易數據層。在量化交易系統的五層結構裡,數據層排在最底部,理由很直接:垃圾進,垃圾出,而且這一層的錯誤會一路往上污染訊號層、策略層,連你辛苦做的walk-forward 驗證都是在驗證一個不存在的世界。

這篇拆三件事:數據源怎麼選、數據清洗規則要蓋住哪些坑、時間序列資料庫怎麼選才經得起長期回測與監控。看完你會有一份可以直接對照自己專案的檢查清單,不是一句「數據很重要」的空話。


量化交易數據層是一套系統性流程,負責取得、驗證、清洗、儲存市場與鏈上數據,確保訊號層和策略層拿到的是乾淨、時間對齊、沒有前視偏誤的資料。它不是「寫個爬蟲抓K線」這麼簡單,是一組要長期維運的基礎設施,壞掉的時候通常悄無聲息,直到策略績效開始不對勁,你才會回頭懷疑它。

為什麼量化交易數據層該比策略邏輯花更多心力

大多數人做程式交易系統時,數據層是最快帶過的一段。抓個 API、存進資料庫、接上策略,感覺就完工了。策略邏輯才是大家真正花腦力的地方。

順序反了。策略邏輯錯了,回測績效會難看,你會發現。數據層錯了,回測績效反而會變漂亮,因為錯誤的數據常常剛好餵出一套「看起來有規律」的假象,而這種假象最難被發現,因為所有下游的量化回測驗證,包括樣本外測試、walk-forward,都是建立在同一份壞掉的數據上跑的。你不是在驗證策略,是在用同一套錯誤反覆說服自己。

阿翔那 11 小時的假數據,就是這種情況。策略在無波動區間學會了「盤整時加倉」,回測分數因此被墊高。如果不是實盤剛好在真實市場遇到類似盤整卻虧損,他可能永遠不會回頭去查那段K線。

如果你手上已經有數據來源,卻不確定清洗到什麼程度才算及格,這正是付費實驗室裡工程量最大、但討論最少的一塊。

數據源的選擇:交易所、鏈上、總經,各自埋著不同的坑

不同數據源的坑不一樣,選之前要先知道自己在賭什麼。

交易所 API。 現貨、合約、資金費率、未平倉量通常是不同的 endpoint, K線收盤時間的定義也不是每家交易所都一樣,有的用開盤時刻打時間戳,有的用收盤。歷史數據的可回溯深度也常有限制,免費額度往往只給你最近幾個月的分鐘級數據。如果你同時抓多家交易所做比較,像 CCXT 這類統一介面能省掉不少格式對齊的工。

鏈上數據。 直接讀節點準,但慢、貴,而且要處理鏈重組(reorg),一筆剛入塊的交易可能幾分鐘後又被撤銷。用第三方服務(Glassnode、Nansen 這類)方便,但要確認它的區塊時間戳對應的是「上鏈時間」還是「服務商入庫時間」,兩者可能差幾分鐘到幾小時,對高頻策略是致命差距。

總經數據 這裡的坑最隱蔽: CPI、非農這類數據公布後,幾週或幾個月內常會被修正。FRED 資料庫預設給你的往往是最新修正值,不是當時市場實際看到的初值。如果拿修正後的數字去回測「數據公布當下」的反應策略,你驗的是一個根本不存在的世界,因為當天沒有人看得到那個修正後的數字。

團隊裡一位分析師 Lena 就踩過這個坑:她用某月 CPI 數據回測一套總經聯動策略,模型「精準預判」了那次通膨數據帶動的比特幣走勢。後來才發現,她用的是三個月後 BLS 修正過的 3.4%,而市場當天實際看到的初值是 3.2%。策略根本不是預判對了,是拿了未來才存在的數字去解釋過去的價格。這正是前視偏誤最典型的樣子:錯不在邏輯,在你餵給邏輯的那個數字,當下根本不存在。這類「數據當下不存在」的陷阱,在回測過擬合的九種死法裡也是常見死因之一。

還有一種偏差藏在數據源本身:倖存者偏差(survivorship bias)。如果歷史數據只涵蓋「現在還活著」的交易所或代幣,那些當年倒閉的交易所、下市的代幣早就被排除在資料集之外。回測出來的績效,永遠只看得到活下來的那一半,策略看起來穩健,可能只是因為真正致命的案例根本沒被算進你的數據裡。

數據清洗規則:時間戳對齊、缺失值、異常值、前視偏誤

清洗這一步,決定你上層做的所有驗證有沒有意義。

時間戳統一到 UTC,並且只用「當下可得」的版本。 這是最容易被忽略、也最致命的一條規則。任何有「公布時間」與「生效時間」之分的數據,像財報、總經數據、鏈上質押解鎖,回測時都必須用公布當下的原始值,而不是後來的修正版。判斷標準很簡單:如果這個數字在當時的時間點還不存在,它就不該出現在那個時間點的資料列裡。

缺失值不能無腦向前填。 阿翔的案例就是反面教材。缺失應該先被標記(flag),讓你知道這段數據品質不足,再決定是跳過那段回測區間、用其他數據源交叉驗證,還是直接排除。默默填補等於是在告訴系統「這裡什麼都沒發生」,而市場真正劇烈的時候,往往就是數據最容易斷線的時候,兩者高度相關,不是隨機缺失。

異常值要偵測,不要直接刪。 交易所故障造成的插針(wick)、瞬間報價錯誤,確實該濾掉。但加密市場的真實暴力波動,例如清算連環引發的閃崩,長得跟故障插針很像。用統計門檻(如超過 N 個標準差)自動全部砍掉,可能連真實的尾端風險事件都一起砍掉了,而策略的風控邏輯恰好最需要在這種尾端事件上被檢驗。比較穩妥的做法是交叉比對多個交易所的同時段報價,只有單一來源出現、其他來源沒有的尖峰,才判定為故障。

訊號計算不能偷看未來窗口。 算移動平均、算波動率時,窗口右邊界絕對不能碰到當下這根K線收盤之後的數據。這聽起來像常識,但在向量化回測裡,一個 shift() 方向寫反,就足以讓策略在回測裡表現得像先知。

儲存架構:為什麼原始層要跟清洗層分開放

數據存起來之後,架構本身的設計決定你日後能不能追溯問題。

第一個原則是原始層(raw)和清洗層(cleaned)要分開存,而且原始層不可竄改。清洗過程一定會犯錯,規則也會隨時間調整。如果你把清洗後的結果直接覆蓋原始數據,發現規則錯了的時候,你已經沒有辦法回頭重跑一次乾淨的清洗。原始層的角色,是讓你永遠有一份「案發現場」可以重新鑑識。

第二個原則是選對儲存引擎。傳統關聯式資料庫(如 PostgreSQL)不是不能用,但時間序列數據有查詢模式上的特性,像是大量按時間範圍聚合、降頻採樣,一般 SQL 索引效率會隨數據量增長明顯下降。TimescaleDB、InfluxDB 這類專為時間序列設計的資料庫,在這類查詢上通常快上一個量級,而且原生支援時間分區與自動降頻,對長期累積數分鐘級以下數據的量化專案幫助很直接。

比較項 傳統關聯式資料庫 時間序列資料庫
大範圍時間查詢 隨數據量增長變慢 原生分區,效率穩定
降頻採樣 需自行寫聚合邏輯 內建連續聚合
寫入吞吐 中等 針對高頻寫入優化
學習成本 低,團隊多半熟悉 中,需另外學查詢語法
適合場景 低頻數據、關聯查詢多 分鐘級以下、長期累積

第三個原則是保留可重建任意時間點快照的能力,也就是 point-in-time 的概念。不只是存「現在的樣子」,而是存「這筆數據在每個歷史時間點各是什麼樣子」,包含後續的修正記錄。這樣才能在多年後回頭驗證一套策略時,誠實還原「當時真正能看到的世界」,而不是拿現在才有的完整版本,去騙過去的自己。

監控:數據層怎麼知道自己壞了

數據層最危險的失效方式不是報錯,是沉默地錯下去。

一位做資金費率套利的讀者遇過這種狀況:某交易所在沒有公告的情況下,把資金費率結算頻率從 8 小時改成 4 小時,他的抓取腳本還是按照舊邏輯每 8 小時抓一次,抓到的數字看起來正常,格式完全沒變,只是代表的意義已經不一樣了。策略靠著這個特徵計算部位大小,連續三週績效緩慢惡化,直到他把原始回應內容攤開來看,才發現欄位語意早就變了,程式沒有報任何錯誤。

自動化交易裡,沒有人時刻盯著每一筆成交,數據一旦悄悄壞掉,策略照樣運行,只是運行在錯誤的基礎上,而且不會有任何錯誤訊息提醒你。

要擋住這類問題,監控層至少要盯三件事:數據延遲(最新一筆數據的時間戳,離現在是不是異常地遠)、數據缺口(相鄰兩筆時間戳之間的間隔,是否超過預期頻率)、分佈漂移(近期數據的統計特性,像波動率、均值,是否和歷史窗口出現不合理的跳變)。這三項只要自動化成排程檢查,搭配告警通知,大多數靜默損壞都能在幾小時內被抓到,而不是等到對帳單難看了才回頭查。

想長期追蹤這類數據品質與市場微結構的細節,而不是每天被價格噪音牽著走,可以訂閱電子報,定期拆解這類容易被忽略的結構性風險。

把量化交易數據層跟前面幾層串起來的檢查清單

數據層做得好不好,不必等到策略上線才知道。上線前,先對照這幾件事:

  • 數據源的時間戳定義是否已經確認清楚,不同來源之間是否對齊到同一個時區與同一種收盤定義。
  • 所有帶有「公布」與「修正」之分的數據,是否使用當下可得的原始版本,而不是事後修正值。
  • 缺失值是否被標記而非默默填補,異常值是否經過交叉驗證而非單純統計門檻砍掉。
  • 原始層是否與清洗層分開儲存,原始層是否不可被覆寫。
  • 儲存架構是否撐得住你未來一到兩年的數據量與查詢模式,而不是現在夠用就好。
  • 是否有自動化監控在盯延遲、缺口、分佈漂移,而不是靠人眼每天看盤。

這份清單走完,你才有資格說,前面五層結構裡最底層的地基是穩的。不然無論策略邏輯設計得多嚴謹,walk-forward 分析做得多扎實,驗證的都只是同一份壞掉的數據反覆給出的假象,起點都在數據層,而不是統計方法本身。

結論

量化交易數據層不是整套系統裡最有趣的部分,卻是決定其他每一層是否值得信任的地方。

把這篇濃縮成幾個可執行的重點:

  • 數據層的錯誤通常讓回測績效變好看,而不是變難看,這正是它比策略邏輯錯誤更難被發現的原因。
  • 選數據源之前,先搞清楚時間戳定義、修正機制、可回溯深度,總經數據尤其要注意初值與修正值的差異。
  • 清洗規則要蓋住時間對齊、缺失值標記、異常值交叉驗證、前視偏誤四件事,任何一件漏掉,上層驗證都是白做。
  • 原始層與清洗層分開存,原始層不可竄改,才有能力回頭重建任何一個歷史時間點當時的真實樣貌。
  • 監控延遲、缺口、分佈漂移,數據層壞掉幾乎不會報錯,只會安靜地把你的策略帶往錯誤的方向。

你交易的不該是一條漂亮的回測曲線,而是一套從數據源到儲存都經得起反覆質疑的結構。如果你想把這套數據紀律套用在自己的專案上,或想看更多市場微結構與數據工程的拆解,歡迎加入付費實驗室一起把地基蓋穩。


延伸閱讀

外部參考


Meta Title: 量化交易數據層:為什麼數據出錯,回測反而更好看
Meta Description: 數據層錯了,回測績效反而會變好看,這是它比策略邏輯更難被發現的原因。本文拆解量化交易數據層的數據源選擇、清洗規則、前視偏誤陷阱與時間序列資料庫架構。
Primary Keyword: 量化交易數據層
Secondary Keywords: 數據清洗, 前視偏誤, 時間序列資料庫, 數據源, 程式交易, 自動化交易, 量化回測
URL Slug: /blog/quant-trading-data-layer
Internal Links: adtraderlab.com/blog/quant-trading-system, adtraderlab.com/blog/walk-forward-analysis, adtraderlab.com/blog/backtest-overfitting, adtraderlab.com/#lab-benefits, adtrader.beehiiv.com/
External Links: investopedia.com/terms/l/lookaheadbias.asp, investopedia.com/terms/s/survivorshipbias.asp, github.com/ccxt/ccxt
Word Count: ~3750 characters (Traditional Chinese, character count not whitespace word count)

個人頭像照片
AD.Trader Lab

AD.Trader Lab 創辦人 | 量化交易員 專注於在充滿雜訊的市場中,尋找數學上的必然性。AD.Trader Lab 實驗室主理人,帶你用數據看透漲跌背後的真相。