返回目錄
A
數據驅動的投資分析:從基礎到實戰 - 第 6 章
第六章 交易策略的構建與測試:模擬與實盤
發布於 2026-02-27 09:31
# 第六章 交易策略的構建與測試:模擬與實盤
在前幾章我們已經掌握了數據蒐集、清洗、因子構建與風險管理。這一章將帶你進入實戰的核心:從策略生成到回測、成本模擬,最終落到實盤執行。
## 1. 策略設計的三大支柱
| 支柱 | 目的 | 主要工具 |
|------|------|----------|
| **訊號生成** | 從數據中挖掘可交易的訊號 | 技術指標、機器學習模型、因子投資法 |
| **風險控制** | 防止過度風險集中 | 位置大小、止損、風險/報酬比率 |
| **執行機制** | 確保訊號被有效轉化為交易 | 交易 API、限價/市價單、滑點控制 |
> **註**:訊號與執行必須同步,否則訊號即使準確也可能因執行延遲而失效。
## 2. 策略生成:從想法到代碼
1. **概念定義**:先寫出策略規則的文字說明。
```
當移動平均線 MA50 穿越 MA200 且 RSI(14) < 30 時買入,
當 MA50 穿越 MA200 且 RSI(14) > 70 時賣出。
```
2. **資料需求**:確定需要的時間頻率、行情類型與因子。
3. **開發框架**:選擇適合的 backtesting library,例如
- Backtrader (Python)
- Zipline (Python)
- TradingView Pine Script
- QuantConnect Lean (C# / Python)
> **案例**:使用 Backtrader 實作簡易均線交叉策略
>
> ```python
> import backtrader as bt
>
> class MA_Cross(bt.Strategy):
> params = (('ma_short', 50), ('ma_long', 200), ('rsi_period', 14), ('rsi_overbought', 70), ('rsi_oversold', 30))
>
> def __init__(self):
> self.ma_short = bt.indicators.SimpleMovingAverage(self.data.close, period=self.p.ma_short)
> self.ma_long = bt.indicators.SimpleMovingAverage(self.data.close, period=self.p.ma_long)
> self.rsi = bt.indicators.RelativeStrengthIndex(self.data.close, period=self.p.rsi_period)
> self.crossover = bt.indicators.CrossOver(self.ma_short, self.ma_long)
>
> def next(self):
> if not self.position:
> if self.crossover > 0 and self.rsi < self.p.rsi_oversold:
> self.buy()
> elif self.crossover < 0 and self.rsi > self.p.rsi_overbought:
> self.sell()
> else:
> if self.position.size > 0 and self.crossover < 0:
> self.close()
> elif self.position.size < 0 and self.crossover > 0:
> self.close()
> ```
>
> 這段程式碼已經涵蓋了訊號生成與位置管理。
## 3. 回測框架搭建
### 3.1 基礎回測流程
1. **載入歷史數據**:格式化為 OHLCV、時間戳、頻率。
2. **初始化策略**:傳入參數、指標。
3. **執行回測**:模擬交易、計算報酬。
4. **結果統計**:CAGR、Sharpe、最大回撤、勝率等。
### 3.2 高級特性
| 功能 | 目的 | 示範代碼 |
|------|------|----------|
| **多因子交叉驗證** | 避免樣本外誤差 | `bt.indicators.CrossOver(ma_short, ma_long, plot=False)` |
| **Walk‑Forward 分析** | 真實投資環境驗證 | 參考 `bt.algos.CrossCumulativeReturn()` |
| **時間權重回測** | 較長時間跨度的波動調整 | 參考 `bt.algos.TimeWeightedReturn()` |
> **實作建議**:盡量保持數據前處理、交易邏輯與風險控制分離,方便單元測試。
## 4. 成本模擬:滑點與手續費
| 成本類型 | 模擬方法 |
|----------|----------|
| **手續費** | 固定費用或百分比 | `commission = 0.0005` (即 5bps) |
| **滑點** | 價格波動與深度模型 | 隨機分佈:`slippage = 0.001 * random.random()` |
| **市場沖擊** | 大量單筆交易對行情影響 | 參考「Merton 模型」或簡化「Price Impact」公式 |
### 4.1 以 Backtrader 為例
```python
class SlippageExample(bt.Strategy):
def __init__(self):
self.slow_ma = bt.indicators.SimpleMovingAverage(self.data.close, period=50)
self.fast_ma = bt.indicators.SimpleMovingAverage(self.data.close, period=20)
def next(self):
if self.fast_ma > self.slow_ma:
self.buy(exectype=bt.Order.Market, price=self.data.close[0] * (1 + 0.001))
```
> **注意**:滑點應隨時間、流動性與行情波動動態調整。
## 5. 實盤執行:從測試到現場
### 5.1 執行流程
1. **策略同步**:將回測策略代碼部署到實盤環境。
2. **行情接口**:選擇 Broker API(如 Interactive Brokers、Alpaca、OANDA、MetaTrader)。
3. **下單邏輯**:檢查市場開放、合約可交易性。
4. **風險檢查**:確保每日風險限制、資金比例不超過。
5. **監控與回報**:實時紀錄交易、報酬、風險指標,並提供告警機制。
### 5.2 常見 Broker API 範例
| Broker | API | 支援語言 |
|--------|-----|----------|
| Interactive Brokers | IB‑Python | Python |
| Alpaca | REST / WebSocket | Python, Node.js |
| OANDA | REST | Python, Java |
| Tradier | REST | Python, Ruby |
#### 5.2.1 Alpaca 範例
```python
from alpaca_trade_api import REST
import pytz
api = REST('APCA-API-KEY-ID', 'APCA-API-SECRET-KEY', base_url='https://paper-api.alpaca.markets')
# 把策略訊號轉為 Order
if signal == 'buy':
api.submit_order(
symbol='AAPL',
qty=100,
side='buy',
type='market',
time_in_force='gtc'
)
```
### 5.2 風險監控與自動化
- **日誌**:使用 `logging` 追蹤每筆訂單、執行情況。
- **容錯機制**:若連線中斷,自動重連或暫停策略。
- **資金管理**:每天檢查是否超過最大持倉比例。
- **持倉平衡**:使用「Portfolio‑Balanced」或「Kelly」公式。
> **最佳實踐**:在低頻率實盤環境(如日線)下先用紙交易(Paper Trading)測試執行邏輯,確保不會因 API 速率限制或延遲導致錯過訊號。
## 6. 策略優化與迭代
| 步驟 | 目的 | 工具 |
|------|------|------|
| **超參數優化** | 找到最佳參數集合 | `bt.indicators.BollingerBands` + `bt.algos.RunOnce` |
| **參數空間探索** | 避免過度擬合 | `scipy.optimize` 或 `Optuna` |
| **性能監測** | 長期策略持續檢驗 | Grafana + Prometheus |
### 6.1 Optuna 範例
```python
import optuna
def objective(trial):
ma_short = trial.suggest_int('ma_short', 10, 100)
ma_long = trial.suggest_int('ma_long', 100, 300)
# 建立回測環境、執行、回傳最大回撤作為目標
max_dd = run_backtest(ma_short, ma_long)
return -max_dd # 目標最小化
study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=200)
```
## 7. 風險與回測品質的持續檢核
| 檢查項目 | 方法 |
|----------|------|
| **數據完整性** | 檢查缺失值、重複、時區一致 | `data.isnull().sum()` |
| **單元測試** | 驗證策略核心邏輯 | `pytest` + `unittest` |
| **回測隔離** | 每次回測使用獨立數據副本 | `data_copy = data.copy()` |
| **CI/CD** | 每次提交自動執行單元與回測 | GitHub Actions + Docker |
### 7.1 GitHub Actions 範例
```yaml
name: Backtest CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
- name: Install Dependencies
run: pip install -r requirements.txt
- name: Run Backtest
run: python run_backtest.py
- name: Upload Results
uses: actions/upload-artifact@v2
with:
name: backtest-results
path: results/
```
## 8. 應對實盤突發:危機管理
| 風險 | 應對措施 |
|------|-----------|
| **交易停止** | 在市場熔斷、系統崩潰時自動停止交易 | 監控 `orderstatus`、`margin` |
| **連續虧損** | 快速止損、策略暫停 | `if dd > 0.3: self.position.close(); self.enabled = False` |
| **資金枯竭** | 風險/報酬比失衡 | 定期重新評估 `max_drawdown` |
> **案例**:在行情異常波動時,將止損價設定為 10% 之內,並在三天內停用策略。
## 9. 小結
> **關鍵字**:訊號、成本、風險、執行。只有三者同步,策略才能在真實市場中持續產生正向報酬。
- **訊號**:保持簡潔、可解釋,避免過度擬合。
- **回測**:盡量多層驗證(交叉、walk‑forward)。
- **成本**:滑點與手續費必須模擬到位。
- **實盤**:監控、風險檢查、容錯機制是關鍵。
> **延伸閱讀**:
> - *"High‑Frequency Trading: A Practical Guide to Algorithmic Trading Systems"*
> - *"Advances in Financial Machine Learning"* by Marcos López de Prado
> - Backtrader 官方文檔 https://www.backtrader.com/docu/
>
> **練習題**:
> 1. 以 VWAP + 帶有動態滑點的均線交叉策略,完成 5 年日線回測並報告最大回撤。
> 2. 使用 Optuna 找到最佳 RSI 參數組合,並在 walk‑forward 模式下驗證。
>
> 祝你在實盤中順利執行,並持續優化策略!