聊天視窗

數據驅動的投資分析:從基礎到實戰 - 第 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 模式下驗證。 > > 祝你在實盤中順利執行,並持續優化策略!