做 K 線回測時,我才真正意識到,資料對齊比策略本身花的時間還多。起初我以為重點會放在指標設計上,結果真正讓回測卡住的,是不同週期 K 線之間的時間戳對不齊和資料缺口。一開始用 1 分鐘 K 線計算信號,再用 5 分鐘 K 線確認趨勢,理論上很直觀,但實際跑起來卻發現數據常常對不上,甚至有些 K 線收盤時間不一致,這些問題疊在一起,回測結果直接偏掉。
舉個例子,1 分鐘信號可能寫成 if close_1m[-1] > ma_1m: signal = 1,再疊加 5 分鐘趨勢判斷 if close_5m[-1] > ma_5m: trend = 1,看起來沒問題,但關鍵是兩個資料點可能不在同一時間。核心思路是先統一時間軸,再做計算。我通常把所有 K 線統一成時間戳(毫秒級),以 1 分鐘為基準,5 分鐘 K 線做 forward fill,再 merge 到同一個 DataFrame,如此同一行的資料就對應同一時間維度。
import pandas as pd
df_1m = pd.DataFrame(data_1m)
df_5m = pd.DataFrame(data_5m)
df_1m['ts'] = pd.to_datetime(df_1m['timestamp'])
df_5m['ts'] = pd.to_datetime(df_5m['timestamp'])
df_5m = df_5m.set_index('ts').resample('1T').ffill()
df = df_1m.merge(df_5m, on='ts', how='left', suffixes=('_1m', '_5m'))
資料來源反而成為關鍵。有些免費資料源會出現 K 線缺失、時間戳不連續或不同市場對齊誤差,後來改用統一的行情接口,資料結構標準化,時間和開高低收都一致,直接丟進 DataFrame 就能使用。例如透過 AllTick 取得 EURUSD K 線資料:
import requests
url = "https://quote.alltick.co/v1/kline"
params = {"symbol": "EURUSD", "interval": "1m", "limit": 500}
headers = {"Authorization": "Bearer YOUR_API_KEY"}
res = requests.get(url, params=params, headers=headers)
data = res.json()["data"]
統一資料源與對齊方式之後,回測結果波動明顯降低,同一策略多次執行結果一致,除錯時間也減少。目前更關注的點是 tick 級資料與 K 線聚合誤差、不同交易所的時間基準,以及高頻策略對延遲的敏感度。如果一開始沒處理好,後續工作很容易返工。整體感覺是,策略可以慢慢調,但資料如果不乾淨,後面會一直被拖住。