基于Transformer的多資產收益預測模型實戰(附PyTorch模型訓練及可視化完整代碼)
一、項目背景與目標
在量化投資領域,利用時間序列數據預測資產收益是核心任務之一。傳統方法如LSTM難以捕捉資產間的復雜依賴關系,而Transformer架構通過自注意力機制能有效建模多資產間的聯動效應。
本文將從零開始構建一個基于PyTorch的多資產收益預測模型,涵蓋數據生成、特征工程、模型設計、訓練及可視化全流程,適合深度學習與量化投資的初學者入門。
二、核心技術棧
- 數據處理:Pandas/Numpy(數據生成與預處理)
- 深度學習框架:PyTorch(模型構建與訓練)
- 可視化:Matplotlib(結果分析)
- 核心算法:Transformer(自注意力機制)
三、數據生成與預處理
1. 模擬金融數據生成
我們通過以下步驟生成包含5只資產的時間序列數據:
- 市場基準因子:模擬市場整體趨勢(幾何布朗運動)
- 行業因子:引入周期性波動區分不同行業(如科技、消費、能源)
- 特質因子:每只資產的獨立噪聲
def generate_market_data(days=2000, n_assets=5): np.random.seed(42) market = np.cumprod(1 + np.random.normal(0.0003, 0.015, days)) # 市場基準 assets = [] sector_map = {0: "Tech", 1: "Tech", 2: "Consume", 3: "Consume", 4: "Energy"} for i in range(n_assets): sector_factor = 0.3 * np.sin(i * 0.8 + np.linspace(0, 10 * np.pi, days)) # 行業周期因子 idiosyncratic = np.cumprod(1 + np.random.normal(0.0002, 0.02, days)) # 特質因子 price = market * (1 + sector_factor) * idiosyncratic # 價格合成 assets.append(price) dates = pd.date_range("2015-01-01", periods=days) return pd.DataFrame(np.array(assets).T, index=dates, columns=[f"Asset_{i}" for i in range(n_assets)])
2. 數據形狀說明
生成的DataFrame形狀為[2000天, 5資產]
,索引為時間戳,列名為Asset_0到Asset_4。
四、特征工程:從價格到可訓練數據
1. 基礎時間序列特征
為每只資產計算以下特征:
- 收益率(Return):相鄰日價格變化率
- 波動率(Volatility):20日滾動標準差年化
- 移動平均(MA10):10日價格移動平均
- 行業相對強弱(Sector_RS):資產價格與所屬行業平均價格的比值
def create_features(data, lookback=60): n_assets = data.shape[1] sector_map = {0: "Tech", 1: "Tech", 2: "Consume", 3: "Consume", 4: "Energy"} features = [] for i, asset in enumerate(data.columns): df = pd.DataFrame() df["Return"] = data[asset].pct_change() df["Volatility"] = df["Return"].rolling(20).std() * np.sqrt(252) # 年化波動率 df["MA10"] = data[asset].rolling(10).mean() # 計算行業相對強弱 sector = sector_map[i] sector_cols = [col for col in data.columns if sector_map[int(col.split("_")[1])] == sector] df["Sector_RS"] = data[asset] / data[sector_cols].mean(axis=1) features.append(df.dropna()) # 去除NaN # 對齊時間索引 common_idx = features[0].index for df in features[1:]: common_idx = common_idx.intersection(df.index) features = [df.loc[common_idx] for df in features] # 構建3D特征張量 [樣本數, 時間步, 資產數, 特征數] X = np.stack([np.stack([feat.iloc[i-lookback:i] for i in range(lookback, len(feat))], axis=0) for feat in features], axis=2) # 標簽:未來5日平均收益率 y = np.array([data.loc[common_idx].iloc[i:i+5].pct_change().mean().values for i in range(lookback, len(common_idx))]) return X, y
2. 輸入輸出形狀
- 特征張量
X
形狀:[樣本數, 時間步(60), 資產數(5), 特征數(4)]
- 標簽
y
形狀:[樣本數, 資產數(5)]
(每個樣本對應5只資產的未來5日平均收益率)
五、Transformer模型構建:核心架構解析
1. 模型設計目標
- 處理多資產時間序列:同時輸入5只資產的歷史數據
- 捕捉時間依賴與資產間依賴:通過位置編碼和自注意力機制
- 輸出多資產收益預測:回歸問題,使用MSE損失
2. 關鍵組件解析
(1)資產嵌入層(Asset Embedding)
將每個資產的4維特征映射到64維隱空間:
self.asset_embed = nn.Linear(n_features=4, d_model=64)
輸入形狀:(batch, seq_len, assets, features)
→ 輸出:(batch, seq_len, assets, d_model)
(2)位置編碼(Positional Embedding)
由于Transformer無內置時序信息,需手動添加位置編碼:
self.time_pos = nn.Parameter(torch.randn(1, lookback=60, 1, d_model=64)) # 時間位置編碼
self.asset_pos = nn.Parameter(torch.randn(1, 1, n_assets=5, d_model=64)) # 資產位置編碼
- 通過廣播機制與資產嵌入相加,分別捕獲時間和資產維度的位置信息。
(3)自定義Transformer編碼器層(Custom Transformer Encoder Layer)
繼承PyTorch原生層,返回注意力權重以可視化:
class CustomTransformerEncoderLayer(nn.TransformerEncoderLayer): def __init__(self, d_model, nhead, dim_feedforward=256, dropout=0.1): super(