貝葉斯優化實作 Lab 6:用 Python 改良交易策略參數的完整流程
第 30 課・共 34 課
目錄
理論學完就要動手。本講是 Liu Peng 課程的 Lab 6 實作課,承接第 25 講的貝葉斯優化框架與第 26 講的高斯過程及採集函數數學,示範如何用 Python 的 BoTorch 函式庫,為配對交易策略的入場與離場門檻做貝葉斯優化(Bayesian Optimization)調參,並同場比較四種採集函數的搜索效率。本篇筆記按原片脈絡重構,公式以 LaTeX 重寫。
學習重點
- 把整個交易策略(下載數據、計算價差、產生訊號、回測)包裝成單一黑盒函數:輸入參數、輸出夏普比率
- 貝葉斯優化的實作骨架:隨機初始點 → 擬合高斯過程 → 最大化採集函數提議新點 → 求值並更新數據,循環往復
- 四種採集函數同場比較:EI、qEI、UCB、qKG,並設純隨機抽樣作對照組
- 單次試驗可能靠運氣,重複實驗取均值與標準差才能判斷方法是否穩定
- 實驗結果:四種貝葉斯優化策略找到的最佳夏普比率全部高於隨機抽樣,且波動更小
詳細筆記
實驗目標:把交易策略視為黑盒函數
本 Lab 要解決的問題很具體:沿用上一堂實作課的配對交易策略(以 GOOG 與 MSFT 為例),策略有兩個可調的「旋鈕」——入場門檻 entry threshold 與離場門檻 exit threshold。目標是找到一組門檻,令回測得出的夏普比率 Sharpe Ratio 最大化。
講者把整個策略視為一個黑盒函數 $f$:輸入兩個門檻參數,輸出一個夏普比率,中間的數據下載、價差計算、訊號生成與績效統計全部隱藏在函數內部。這正是貝葉斯優化的標準設定——目標函數沒有解析式、不能求導、每次求值成本高(要跑完整回測),傳統梯度法與窮舉法都不適用。
黑盒函數類別:由數據下載到夏普比率
實作上,講者建立一個繼承 PyTorch nn.Module 的類別。繼承並非必須,純粹是貪其方便:直接呼叫物件實例就會觸發底層的 forward 函數,令「呼叫策略」與「呼叫函數」寫法一致。
初始化函數接收股票代號組合、起始日期、結束日期與無風險利率(預設 4%),實例化時自動以 yfinance 下載調整後收盤價並存為物件屬性。核心運算集中在 forward 函數,接收入場門檻、離場門檻與滾動窗口長度(預設 10),流程如下:
- 估計對沖比率:以最小二乘法(OLS)對兩隻股票價格擬合線性關係,價差定義為實際值與擬合值之差 $s_t = Y_t - (\hat{\alpha} + \hat{\beta} X_t)$。講者特別說明,價差的定義並無標準答案,這只是眾多做法之一。
- 計算 Z 分數:以滾動窗口計算價差的均值與標準差,得出 $z_t = \dfrac{s_t - \bar{s}_t}{\hat{\sigma}_t}$,作為價差偏離常態的度量。
- 生成交易訊號:Z 分數越過入場門檻即開倉(一腿造好、一腿造淡),回落至離場門檻之內即平倉,其餘時間維持原倉。這段迴圈邏輯與上一堂實作課相同,原片略過不重複。
- 績效年化:兩腿回報相加得策略總回報序列,先做複利累乘再折算成年化回報(假設一年 252 個交易日):
年化波動率利用「方差隨時間線性增長」的性質,將日度標準差乘以時間平方根:
$$\sigma_{ann} = \sigma_{daily} \times \sqrt{252}$$若波動率為零,則以一個大數代入避免除零錯誤。最後輸出夏普比率:
$$S = \frac{R_{ann} - r_f}{\sigma_{ann}}$$講者現場示範:以 2022 年初起的 GOOG/MSFT 數據實例化,傳入一組門檻即回傳夏普比率 1.69;換一組參數,數值隨即改變。問題正式浮現——如何在參數空間中系統性地找到最大夏普比率。
黑盒函數類別的程式碼結構。截圖出自原片(Liu Peng)
生成初始訓練數據
BoTorch 建基於 PyTorch,可善用 GPU 加速,因此先設定運算裝置(device)與數據類型(dtype),並固定隨機種子令結果可重現。搜索邊界方面,入場門檻允許在 $x_1 \in [1, 3]$ 之間變化,離場門檻則在 $x_2 \in [0, 1]$ 之間。
初始訓練集以均勻隨機抽樣產生三個點:先在 $[0,1]$ 抽取隨機數 $u$,再線性映射 $x_1 = 1 + 2u$ 到目標區間;$x_2$ 本身已在 $[0,1]$ 之內,無需縮放。然後用迴圈逐點呼叫黑盒函數,取得對應的夏普比率,組成初始訓練集,同時記錄當前最佳觀測值(best observed value),作為 EI 類採集函數的基準。
初始化高斯過程模型與超參數優化
模型初始化函數做三件事:以 SingleTaskGP 建立高斯過程代理模型、以 ExactMarginalLogLikelihood 構建邊際對數似然,然後用 fit_gpytorch_mll 優化模型自身的超參數——包括核函數的長度尺度、輸出尺度與噪聲方差。講者展示了優化前後的對比:初始超參數是一組預設值,擬合後明顯改變,代表模型更貼合手頭的觀測數據。
這一步呼應第 26 講的重點:高斯過程後驗的品質,直接決定採集函數提議的品質,所以每一輪有新數據進來,都要重新擬合一次。原片亦保留了加入觀測噪聲的註解程式碼,示範當回測結果帶有隨機誤差時,可在似然函數層面如實反映,而非假裝觀測完美無誤。
四種採集函數同場較量
本 Lab 的亮點,是並排比較四種採集策略,各自配一套獨立的高斯過程模型與訓練數據,由相同的三個初始點出發,確保公平:
- EI:預期改善,$\text{EI}(x) = \mathbb{E}\left[\max(f(x) - f^{*}, 0)\right]$,以當前最佳觀測 $f^{*}$ 為基準計算期望增益
- qEI:EI 的批量並行版本,可同時評估多個候選點
- UCB:上置信界,$\text{UCB}(x) = \mu(x) + \beta\,\sigma(x)$,在後驗均值與不確定性之間取加權
- qKG:批量知識梯度,內部以蒙地卡羅「幻想」模擬(
num_fantasies設為 64)推演採樣後後驗的變化,探索傾向最強,參數需求也最多
提議新點的機制統一封裝成一個函數:呼叫 optimize_acqf 最大化採集函數,採用多起始點優化(10 組重啟、1024 個原始樣本作初始化啟發),批量大小設為 1,即每輪只提議一個新點。取得候選位置後,呼叫黑盒函數求得真實夏普比率,轉換格式後回傳。
採集函數的優化與新觀測獲取流程。截圖出自原片(Liu Peng)
序貫搜索循環與隨機對照組
主循環共跑 20 輪迭代。每一輪的動作:各策略因應新數據重新擬合高斯過程 → 初始化各自的採集函數 → 各自提議新點並求值 → 把新觀測追加到各自的訓練集 → 更新「至今最佳」的夏普比率紀錄 → 重新初始化模型,準備下一輪。
同場設有純隨機抽樣作為對照組:每輪不建模,直接在邊界內隨機取點求值,再與各策略同步更新各自的「至今最佳」紀錄。這個對照組不可或缺——它回答一個根本問題:花力氣建模,是否真的比亂槍打鳥好?值得注意的是,「至今最佳」採累積最大值計算,即新觀測只有超越歷史紀錄才會推高曲線,因此所有走勢線都是單調不減的階梯形,比較的重點在於誰爬升得快、誰的最終平台更高。
結果解讀:效率、效力與穩定性
單次試驗的走勢圖以迭代次數為橫軸、至今最佳夏普比率為縱軸。結果顯示 UCB 用最少的迭代次數鎖定最高夏普比率(逼近 3.0);EI 與 qEI 在中段逐步追上;qKG 因探索較多,上升最慢。但重點是:四種貝葉斯優化策略的最終表現全部明顯優於隨機抽樣。
20 輪迭代的搜索進度比較。截圖出自原片(Liu Peng)
講者特別提醒,單次試驗可能純靠運氣,於是把整個實驗重複 4 次,抽取各策略最終最佳值,計算均值與標準差。結果顯示:UCB 均值最高(約 2.79),EI、qEI、qKG 緊隨其後(約 2.71 至 2.74),全部高於隨機策略的約 2.47;更重要的是,四種貝葉斯優化策略的標準差(約 0.11 至 0.15)全部小於隨機策略的約 0.25。換言之,貝葉斯優化不但找到更好的參數,結果也更穩定,證明此方法在定位全局最優上兼具效率與效力。
重複實驗後各策略的均值與標準差比較表。截圖出自原片(Liu Peng)
🙏 覺得內容有用?本站所有內容免費提供,使用推薦碼開戶就是支持我們繼續營運的最大鼓勵:
ZA Bank 邀請碼 P20923
—— 你享 HKD 2,000 迎新獎賞,本站獲得營運支持。
立即開戶 →
(聯盟連結|投資涉及風險,受條款及細則約束,此資料僅可於香港境內分發)
欣利克的看法
- 樣本內最優不等於未來最優。貝葉斯優化找到的是「這段歷史數據下回測夏普比率最高」的參數,本質仍是回測優化。方法再先進,過度擬合的風險也不會消失——參數在樣本外是否成立,原片並未處理,這是讀者自行延伸時必須補做的一步。
- UCB 勝出不可推廣成普遍結論。本次實驗只有一個股票組合、一段時期、兩維參數空間,UCB 跑贏只是這個特定設定下的結果。換一個目標函數或提高維度,排名可以完全不同;原片亦只陳述實驗現象,沒有宣稱哪種採集函數「最好」。
- 貝葉斯優化的價值在於「昂貴求值」場景。本例每次求值要跑完整回測,20 輪已見成效,正是貝葉斯優化的主場。但若參數只有兩維、回測又便宜,網格搜索其實未必輸——選工具應看求值成本與維度,而非盲目追新。
- 實驗規模屬教學級別,時效有限。數據只涵蓋 GOOG/MSFT 約一年半的歷史,重複 4 次亦屬小樣本,統計結論僅供教學參考。此外 BoTorch 與 GPyTorch 迭代迅速,截至 2026 年中其 API 可能已與原片不同,動手重現時宜先核對版本文件。
名詞解釋
- 貝葉斯優化 Bayesian Optimization:代理模型加採集函數的昂貴黑盒函數優化框架
- 高斯過程 Gaussian Process:本課的代理模型,為未觀測點提供均值與不確定性
- 採集函數 Acquisition Function:為候選點評分、決定下一採樣位置的人工設計函數
- 預期改善 Expected Improvement:以當前最佳觀測為基準的期望邊際增益,本課四策略之一
- 上置信界 Upper Confidence Bound:後驗均值加 β 倍標準差的採集函數,本實驗表現最佳
- 知識梯度 Knowledge Gradient:以蒙地卡羅模擬衡量資訊增益的進階採集函數,探索傾向最強
- BoTorch 貝葉斯優化函式庫:建基於 PyTorch 的開源貝葉斯優化工具,本 Lab 的核心工具
- 夏普比率 Sharpe Ratio:每單位風險的超額回報,本課的優化目標
- Z 分數 Z-Score:價差偏離滾動均值的標準化倍數,交易訊號的依據
- 配對交易 Pairs Trading:一長一短兩腿買賣價差回歸的市場中性策略
- 蒙地卡羅模擬 Monte Carlo Simulation:以大量隨機抽樣推算期望值的方法,qKG 內部所用
- 過度擬合 Overfitting:參數過度遷就歷史數據而失效於樣本外的風險
常見問題 FAQ
為甚麼要用 nn.Module 包裝交易策略?
這純粹是寫法上的便利,與神經網絡無關。繼承 nn.Module 後,直接呼叫物件實例便會觸發 forward 函數,令「傳入參數、取回夏普比率」的寫法與普通函數一致,配合 BoTorch 以張量傳遞參數的習慣也更順手。原片明確指出繼承是可選的,用普通類別或函數同樣可行。
貝葉斯優化與網格搜索、隨機搜索有何分別?
網格搜索與隨機搜索對每個試點一視同仁,完全不利用已累積的觀測結果;貝葉斯優化則每輪用高斯過程消化已有數據,由採集函數權衡「在看好區域加碼」與「往未知區域探索」,令每一次昂貴的回測都更有目的。本實驗的對照組證實:同樣 20 次求值,建模搜索找到的最佳值明顯高於純隨機抽樣,且結果更穩定。
qKG 探索最多、上升最慢,是否代表它最差?
不能這樣下結論。qKG 的設計目標是衡量每次觀測的資訊價值,傾向先掌握全局再收斂,短期內「至今最佳值」上升較慢是預期行為。本實驗參數空間只有兩維、預算只有 20 輪,探索的長遠回報未必兌現;在更高維、噪聲更大的問題上,它的策略可能更有優勢。最終統計中 qKG 的均值仍高於隨機對照組,誤差也較小。
這個實驗找到的最佳門檻可以直接用於實盤嗎?
不可以這樣推論。實驗優化的是特定歷史區間的回測夏普比率,屬樣本內結果;交易成本、滑價與數據偏差均未在示範中處理,且重複次數有限。原片目的是展示貝葉斯優化的工作流程,而非產出可交易的參數,任何參數都應先經過樣本外驗證,本課內容亦不構成任何投資建議。
原影片
本文整理自以下影片,版權屬原創作者所有,建議配合原片觀看: