聊天視窗

金融數據分析實務:從資料到洞見 - 第 4 章

第 4 章 時間序列建模與預測

發布於 2026-03-02 10:33

# 第 4 章 時間序列建模與預測 > 在金融世界裡,時間往往是唯一不斷流動且充滿噪聲的資產。對於投資者與風險管理者而言,如何從歷史價格、利率、匯率等時間序列資料中提取可行的預測信號,既是科學也是藝術。本章將從理論到實務,循序漸進地揭示幾種主流的時間序列建模方法,並結合案例說明其實際應用。 ## 4.1 時間序列特性與預處理 1. **單位根與隨機行走**:使用ADF、KPSS、Phillips–Perron 等檢定確認序列是否平穩。若非平穩,需採用差分、對數變換或加權移動平均等方法。 2. **季節性與週期性**: - **季節性**:使用 `statsmodels.tsa.seasonal_decompose` 或 `STL` 分解,獲得季節成分。 - **週期性**:若存在明顯的金融週期(如美國債券每個季度公布),可利用 Fourier 變換將週期成分嵌入模型。 3. **自相關與偏自相關**:利用 ACF/PACF 圖表判斷 ARMA 模型的階數。 4. **異方差性**:檢測波動率聚集,可使用 ARCH/Ljung-Box 檢定,若顯著則考慮 GARCH 族模型。 5. **外生變數**:將宏觀指標、新聞情緒指數等作為 `exog` 變數引入模型。 > **注意**:任何預處理步驟都必須在訓練集上完成,避免資料洩漏。 ## 4.2 傳統統計模型 | 模型 | 優點 | 缺點 | 適用場景 | |------|------|------|------------| | ARIMA | 理論基礎扎實、易於解釋 | 需要人工挑選階數、假設線性 | 週期性、短期預測 | | SARIMA | 捕捉季節性 | 參數較多 | 具有明顯季節波動的市場 | | GARCH | 模型化波動率 | 參數化困難、估計不穩定 | 風險管理、波動率預測 | | VAR | 多變量共整合 | 需要大量資料 | 互相關聯的金融指標 | ### 4.2.1 ARIMA 範例 python import pandas as pd from statsmodels.tsa.arima.model import ARIMA # 讀取資料 df = pd.read_csv('btc_price.csv', parse_dates=['date'], index_col='date') price = df['close'] # 1. 差分平穩化 price_diff = price.diff().dropna() # 2. 模型擬合 model = ARIMA(price_diff, order=(1,0,1)) fit = model.fit() print(fit.summary()) # 3. 預測 forecast = fit.forecast(steps=30) > **備註**:在實務中,ARIMA 的階數往往由自動化工具(如 `pmdarima.auto_arima`)選擇,以避免主觀偏差。 ## 4.3 統計機器學習模型 | 模型 | 特點 | 適用場景 | |------|------|------------| | XGBoost | 強大的非線性表現、能處理缺失值 | 需要多變量特徵、非平穩序列 | | LightGBM | 大數據下高效、支持分箱 | 大型金融資料集 | | CatBoost | 內建類別特徵處理 | 有離散變數的市場數據 | ### 4.3.1 XGBoost 時間序列預測 python import xgboost as xgb from sklearn.model_selection import TimeSeriesSplit from sklearn.metrics import mean_squared_error import numpy as np # 建立特徵:滯後值、移動平均 lag_features = pd.concat([price.shift(i) for i in range(1, 8)], axis=1) lag_features.columns = [f'lag_{i}' for i in range(1, 8)] lag_features = lag_features.dropna() X = lag_features.values y = price.iloc[lag_features.index].values # 時間序列交叉驗證 tscv = TimeSeriesSplit(n_splits=5) for train_idx, test_idx in tscv.split(X): dtrain = xgb.DMatrix(X[train_idx], label=y[train_idx]) dtest = xgb.DMatrix(X[test_idx], label=y[test_idx]) params = { 'objective': 'reg:squarederror', 'eval_metric': 'rmse', 'max_depth': 6, 'eta': 0.1, } bst = xgb.train(params, dtrain, num_boost_round=500, evals=[(dtest, 'test')], early_stopping_rounds=30) pred = bst.predict(dtest) rmse = mean_squared_error(y[test_idx], pred, squared=False) print(f'RMSE: {rmse:.4f}') > **提醒**:機器學習模型不自帶時間依賴結構,需自行構造滯後特徵,並保證資料不泄漏。 ## 4.4 深度學習模型 | 模型 | 優勢 | 缺點 | |------|------|------| | LSTM | 捕捉長期依賴、可處理序列長度 | 訓練時間長、難以解釋 | | GRU | 訓練更快、參數較少 | 同樣缺乏解釋性 | | Transformer (TimeSeries Transformer) | 利用自注意力捕捉全局關係 | 資料量要求高 | ### 4.4.1 LSTM 範例 python import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout import numpy as np # 資料預處理:將時間窗轉化為三維張量 (samples, timesteps, features) seq_len = 30 X, y = [], [] for i in range(len(price) - seq_len): X.append(price.values[i:i+seq_len]) y.append(price.values[i+seq_len]) X = np.array(X).reshape(-1, seq_len, 1) y = np.array(y) # 分割訓練/驗證 split = int(0.8 * len(X)) X_train, X_val = X[:split], X[split:] y_train, y_val = y[:split], y[split:] model = Sequential([ LSTM(64, return_sequences=True, input_shape=(seq_len,1)), Dropout(0.2), LSTM(32), Dense(1) ]) model.compile(optimizer='adam', loss='mse', metrics=['mae']) model.fit(X_train, y_train, epochs=50, batch_size=32, validation_data=(X_val, y_val)) > **風險**:深度模型的訓練對資料量敏感,且往往需要大量計算資源。若資料不夠多,易發生過擬合。 ## 4.5 模型評估與選擇 1. **指標**:RMSE、MAE、MAPE、SSE、AIC/BIC(統計模型)。 2. **交叉驗證**:使用 `TimeSeriesSplit` 或 rolling forecast。 3. **模型組合**:將不同模型的預測進行加權平均,可顯著提升預測穩定性。 4. **可解釋性**:在金融決策中,模型的可解釋性往往與合規要求直接掛鉤。若需要解釋,選擇 ARIMA 或 GARCH 為首;若追求預測精度,可選擇機器學習/深度模型並配合 SHAP、LIME 等工具。 ## 4.6 實務部署 1. **模型序列化**:使用 `pickle`、`joblib` 或 `ONNX`。對於深度模型,則保存為 `SavedModel` 或 `tf Lite`。 2. **服務化**:利用 FastAPI 或 Flask 將模型包裝為 REST API。示例: python from fastapi import FastAPI import joblib app = FastAPI() model = joblib.load('xgboost_model.pkl') @app.post('/predict') def predict(features: dict): X = pd.DataFrame([features]) pred = model.predict(X) return {'prediction': pred[0]} 3. **監控**:使用 Prometheus 收集預測延遲、CPU/內存占用;配合 Grafana 可視化。若預測結果偏離歷史分佈,可觸發警報。 4. **CI/CD**:使用 GitHub Actions 或 GitLab CI 對模型更新進行自動測試、部署。 ## 4.7 風險管理考量 - **回測與前向測試**:必須在真實市場環境下測試模型的投資策略。避免「過擬合」導致實盤失誤。 - **滑點與交易成本**:在預測收益上加入滑點、手續費的模擬,確保策略的實際可行性。 - **市場流動性**:對於高頻交易模型,需考慮市場深度與流動性限制。 - **合規與透明度**:模型的決策邏輯、風險指標需符合監管要求,尤其在投資銀行與對沖基金等環境。 > **結語**:時間序列模型的選擇並非單一「最佳」答案,而是「適配性」與「風險控制」的平衡。對於不同的投資策略、資產類別與市場環境,必須靈活調整模型參數、特徵構造與評估指標,才能在動盪的金融市場中穩健捕捉機會。