配對交易 Pairs Trading 由零開始:Python 實現、Jesse 回測與手續費陷阱
第 8 課・共 18 課
目錄
配對交易 Pairs Trading 是 Edward Thorp 賴以建立八億美元基金的市場中性策略,本課筆記整理自 Algo-trading with Saleh 的教學影片:講者 Saleh 由零開始,先在 Jupyter Notebook 推導數學原理,再用 Jesse 框架寫成可回測的策略。這是同頻道較早期的「原始版本」教學——第 18 課記錄的是他其後實盤改良的版本,兩課對照閱讀,剛好看到一套策略由「看似完美」到「勉強可用」的完整演化。
學習重點
- 配對交易的利潤來源:同時做多一隻、做空另一隻高度相關的資產,賺取兩者相對強弱的收斂,升市、跌市、橫行市理論上都有機會獲利。
- 由圖表到統計:肉眼看到的背馳要變成程式訊號,靠價差序列的 Z 分數——偏離均值多少個標準差。
- 相關不等於可交易:兩條價格序列各自都不平穩,但只要其組合(價差)平穩,即屬協整,才可做均值回歸;講者用一行函數完成檢定。
- Jesse 雙路線架構:一個策略檔負責全部決策,另一個純粹執行,靠
shared_vars字典互通。 - 回測最殘酷的一頁:不計手續費一年 +69%、回撤 -5%;計入真實費率後一萬美元變 343 美元——7,818 宗交易的手續費高達 1.1 萬美元。
詳細筆記
Thorp 與市場中性的誘惑
講者開首交代他迷上這策略的原因:讀了 Thorp 的自傳《A Man for All Markets》後,發現這位發明二十一點算牌術的數學家,其基金幾乎每月賺錢,最差的一個月虧損不足 1%。配對交易是市場中性策略——任何時刻同時持有一個好倉與一個淡倉,利潤不取決於大市方向,而取決於兩隻資產的相對關係是否回歸常態。
他用 TradingView 圖表演示:把 ETH 與 ETC(以太坊經典)的價格放在同一百分比變化尺度上,兩者走勢高度相關,但不時出現背馳——某段時間 ETH 跑輸 ETC,其後又反超前。若在 ETH 相對偏弱時做多 ETH、同時做空 ETC,待關係逆轉時平倉,即使兩者價格同時下跌,淡倉賺的錢仍多過好倉虧的錢,差額就是利潤。圖上類似機會反覆出現,看似俯拾皆是——但講者提醒,這只是事後用肉眼看圖,真正落盤時沒有圖表可看,一切判斷必須改由統計數字做出,這正是下半部分寫程式的原因。

Notebook 內的前期研究
正式寫策略前,講者先在 Jupyter Notebook 做可行性研究。Notebook 放在 Jesse 項目目錄內,便可直接使用其 research 模組與工具函數。關鍵步驟:
- 取數:用
research.get_candles從 Binance 永續合約分別匯入 ETH-USDT 與 ETC-USDT 的 15 分鐘 K 線,示範只取 2024 年 10 月 1 日至 3 日兩天數據。函數回傳暖機 K 線與正式 K 線兩組,研究階段只取後者。 - 轉回報:ETH 以千美元計、ETC 以百美元計,量綱不同不能直接相減,所以用 Jesse 內建的
prices_to_returns把收市價(索引 2)轉成回報序列,令兩者處於同一尺度。 - 畫圖驗證:把兩條回報序列疊畫,肉眼已見多次交叉背馳,初步支持策略假設。
# 取數並轉成回報序列(摘錄自原片教學)
exchange = 'Binance Perpetual Futures'
_, c1 = research.get_candles(exchange, 'ETH-USDT', '15m', start, finish)
_, c2 = research.get_candles(exchange, 'ETC-USDT', '15m', start, finish)
c1 = utils.prices_to_returns(c1[:, 2])
c2 = utils.prices_to_returns(c2[:, 2])

價差、Z 分數與協整
圖表只是演示,落盤機械人看不到圖,一切要化為統計量。第一步是計算價差——兩條回報序列相減。由於轉回報後首個值是 NaN,要由索引 1 起取值。第二步是把價差標準化成 Z 分數:價差減去序列均值、除以標準差,答案代表「當前背馳有幾多個標準差」。Jesse 有現成的 utils.z_score 函數。講者在 Z 分數圖上畫出均值線與 ±1.2 門檻線:跌穿 -1.2 做多第一隻、做空第二隻;升穿 +1.2 反向操作;回到均值平倉。
但還有一道關卡:協整檢定。均值回歸策略要求數據「平穩」——均值長期穩定不漂移。單一資產價格肯定不平穩,但協整的意思是:兩條各自不平穩的序列,其某種組合(這裏是價差的 Z 分數)可以是平穩的;若成立,兩者才可互相對沖交易,否則價差可能永不回歸。講者用 Jesse 的 utils.are_cointegrated 一行完成檢定(底層是 statsmodels 的 p 值檢驗),ETH 與 ETC 通過。他明言數學細節從簡,建議深入研究者看 Quantopian 的相關教學。講者還補充了一個實務細節:Notebook 示範用整段兩天數據計均值畫門檻線,是事後諸葛;實戰時均值只能用「到當刻為止」的數據計算,這一點直接影響下一節的策略寫法。
Jesse 雙策略檔架構
配對交易要同時操作兩個品種,Jesse 的回測以「交易路線」為單位,一條路線配一個策略檔,所以要建立兩個策略檔。講者的分工:PairsTrading2 只是執行層,純粹讀取指令;PairsTrading 負責全部計算與決策。兩者靠 Jesse 的 shared_vars 字典溝通——在此定義的變數對所有路線可見。四個共享變數:s1-position 與 s2-position(1 = 好倉、-1 = 淡倉、0 = 平倉),以及兩邊的保證金 s1-margin、s2-margin。執行層的 should_long 只檢查共享變數是否等於 1,update_position 在變數歸零時調用 liquidate 平倉,結構簡單。這種「一個大腦、兩對手」的設計,好處是所有狀態集中在一處維護,不會出現兩個策略檔各自判斷、訊號互相矛盾的問題。
決策全部集中在主策略的 before() 方法(Jesse 每支 K 線最先執行的鉤子),重點有三:
- 取數防前視:回測中不能像 Notebook 那樣一次過取整段數據,否則會偷看未來。改用
self.get_candles,框架保證只提供「到當刻為止」的 K 線;並且只取最近 200 支收市價——窗口太長,均值會漂移得失去參考價值;品種與時段用self.routes[0].symbol、self.timeframe動態讀取,改設定不用改代碼。 - 每日重檢協整:每 24 小時重新做一次協整檢定,一旦關係失效,立即把兩邊倉位指令歸零、停止開倉。
- 進出場訊號:只取 Z 分數序列最後一個值做判斷。
# 主策略 before() 內的進出場邏輯(摘錄自原片教學)
z = self.z_score
if self.is_close and z < -1.2:
self.shared_vars["s1-position"] = 1
self.shared_vars["s2-position"] = -1
elif self.is_long and z > 0:
self.shared_vars["s1-position"] = 0
self.shared_vars["s2-position"] = 0
elif self.is_close and z > 1.2:
self.shared_vars["s1-position"] = -1
self.shared_vars["s2-position"] = 1
首次回測的除錯插曲
值得一提講者首次按運行鈕時結果明顯有誤。追查後發現:他在策略檔直接把收市價序列拿去計價差,忘記了 Notebook 裏「先轉回報」這一步——價格量綱不同,相減出來的「價差」毫無意義。修正方法是在兩個 property 末端補上 prices_to_returns。這個小插曲對自學者其實有價值:把研究代碼搬進策略框架時,數據前處理的每一步都要原樣照搬,少一步結果就全盤走樣。另外 Jesse 的快速回測模式(fast mode)暫不支援多路線策略,回測前記得關掉,否則直接報錯。
倉位比例:對沖比率 Beta
兩邊倉位不能簡單各放一半本金。講者解釋:市值越大的資產波動越小,ETH 的價格變動幅度通常小於 ETC;若兩邊各放 1,000 美元,價格齊升時 ETC 那邊賺或虧得更多,組合就不再中性。做法是用 utils.calculate_alpha_beta 對兩條回報序列做線性迴歸,求出對沖比率 beta,再按比例分配保證金:第一倉佔 1/(1+beta)、第二倉佔 beta/(1+beta)。講者坦白這部分公式他借助了 AI 工具撰寫、靠自己反覆測試驗證有效,未能逐行解釋數學推導——想深究的讀者同樣可參考 Quantopian 的教學。
回測:由 +69% 到 -97%
首次回測結果「好得難以置信」:2024 年 1 月至 12 月約一年,10,000 美元本金錄得 69% 回報,最大回撤僅 -5.21%,勝率 53%,Sharpe ratio 2.94,Calmar ratio 13.77。疊加基準走勢後可見:升市賺錢、跌市賺錢、橫行也賺錢——只要兩隻資產維持協整的假設成立。

但講者隨即揭盅:這次回測關掉了手續費。一年 7,818 宗交易,一般散戶沒有交易所的特約費率,一旦按 Binance 實際費率重跑,權益曲線直線向下——本金由 10,000 美元跌至 343 美元,單是手續費已付約 11,000 美元。而且現實還有滑點:這策略很多交易本來只賺微利,滑點會令真實結果比這更差。

講者的結論與出路:能拿到極低費率的對沖基金或可直接交易此策略;一般散戶則要加盡可能多的濾網,只做「值得做」的交易,或改用較長時間框架減少交易次數,又或揀選波動更大、單宗利潤空間更厚的相關資產(例如互相關聯的迷因幣)。他又指出對沖基金能享有特約低費率(他估計當年 Thorp 亦然),散戶先天處於劣勢,唯一武器是揀交易。他把源碼放上 GitHub,把「加濾網改良至可實戰」留作觀眾功課,並建議可試其他市場與費率較低的交易所——而這份功課的答案,正是第 18 課的改良版內容。
🙏 覺得內容有用?本站所有內容免費提供,使用推薦碼開戶就是支持我們繼續營運的最大鼓勵:
ZA Bank 邀請碼 P20923
—— 你享 HKD 2,000 迎新獎賞,本站獲得營運支持。
立即開戶 →
(聯盟連結|投資涉及風險,受條款及細則約束,此資料僅可於香港境內分發)
MT5 可行性速評
| 項目 | 評估 |
|---|---|
| 邏輯可移植性 | 價差相減、均值、標準差、Z 分數在 MQL5 都要自建陣列用迴圈計算(無內建函數);協整檢定與線性迴歸 beta 更無現成方案,需自寫 OLS 或預先在 Python 算好定期匯入。 |
| 平台限制 | 策略涉及兩個品種:MT5 的 EA 可用 iClose 讀取多品種數據並分別落盤,但策略測試器對多品種 EA 的回測支援有限,價差合成、協整重檢與兩倉同步開平都要自行處理,工程量大。 |
| 評級 | ⚠️ 需自訂元件——核心統計元件(協整檢定、beta、Z 分數)全部要自寫,多品種回測可信度打折;建議研究與驗證留在 Python,MT5 只作執行層。 |
| MQL5 寫法提示 | 見下方示意。 |
// 示意:讀取兩品種收市價,合成回報價差(非完整 EA)
double r1 = iClose("ETHUSD", PERIOD_M15, 1) / iClose("ETHUSD", PERIOD_M15, 2) - 1;
double r2 = iClose("ETCUSD", PERIOD_M15, 1) / iClose("ETCUSD", PERIOD_M15, 2) - 1;
double spread = r1 - r2;
// 自建環形陣列儲存最近 200 個 spread,迴圈求均值與標準差,再計 z
注意:MT5 回測同樣會過度擬合——即使搬運成功,參數調校後的亮麗曲線與實盤表現可以是兩回事。
欣利克的看法
- 先問「回報由甚麼構成」再看回測數字。 這課是最好的教材:同一策略、同一時段,不計手續費是 +69%,計入費率是 -97%。7,818 宗交易平均每宗賺約 0.01%——利潤薄得只夠付成本。看回測第一步不是看總回報,而是看交易次數、平均每宗盈虧與成本假設;每宗利潤愈薄,回測數字的參考價值愈低。
- 與第 18 課對照,兩個版本是同一策略的前後世。 本課是「原始版」:固定 ±1.2 門檻、無濾網、高頻進出;第 18 課是講者實盤後的「改良版」:布林帶門檻、ADX 與趨勢濾網、最低利潤要求與組合止損,交易次數由數千宗壓至數十宗。兩課合起來,正好示範一套策略如何由概念驗證走向可執行。
- 協整關係會破裂,這是配對交易的本質風險。 講者每日重檢協整、失效即停開倉,默認了「今天協整不保證明天協整」。兩隻資產基本面一旦分道揚鑣,價差可持續擴大而不回歸,好淡兩倉同時虧損。相關與協整都是歷史統計,描述的只是過去的關係。
- 「市場中性」只是方向中性,不是無風險。 兩邊倉位比例靠 beta 估算,beta 本身來自歷史迴歸,會隨市況改變;比例失準,組合就重新暴露於方向風險。加上雙邊開倉令手續費、滑點、資金費率全部乘以二,「中性」的成本其實不低。
- 時效提醒: 片中回測期為 2024 年 1 月至 12 月,標的為 ETH 與 ETC 永續合約;截至 2026 年中,相關費率、兩幣種的相關性與市場結構或已改變,數字只作教學參考。
名詞解釋
- 配對交易 Pairs Trading:同時做多一隻、做空另一隻相關資產,賺取價差收斂的市場中性策略。
- 市場中性 Market Neutral:同時持有好倉與淡倉,令組合盈虧盡量不受大市方向影響的策略結構。
- 協整 Cointegration:兩條各自隨機遊走的價格序列,其線性組合長期穩定的性質;配對交易選對的嚴謹檢驗。
- Z 分數 Z-Score:數值偏離均值多少個標準差的標準化量度,本課用作進出場訊號。
- 均值回歸 Mean Reversion:價格或價差偏離後傾向回歸長期均值的假設,配對交易的理論基礎。
- 統計套利 Statistical Arbitrage:以統計方法尋找短暫定價失效並系統化套利的策略總稱。
- 前視偏差 Look-Ahead Bias:回測時誤用當刻未有的未來數據,令結果虛高的常見謬誤。
- 滑點 Slippage:落盤預期價與實際成交價的差距,高頻薄利策略的隱形成本。
常見問題
配對交易是否真的不論升跌市都賺錢?
只在「兩隻資產維持協整、價差最終回歸」的前提下成立。升市、跌市、橫行市都可能出現收斂機會,但協整關係一旦破裂,價差持續擴大,好淡兩倉會同時虧損。所以策略內建每日重檢協整的機制,失效即停。
為何兩邊倉位不能直接各放一半本金?
因為兩隻資產波動幅度不同:市值大的一般波動小,各放一半會令組合重新暴露於單邊風險。做法是以線性迴歸求出對沖比率 beta,按 1 比 beta 的比例分配保證金,令兩邊的盈虧敏感度對稱。
回測 +69% 的策略為何計入手續費後虧 97%?
因為一年交易 7,818 宗,平均每宗利潤極薄,單是手續費已超過本金;加上現實存在滑點,薄利交易會進一步轉虧。這正說明高頻策略的回測必須計入貼近真實的成本假設,否則數字沒有參考價值。
這課與第 18 課的配對交易教學有何分別?
本課是同頻道較早期的「原始版」:由零推導數學、固定 ±1.2 門檻、無濾網,回測證明計入成本後不可行。第 18 課是講者實盤後的改良版:布林帶門檻、ADX 與趨勢濾網、最低利潤要求與組合止損。建議先讀本課理解原理,再讀第 18 課看改良思路。
原影片
本文整理自以下影片,版權屬原創作者所有,建議配合原片觀看: