返回目錄
A
金融數據分析實務:從資料到洞見 - 第 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 風險管理考量
- **回測與前向測試**:必須在真實市場環境下測試模型的投資策略。避免「過擬合」導致實盤失誤。
- **滑點與交易成本**:在預測收益上加入滑點、手續費的模擬,確保策略的實際可行性。
- **市場流動性**:對於高頻交易模型,需考慮市場深度與流動性限制。
- **合規與透明度**:模型的決策邏輯、風險指標需符合監管要求,尤其在投資銀行與對沖基金等環境。
> **結語**:時間序列模型的選擇並非單一「最佳」答案,而是「適配性」與「風險控制」的平衡。對於不同的投資策略、資產類別與市場環境,必須靈活調整模型參數、特徵構造與評估指標,才能在動盪的金融市場中穩健捕捉機會。