聊天視窗

數據驅動的投資決策:金融分析與機器學習實務 - 第 5 章

5. 量化交易策略設計

發布於 2026-02-24 02:49

# 5. 量化交易策略設計 在本章,我們將把理論與方法論結合,從零開始設計、測試、優化並部署一套完整的量化交易策略。內容分為五個主要階段: 1. **策略構思與設計原則** 2. **因子研究與信號生成** 3. **風險控制與資金管理** 4. **執行成本與交易日誌** 5. **回測、優化與實際部署** 每個階段都配備實作範例、程式碼片段以及實務心得,讓讀者能即時轉化為可執行的投資策略。 --- ## 5.1 策略構思與設計原則 | 步驟 | 目的 | 重要指標 | |------|------|----------| | 1. 研究市場機制 | 確定交易商品、時間框架、風險承受度 | 市場有效性、波動率 | | 2. 選擇投資邏輯 | 趨勢跟隨、均值回歸、套利 | 信號可靠度、風險回報比 | | 3. 定義交易規則 | 入場、平倉、止損 | 交易成本、滑點 | | 4. 評估可行性 | 回測盈虧、最大回撤、夏普率 | 可執行性、資金需求 | > **最佳實務**:在策略設計初期就引入風險控制(例如最大單筆虧損上限、最大持倉數量)與交易成本模型,避免在回測後期才發現策略不可行。 ### 5.1.1 例子:簡易的 20 日均線交叉策略 ```python import pandas as pd import numpy as np # 假設 df 已載入包含 Close 之 OHLCV 資料 # 計算 20 日簡單移動平均 SMA20 = df['Close'].rolling(window=20).mean() # 計算 50 日簡單移動平均 SMA50 = df['Close'].rolling(window=50).mean() # 產生信號:當 SMA20 上穿 SMA50 時為多單,反之為空單 signal = np.where(SMA20 > SMA50, 1, -1) # 將信號轉為 pandas Series,對於 NA 設為 0 signal = pd.Series(signal, index=df.index).fillna(0).astype(int) ``` 此範例僅作為思考導向;實務中須加入波動率縮放、交易成本與風險控管。 --- ## 5.2 因子研究與信號生成 ### 5.2.1 因子定義 | 因子類型 | 代表性指標 | 參考來源 | |----------|------------|----------| | 技術因子 | 移動平均、RSI、MACD | Technical Analysis | | 基本因子 | ROE、EPS、PE | 財報資料 | | 情緒因子 | Twitter 與 Reddit 熱度、Google Trends | 文字挖掘 | | 宏觀因子 | CPI、利率、貨幣供給 | 統計局 | ### 5.2.2 因子選擇與正交性 1. **相關性矩陣**:計算各因子之間的皮爾森相關係數,避免高度相關的重複信號。 2. **因子排序**:使用**多因子模型**(例如 Carhart 4 因子)或 **LASSO** 來篩選有效因子。 3. **因子效能回測**:在不同時間區間、不同市場環境下驗證因子表現。 ### 5.2.3 信號生成流程 ```python import pandas as pd import numpy as np from ta.trend import SMAIndicator from ta.momentum import RSIIndicator # 讀取價格資料 price = pd.read_csv('prices.csv', index_col='date', parse_dates=True) # 計算技術指標 sma = SMAIndicator(price['close'], window=20).sma_indicator() rs = RSIIndicator(price['close'], window=14).rsi() # 組合因子:簡易加權平均 factor_signal = 0.5 * (sma / price['close']) + 0.5 * (rs / 100) # 信號:正值為買進,負值為賣出 signal = np.sign(factor_signal) ``` > **實務提示**:將因子輸出標準化(z-score)可減少因子偏差,並在多因子組合時保持因子之間的正交性。 --- ## 5.3 風險控制與資金管理 ### 5.3.1 風險度量指標 | 指標 | 定義 | 公式 | |------|------|------| | 最大回撤(Max Drawdown) | 最高峰值到最低谷的最大跌幅 | | 風險調整報酬 | 夏普率、Sortino 比率 | | VaR / CVaR | 置信水平下的風險閾值 | ### 5.3.2 資金分配策略 1. **Kelly 定理**: $$f^* = rac{p - q}{b}$$ 其中 p 為勝率、q 為敗率、b 為勝利倍數。 2. **動態加權**:依據波動率調整持倉比例(如 ATR 乘數) 3. **固定比率**:例如每筆交易佔可用資金的 1-2% 以控制單一風險。 ### 5.3.3 交易成本模型 | 成本類型 | 估算方法 | |----------|-----------| | 滑點 | 市場深度與成交量模型 | | 手續費 | 交易所費率、經紀商費率 | | 其他 | 稅金、場內成本 | 成本可在回測時加以模擬,亦可在實盤使用 API 取得實際成本。 > **風險控管實務**:在設計策略時,務必在「信號」生成之前先將風險與成本納入模型,這樣才能在回測階段即看見真實盈虧。 --- ## 5.4 執行成本與交易日誌 ### 5.4.1 執行層面 - **撮合系統**:使用 **backtrader**、**zipline**、或 **cerebro** 等 Python 框架。 - **訊號同步**:確保信號產生與執行時間同步,避免因時間偏差造成損失。 - **滑點校正**:可用 **Historical Tick** 或 **Orderbook** 來測試滑點影響。 ### 5.4.2 交易日誌設計 ```python import json from datetime import datetime # 記錄交易訊息 trade_log = { 'time': datetime.utcnow().isoformat(), 'symbol': 'AAPL', 'action': 'BUY', 'price': 150.23, 'qty': 100, 'cost': 0.75, 'status': 'FILLED' } with open('trade_log.json', 'a') as f: f.write(json.dumps(trade_log) + '\n') ``` > **建議**:交易日誌不僅保存價格與手續費,更要記錄**滑點、成交時間、理由**,方便日後審計與策略調整。 --- ## 5.5 回測、優化與實際部署 ### 5.5.1 回測框架 | 框架 | 特色 | |------|------| | **Backtrader** | 開源、支持多資產、內建風險管理 | | **Zipline** | Twitter 內部框架、可與 Quantopian API 連結 | | **Pandas‑TA + Custom** | 簡潔、易於自訂、適合小規模策略 | ### 5.5.2 參數優化方法 | 方法 | 優點 | 局限 | |------|------|------| | Grid Search | 簡單直觀 | 時間複雜度高 | | Bayesian Optimization (Optuna, Hyperopt) | 節省時間、搜尋全域 | 需額外安裝、過擬合風險 | | Walk‑Forward Analysis | 逐步擴大驗證 | 計算量大 | ```python # Optuna 進行 20/50 SMA 交叉策略參數優化 import optuna import backtrader as bt def objective(trial): s1 = trial.suggest_int('sma1', 10, 30) s2 = trial.suggest_int('sma2', 30, 60) # 建立回測引擎 cerebro = bt.Cerebro() cerebro.addstrategy(MacCrossStrategy, sma1=s1, sma2=s2) cerebro.run() stats = cerebro.broker.getvalue() - cerebro.broker.startingcash return stats / (cerebro.broker.getvalue() * 0.01) # 風險調整報酬 study = optuna.create_study(direction='maximize') study.optimize(objective, n_trials=50) print(study.best_params) ``` ### 5.5.3 部署策略 | 步驟 | 工具 | |------|------| | 連接交易所 | IB API、Interactive Brokers、Oanda | | 實時監控 | Prometheus + Grafana、Jupyter Dashboards | | 失敗自動化 | 監控腳本、Slack 通知 | | 監控日誌 | ElasticSearch + Kibana | > **部署實務**:建議先在模擬帳戶上進行 **逐日** 部署,確保交易機制、風險控制、成本模型在真實環境下均能正常工作,才進行正式資金投入。 --- ## 5.6 期末總結與未來展望 - **策略設計**:從市場機制出發,結合因子、信號、風險與成本,才能確保策略在實盤中的可執行性。 - **因子研究**:正交化與效能驗證是提升策略可靠度的關鍵。 - **風險控制**:動態資金分配與成本模型能顯著提升真實投資表現。 - **回測與優化**:不僅是數值評估,更要驗證模型在不同市場環境下的穩健性。 - **持續監控**:交易日誌、風險警報與成本追蹤是策略長期成功的基石。 > **未來探索**:結合機器學習 (如 LSTM、Transformer) 進行時間序列預測,或使用多邊交易 (Triangular Arbitrage) 等更複雜策略。這些進階主題將在後續的第 6 章「機器學習風險管理」與第 7 章「人工智慧投資平台」中深入討論。 --- ## 5.7 附錄:Jupyter Notebook 範例(簡易 20/50 SMA 交叉) ```python # 1. 匯入套件 import pandas as pd import numpy as np import backtrader as bt from datetime import datetime # 2. 讀取資料 data = pd.read_csv('prices.csv', index_col='date', parse_dates=True) # 3. 建立 Backtrader 資料源 class PandasData(bt.feeds.PandasData): params = ( ('datetime', None), ('open', 'Open'), ('high', 'High'), ('low', 'Low'), ('close', 'Close'), ('volume', 'Volume'), ('openinterest', None), ) # 4. 定義策略 class SMAcrossStrategy(bt.Strategy): params = dict(sma1=20, sma2=50) def __init__(self): self.sma1 = bt.indicators.SimpleMovingAverage(self.data.close, period=self.p.sma1) self.sma2 = bt.indicators.SimpleMovingAverage(self.data.close, period=self.p.sma2) self.crossover = bt.indicators.CrossOver(self.sma1, self.sma2) def next(self): if not self.position: if self.crossover > 0: # 上穿 self.buy() elif self.crossover < 0: # 下穿 self.sell() else: # 風險控制:使用 ATR 進行動態止損 atr = bt.indicators.AverageTrueRange(self.data, period=14) if self.position.size > 0: if self.data.close < self.position.price - 1.5 * atr[0]: self.close() else: if self.data.close > self.position.price + 1.5 * atr[0]: self.close() # 5. 設定回測引擎 cerebro = bt.Cerebro() cerebro.addstrategy(SMAcrossStrategy) cerebro.adddata(PandasData(dataname=data)) cerebro.broker.setcash(100000.0) cerebro.broker.setcommission(commission=0.001) # 6. 執行回測 cerebro.run() # 7. 輸出結果 print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) ``` --- > **提示**:上述範例僅為學術示範,實務部署時請自行加入 **滑點、手續費**、**風險控管** 以及 **多個資產同步執行** 的細節。