跳轉至

建立 2025-02-24 更新 2026-09-16

交易策略回測

回測(Backtesting)是把交易策略套用到歷史資料上,看看如果過去真的照這套規則交易,結果會是賺是賠。回測不能保證未來也會賺錢,但至少能先排除明顯不可行的策略,並抓出策略在什麼市況下容易失效。

回測想確認的三件事

  1. 策略是否有效:長期是否有正報酬,而不是只在特定一段時間湊巧賺錢。
  2. 風險有多大:過程中最大會虧掉多少(最大回撤),見績效指標與風險管理。
  3. 參數是否穩健:稍微調整參數(例如均線天數),績效是否劇烈翻轉——劇烈翻轉通常代表策略是湊出來的,不夠穩健。

使用 backtesting.py 回測

backtesting.py 是輕量、上手快的回測框架,適合驗證入門策略。

pip install backtesting
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
from backtesting.test import SMA, GOOG   # GOOG 是套件內建的範例資料


class SmaCross(Strategy):
    n1 = 10
    n2 = 20

    def init(self):
        close = self.data.Close
        self.sma1 = self.I(SMA, close, self.n1)
        self.sma2 = self.I(SMA, close, self.n2)

    def next(self):
        if crossover(self.sma1, self.sma2):
            self.buy()
        elif crossover(self.sma2, self.sma1):
            self.sell()


bt = Backtest(GOOG, SmaCross, cash=10_000, commission=0.002, exclusive_orders=True)
stats = bt.run()
bt.plot()

bt.run() 回傳的 stats 會包含總報酬、勝率、夏普比率、最大回撤等關鍵數據,是評估策略好壞的第一手資料。

進階選擇:backtrader

如果需要更複雜的多資產、多時間框架回測,或要接上實際券商下單,backtrader 是更完整的框架:

pip install backtrader
import backtrader as bt

class SmaCross(bt.Strategy):
    def __init__(self):
        self.sma = bt.indicators.SimpleMovingAverage(self.data, period=20)

    def next(self):
        if self.data.close[0] > self.sma[0]:
            self.buy()
        elif self.data.close[0] < self.sma[0]:
            self.sell()

cerebro = bt.Cerebro()
cerebro.addstrategy(SmaCross)
cerebro.run()

參數調校

測試不同參數組合,觀察績效是否穩定,而不是只找出「最佳」的單一組合(過度配適歷史資料,實務上常常失靈):

for n1, n2 in [(10, 20), (20, 50), (50, 100)]:
    class Params(SmaCross):
        pass
    Params.n1, Params.n2 = n1, n2
    stats = Backtest(GOOG, Params, cash=10_000).run()
    print(n1, n2, stats["Return [%]"])

上面的寫法是最直覺的做法:一個一個參數組合跑迴圈,組合一多就會很慢。如果要一次測試大量參數組合,更有效率的做法是改用下方的向量化回測框架 vectorbt。

用 vectorbt 做向量化回測

backtesting.py、backtrader 都是逐根 K 棒(bar-by-bar)跑迴圈,邏輯直覺但速度較慢。vectorbt 改用 NumPy 向量化運算,把整段價格序列一次算完,同時測試成百上千組參數只需要幾秒鐘,特別適合「參數調校」這種需要大量嘗試的場景。

pip install vectorbt
import vectorbt as vbt

price = vbt.YFData.download("AAPL", start="2023-01-01", end="2024-01-01").get("Close")

fast_ma = vbt.MA.run(price, 10)
slow_ma = vbt.MA.run(price, 20)

entries = fast_ma.ma_crossed_above(slow_ma)
exits = fast_ma.ma_crossed_below(slow_ma)

portfolio = vbt.Portfolio.from_signals(price, entries, exits, init_cash=10_000, fees=0.002)
print(portfolio.stats())

一次測試大量參數組合

用 run_combs 把多組均線天數兩兩配對,一次算出所有組合的績效,取代前面「參數調校」的手寫迴圈:

fast_windows = list(range(5, 50, 5))
slow_windows = list(range(20, 200, 20))

fast_ma, slow_ma = vbt.MA.run_combs(
    price, window=fast_windows + slow_windows, r=2, short_names=["fast", "slow"]
)
entries = fast_ma.ma_crossed_above(slow_ma)
exits = fast_ma.ma_crossed_below(slow_ma)

portfolio = vbt.Portfolio.from_signals(price, entries, exits, init_cash=10_000, fees=0.002)
print(portfolio.total_return().sort_values(ascending=False).head())   # 報酬率最高的前幾組參數

開源版本更新較慢,但仍是入門首選

這裡使用的是開源版 vectorbt,近年更新頻率較低;官方另有維護中的付費版 vectorbt PRO。學習向量化回測的概念,開源版已經足夠,之後有實際需求再評估是否升級。

動手做

7-1 簡單回測實作 用 backtesting.py 完整示範上方的均線交叉策略,可直接在 Colab 開啟執行。

推薦影音

Backtesting.py 實戰教學

簡述:Part Time Larry(README 也推薦的量化 YouTuber)示範如何用 backtesting.py 撰寫策略、執行回測並解讀績效報表,內容與本頁的 backtesting.py 範例直接對應。

Backtrader 入門

簡述:介紹 backtrader 框架的基本架構與寫法,適合之後想換用更完整、功能更多的回測框架時參考。

vectorbt 完整教學

簡述:Chad Thackray(本頁上方 Backtesting.py 教學的同一位講師)完整示範 vectorbt 的向量化回測流程,包含下載資料、建立訊號到大量參數組合的績效比較,對應本頁「用 vectorbt 做向量化回測」的部分。