返回目錄
A
數據驅動的投資決策:金融分析與機器學習實務 - 第 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())
```
---
> **提示**:上述範例僅為學術示範,實務部署時請自行加入 **滑點、手續費**、**風險控管** 以及 **多個資產同步執行** 的細節。