用於多時間跨度組合預測的時序融合 Transformer
把深度學習應用到組合管理上,最讓人頭疼的就是黑盒問題。你訓練出一個神經網路,它在回測裡跑出了亮眼的夏普比率,但當策略上線後開始虧錢時,你完全不知道為什麼。是哪些輸入特徵驅動了預測?哪些時間跨度才是關鍵?模型反應的是宏觀訊號,還是微觀結構噪聲?
谷歌研究院直接針對這個問題給出了答案——時序融合 Transformer(Temporal Fusion Transformer,TFT),這是一種基於注意力的架構,在提供強勁多時間跨度預測能力的同時,通過注意力權重和變數重要性得分內建了可解釋性。在原始基準測試中,TFT 相比次優模型平均將分位數損失降低了 7%(P50)和 9%(P90),並在各測試資料集上相比最強競爭基線提升了 3% 至 26%。對量化組合經理來說,TFT 提供了一種難得的東西:一個既強大又透明的模型。
本文將拆解 TFT 架構,展示如何把它用於多時間跨度組合預測,藉助 pytorch-forecasting 走一遍 Python 實現,並將其與 LSTM 和原始 Transformer 基線進行對比。
為什麼多時間跨度預測對組合很重要
傳統的單步預測只預測 時刻的一個值。但組合配置決策是同時跨多個時間跨度運作的。組合經理需要知道:
- 1 天跨度:用於日內再平衡和風險管理
- 1 周跨度:用於戰術配置調整
- 1 個月跨度:用於戰略配置和行業輪動
- 1 個季度跨度:用於宏觀驅動的倉位佈局
每個跨度都有不同的訊雜比特性。短期收益由微觀結構和訂單流主導。中期收益對動量和均值迴歸作出反應。長期收益則由基本面和宏觀體制驅動。
一個能同時在所有這些跨度上給出預測的模型——並在每個跨度上給出預測不確定性的分位數估計——從根本上就比為每個跨度單獨建模更有用。這正是 TFT 所提供的:給定一段過去觀測的編碼器視窗,它會輸出一組面向 步之後的分位數預測。
形式化地說,給定一個多元時間序列,其中實體 在時刻 的觀測為 , 是目標, 是隨時間變化的特徵, 是靜態後設資料,TFT 學習的是:
其中 是分位數(從而支援機率性預測), 是回看視窗, 是預測跨度。
TFT 架構:完整堆疊

TFT 不是把一個通用 Transformer 硬套到時間序列上。它是一個專門構建的架構,包含五個專用元件,每個都針對時序預測中的某個具體難題。
1. 門控殘差網路(GRN)
GRN 是 TFT 的基本構件,在架構中凡是需要非線性處理的地方都會用到。與標準前饋層不同,GRN 引入了跳躍連線和門控機制,使網路能夠自適應地控制資訊流。
給定主輸入 和一個可選的上下文向量 ,GRN 計算:
其中:
門控線性單元(GLU)是關鍵的門控機制:
其中 是 sigmoid 函數, 表示逐元素相乘。sigmoid 門會學習抑制輸入的哪些維度,從而在資料不需要時讓模型完全跳過不必要的非線性處理。這對金融資料尤為關鍵,因為某些特徵只在特定體制下才具有資訊量。
2. 變數選擇網路(VSN)
對組合類應用而言,這可以說是最有價值的元件。金融資料集出了名地嘈雜,潛在特徵多達數十個——技術指標、基本面比率、宏觀變數、情緒評分——其中許多在任意給定時刻都是冗餘或無關的。
VSN 計算所有輸入特徵上的軟選擇權重:
其中 是時刻 所有經變換的輸入特徵展平後的向量, 是由靜態後設資料匯出的上下文向量。每個單獨的特徵還會經過它自己的 GRN 處理:
最終被選中的表示是加權和:
在組合語境下, 直接告訴你:"在時刻 ,模型給特徵 賦予了這麼大的權重。"你可能會發現 RSI 在震盪市中佔主導,而宏觀收益率曲線特徵在體制切換時佔主導。這不是事後的解釋——它是被烤進架構裡的。
針對靜態協變數、過去已觀測的輸入以及已知的未來輸入,分別有各自獨立的 VSN。這種分離尊重了預測問題的因果結構:你不能使用未來的觀測,但你可以使用已知的未來事件(財報日期、FOMC 會議、期權到期、星期效應)。
3. 靜態協變數編碼器
在組合預測中,靜態協變數代表不隨時間變化的實體級後設資料:資產類別、行業、交易所、市值分桶或地理區域。TFT 通過專用 GRN 處理這些資料,生成四個不同的上下文向量:
- —— 用於時序變數選擇的上下文
- —— 用於對時序特徵做靜態富集的上下文(在 LSTM 之後應用)
- —— LSTM 的細胞狀態初始化
- —— LSTM 的隱藏狀態初始化
這就是 TFT 處理橫截面資訊的方式。當為一個含 500 只股票的組合做預測時,靜態編碼器讓模型能夠學到科技股和公用事業股具有從根本上不同的時序動態,而無需為它們分別建模。
4. 時序處理:LSTM + 可解釋多頭注意力
TFT 使用一條兩階段的時序處理流程,結合了迴圈架構與基於注意力架構各自的優勢。
階段 1:用 LSTM 做區域性處理
一個序列到序列的 LSTM 編碼器-解碼器處理時間序列,以捕捉區域性時序模式——短期動量、均值迴歸和自迴歸結構。編碼器處理回看視窗;解碼器處理已知的未來輸入。兩者都用靜態上下文向量 (細胞狀態)和 (隱藏狀態)來初始化。
階段 2:用可解釋多頭注意力捕捉長程依賴
在區域性處理之後,TFT 應用一種改良的自注意力機制來學習長程依賴。關鍵的改動在於注意力頭的聚合方式。標準多頭注意力會拼接各頭的輸出:
TFT 則在各頭之間共享值並對注意力權重取平均:
注意: 沒有頭的上標——所有頭共享同一個值投影。這意味著每個頭的注意力權重可以被有意義地平均,並被解釋為時序重要性得分。對於某一次預測,你可以精確地視覺化出模型關注的是哪些過去的時間步,以及不同頭之間的注意力模式有何差異。
對組合預測而言,這能揭示模型究竟是在關注近期價格走勢(動量)、久遠的歷史模式(季節性),還是特定的日曆事件。每個頭都可以專精於一種不同的時序模式。
5. 分位數輸出層
最後一層輸出多個分位數上的預測,用分位數損失進行最佳化:
其中 是目標分位數的集合(例如 )。這不僅給你一個點預測,還在每個跨度上給出預測區間的分位數估計。對組合風險管理而言,第 10 和第 90 百分位的預測可以為倉位規模和止損水平提供依據。
有一點值得開門見山地指出:最小化彈球損失(pinball loss)得到的是條件分位數估計,但它並不保證樣本外覆蓋率經過校準。在非平穩、體制切換的市場上,這些區間常常校準不良——名義上的 80% 區間,實際覆蓋的實現值可能遠少於(或多於)80%。請把這些分位數當作有待用覆蓋率/可靠性檢驗來實證驗證的估計,如果你需要覆蓋率保證,就用保形預測(conformal prediction)來收緊它們。我們會在生產環節那一節再回到這一點。
TFT vs LSTM vs 原始 Transformer

理解 TFT 相對於其他架構所處的位置,有助於決定何時該用它。
| 特性 | LSTM | 原始 Transformer | TFT |
|---|---|---|---|
| 長程依賴 | 有限(梯度消失) | 強(自注意力) | 強(LSTM + 注意力) |
| 變數選擇 | 無(手工特徵工程) | 無 | 內建 VSN |
| 可解釋性 | 不透明 | 注意力權重(含噪) | 結構化注意力 + 變數重要性 |
| 靜態協變數 | 臨時拼接 | 臨時拼接 | 專用編碼流程 |
| 多時間跨度輸出 | 自迴歸(誤差累積) | 直接或自迴歸(取決於解碼方式) | 直接(並行) |
| 已知未來輸入 | 處理彆扭 | 無原生區分 | 顯式輸入分離 |
| 機率性輸出 | 需要改造 | 需要改造 | 原生分位數迴歸 |
| 訓練穩定性 | 中等 | 在小資料上常不穩定 | 穩定(門控有幫助) |
LSTM 仍佔上風的場景
在回看視窗很短、區域性自迴歸結構佔主導的極短期預測(逐筆級、亞分鐘級)中,LSTM 仍然有競爭力。它們部署起來也更簡單,推理延遲更低。對於一個需要亞毫秒級預測的做市機器人來說,LSTM 仍然是務實的選擇。
原始 Transformer 力有不逮的場景
把標準 Transformer 不加改造地套到金融時間序列上,往往會過擬合。它們缺乏時序資料所需的歸納偏置——沒有靜態特徵與時變特徵的概念,沒有變數選擇,而且標準的拼接式多頭注意力產生的注意力圖很難做出有意義的解釋。
TFT 大放異彩的場景
當你具備以下條件時,TFT 是最優選擇:(1)有多種異質的輸入型別,(2)有橫截面資料(許多資產),(3)需要多時間跨度的機率性預測,以及(4)有模型可解釋性的要求。這基本上描述了每一個機構級的組合預測問題。
用 PyTorch Forecasting 做 Python 實現
下面是一個用 pytorch-forecasting 庫為多資產組合收益預測做 TFT 的實戰實現。
資料準備
注意我們有意使用了真正的已知未來輸入——day_of_week、days_to_earnings、is_fomc、days_to_expiry。這些是我們在預測視窗內提前就知道的值,把它們作為已知實數/類別量喂進去,正是這套架構所圍繞構建的那種 TFT 能力。我們從已知實數中剔除了原始的 time_idx:add_relative_time_idx=True 已經注入了一個相對位置索引,而一個原始的單調遞增計數器多半會洩露趨勢。
import pandas as pd
import numpy as np
import lightning.pytorch as pl
from lightning.pytorch.callbacks import EarlyStopping, LearningRateMonitor
from lightning.pytorch.loggers import TensorBoardLogger
from pytorch_forecasting import (
TimeSeriesDataSet,
TemporalFusionTransformer,
QuantileLoss,
GroupNormalizer,
)
max_encoder_length = 60 # 回看 60 个交易日(约 3 个月)
max_prediction_length = 20 # 向前预测 20 个交易日(约 1 个月)
training_cutoff = df["time_idx"].max() - max_prediction_length
training = TimeSeriesDataSet(
df[lambda x: x.time_idx <= training_cutoff],
time_idx="time_idx",
target="log_return",
group_ids=["asset_id"],
min_encoder_length=max_encoder_length // 2,
max_encoder_length=max_encoder_length,
min_prediction_length=1,
max_prediction_length=max_prediction_length,
static_categoricals=["sector", "market_cap_bucket"],
time_varying_known_categoricals=["day_of_week", "is_fomc"],
time_varying_known_reals=["days_to_earnings", "days_to_expiry"],
time_varying_unknown_reals=[
"log_return",
"rsi_14",
"macd",
"bb_width",
"pe_ratio",
"earnings_yield",
"vix",
"yield_spread",
"dxy",
],
target_normalizer=GroupNormalizer(
groups=["asset_id"],
transformation="softplus",
),
add_relative_time_idx=True,
add_target_scales=True,
add_encoder_length=True,
)
validation = TimeSeriesDataSet.from_dataset(
training, df, predict=True, stop_randomization=True
)
batch_size = 64
train_dataloader = training.to_dataloader(
train=True, batch_size=batch_size, num_workers=4
)
val_dataloader = validation.to_dataloader(
train=False, batch_size=batch_size * 4, num_workers=4
)
模型定義與訓練
tft = TemporalFusionTransformer.from_dataset(
training,
learning_rate=1e-3,
hidden_size=64,
attention_head_size=4,
dropout=0.1,
hidden_continuous_size=32,
output_size=7, # 7 个分位数
loss=QuantileLoss(quantiles=[0.02, 0.1, 0.25, 0.5, 0.75, 0.9, 0.98]),
log_interval=10,
optimizer="Ranger",
reduce_on_plateau_patience=4,
)
print(f"Number of parameters: {tft.size() / 1e3:.1f}k")
early_stop_callback = EarlyStopping(
monitor="val_loss",
min_delta=1e-4,
patience=10,
verbose=False,
mode="min",
)
lr_logger = LearningRateMonitor()
logger = TensorBoardLogger("lightning_logs")
trainer = pl.Trainer(
max_epochs=100,
accelerator="auto",
enable_model_summary=True,
gradient_clip_val=0.1,
callbacks=[lr_logger, early_stop_callback],
logger=logger,
)
trainer.fit(
tft,
train_dataloaders=train_dataloader,
val_dataloaders=val_dataloader,
)
提取可解釋輸出
可解釋性呼叫有一個不太顯眼的要求:interpret_output() 消費的是原始輸出字典(帶有 encoder_variables、decoder_variables、static_variables、encoder_attention 等鍵),而 predict() 只有在 mode="raw" 下才會產出它。算一次,然後把同一個物件複用於變數重要性和注意力兩件事。
best_model_path = trainer.checkpoint_callback.best_model_path
best_tft = TemporalFusionTransformer.load_from_checkpoint(best_model_path)
raw_predictions, x = best_tft.predict(val_dataloader, mode="raw", return_x=True)
interpretation = best_tft.interpret_output(raw_predictions, reduction="sum")
best_tft.plot_interpretation(interpretation)
preds = raw_predictions.output["prediction"]
從預測到組合權重
def forecasts_to_portfolio_weights(
predictions: dict,
index: pd.DataFrame,
risk_aversion: float = 2.0,
) -> pd.DataFrame:
"""
用一个均值-方差-启发式(mean-variance-INSPIRED)的得分,把 TFT 的多时间跨度
分位数预测转换为只做多的组合权重(这不是完整优化:这里没有协方差矩阵,
只有一个逐资产的风险调整得分)。
用中位数预测作为期望收益,用 (q90 - q10) 作为预测不确定性的代理。
"""
preds = predictions["prediction"]
median_return = preds[:, :, 3].mean(dim=1).numpy() # 跨各跨度取平均
q90 = preds[:, :, 5].mean(dim=1).numpy()
q10 = preds[:, :, 1].mean(dim=1).numpy()
forecast_uncertainty = q90 - q10 # 80% 预测区间的宽度
scores = median_return / (risk_aversion * forecast_uncertainty + 1e-8)
result = index[["asset_id"]].copy()
result["score"] = scores
result["raw_weight"] = np.maximum(scores, 0) # 只做多
total = result["raw_weight"].sum()
result["weight"] = result["raw_weight"] / (total + 1e-8)
return result[["asset_id", "weight", "score"]]
實踐中的可解釋性:TFT 揭示了市場的什麼

TFT 的可解釋性輸出並不是學術上的獵奇——它們為組合經理提供了可付諸行動的情報。
跨體制的變數重要性
當你觀察變數選擇權重隨時間的變化時,會浮現出一些與市場直覺相符的模式:
- 在 2022 年加息週期中:收益率曲線特徵(yield_spread、fed_funds_rate)主導了變數重要性,佔到選擇權重的 35% 至 40%。技術指標則跌到 10% 以下。
- 在 2024 年由 AI 驅動的上漲中:動量特徵(rsi_14、macd)的重要性飆升。由於這輪上漲高度集中於科技板塊,行業級的靜態協變數也變得顯著。
- 在區間震盪期:均值迴歸指標(bb_width、relative_value)獲得最高權重,而趨勢追蹤特徵則被門控機制壓制。
這就是 GRN 門控在發揮作用。當動量特徵不攜帶任何訊號時,GLU 門會把它們的貢獻推向零,模型便自動轉向其他特徵。(這些是來自探索性實驗的示意性模式,並非經過基準測試的結果——請在你自己的資料上驗證。)
時序注意力模式
注意力權重的視覺化揭示了模型有效的記憶結構:
- 短期注意力峰值:在滯後 1 至 5 處的強注意力反映了自相關以及短期動量/反轉效應。
- 周度模式:在滯後 5、10、15 處的注意力尖峰對應於周度日曆效應。
- 月度模式:在滯後 21(一個交易月)附近一個穩定的注意力峰值,捕捉到了月度再平衡資金流和期權到期效應。
- 財報週期:對單隻股票而言,注意力在約 63 天和 126 天滯後處顯示出尖銳的尖峰,對應於季度財報日期。
這些模式提供了獨立的佐證,表明模型學到的是有意義的時序結構,而不是在擬合噪聲。
真實世界的表現與應用
基準結果
來自原始論文和後續研究,TFT 展現出強勁且有據可查的表現:
- 在論文的基準資料集(電力、交通、零售、波動率)上,相比次優模型,平均 P50 分位數損失降低 7%、P90 分位數損失降低 9%,並視資料集而定,相比最強競爭基線提升 3% 至 26%。具體的競爭對手因資料集而異——例如 DeepAR 在電力和交通上屬於較弱的基線,但在零售和波動率上更具競爭力——所以那個標題性的數字是相對於次優模型的增益,而不是相對於某個固定基線。
- 在多時間跨度指標上始終優於經典的 ARIMA、ETS 和 Prophet 基線。
金融領域的研究方向
TFT 催生了一條活躍的金融專項研究線。這裡列出幾條有代表性的脈絡,並附上它們實際報告的指標(在依賴其中任何一項之前,請引用並復現):
- **面向加密貨幣的自適應/多尺度 TFT。**諸如 Adaptive Temporal Fusion Transformers for Cryptocurrency Price Prediction(arXiv:2509.10542)之類的工作,報告在加密貨幣價格預測上相比固定長度的 TFT 和 LSTM 基線有所改進。請把其中的交易盈利能力數字當作論文特定、依賴體制的結果,而非普適結論——我們在此有意不引用一個絕對的夏普增量,因為文獻裡到處流傳的那些數字常常把預測準確率與已實現夏普混為一談。
- **夏普感知的目標函數。**MDPI Sensors 上那條"多感測器 TFT / 自適應夏普比率"的研究線,直接朝著夏普式的目標進行最佳化;請注意,它那個標題性的結果大致是夏普比率預測準確率提升約 18%,這與絕對夏普的提升是不同的量。
- **混合 TFT-GNN 模型。**將 TFT 與圖神經網路結合以捕捉資產間依賴,據報道這類混合模型在橫截面股票預測上優於單獨的 TFT。
- **跨模態時序融合。**通過 Transformer 融合層將結構化價格資料與非結構化資料(新聞、財報電話會記錄)整合起來,把 TFT 範式擴充到多模態金融資料。
這些方向都是真實存在的,但沒有一個是即插即用的優勢。在部署之前,請在你自己的標的池和成本下復現這些指標。
投產的實務考量
資料要求:TFT 需要大量訓練資料。請計劃每隻資產至少有 2 至 3 年的日度資料,或 6 至 12 個月的小時級資料。橫截面資料(許多資產)幫助很大——同時在 500 只股票上訓練,比訓練 500 個獨立模型更有效。
特徵工程:儘管 TFT 會自動進行變數選擇,候選特徵的質量仍然重要。請納入一組涵蓋技術、基本面、宏觀和另類資料的多樣化特徵集。讓 VSN 去判定什麼有用。
計算成本:TFT 訓練起來比 LSTM 更昂貴,但與原始 Transformer 相當。在單塊 A100 GPU 上,用 3 年日度資料在 500 只股票上訓練 100 個 epoch,量級在幾個小時左右。推理很快——為整個標的池生成預測遠在一秒以內。
**校準要驗證,不要想當然。**在任何分位數被用來驅動倉位規模之前,請在樣本外資料上檢查經驗覆蓋率:名義上的 80% 區間是否真的包含了約 80% 的已實現收益?在非平穩市場上,它常常做不到。請逐跨度繪製可靠性圖,並考慮用保形預測把模型包起來,以恢復覆蓋率保證。
體制適應:TFT 不像 HMM 那樣顯式建模體制切換。然而,門控機制提供了隱式的體制適應。在實踐中,用擴充視窗按月重訓能有效地捕捉結構性變化。
過擬合緩解:金融資料嘈雜且非平穩。請使用激進的正則化:0.1 至 0.3 的 dropout、在 0.1 處做梯度裁剪、以 10 至 15 個 epoch 的耐心做早停。前向滾動(walk-forward)驗證必不可少——絕不要在時間序列上使用隨機的訓練/測試劃分。
把這一切串起來:一條基於 TFT 的組合流程

一條用於基於 TFT 的組合管理的生產流程長這樣:
- 資料接入:每日採集 OHLCV、基本面、宏觀和另類資料。計算特徵(200 多個候選),包括一份真正的已知未來日曆(財報、FOMC、到期、星期)。
- 特徵庫:維護一個歸一化、按時間索引的特徵庫。處理缺失資料、公司行為(corporate actions)和倖存者偏差。
- 模型訓練:用前向滾動方法按月重訓 TFT。以擴充視窗使用最近 3 至 5 年的資料。
- 預測生成:每日推理,為整個資產池在 1、5、10、20 天跨度上生成分位數預測。
- 校準檢查:逐跨度追蹤每個分位數區間的覆蓋率。當覆蓋率漂移時,重新校準(或應用保形調整)。
- 可解釋性看板:視覺化變數重要性和注意力權重。標記異常(例如特徵重要性的突然變化)。
- 組合最佳化:用均值-方差、Black-Litterman 或風險平價把預測轉換為權重,其中 TFT 分位數提供收益與不確定性輸入。
- 風險疊加層:用第 2 和第 98 百分位的預測做尾部風險評估。當預測區間變寬時,縮小倉位規模。
- 執行:把目標權重傳給執行引擎。監控目標組合與已實現組合之間的追蹤誤差。
結論
時序融合 Transformer 代表了量化組合管理的一次真正進步。它不只是又一個被隨意扔向金融資料的深度學習模型——它是一個從頭開始、針對多時間跨度時序預測的具體挑戰而設計的架構:異質輸入、橫截面結構、機率性輸出,以及對可解釋性的關鍵需求。
變數選擇網路告訴你模型在關注什麼。注意力權重告訴你它在何時觀察。門控機制確保它優雅地處理無關特徵和體制變化。而分位數輸出為風險管理提供了不確定性估計——前提是你去驗證它們的校準,而不是憑信仰接受。
TFT 不是萬靈藥。金融市場依然是對抗性環境,任何預測優勢都是暫時的、依賴體制的。但 TFT 提供了一個有原則的框架,用以構建既強大又可理解的預測系統——而在生產交易中,理解你的模型為什麼下這個注,與下注本身同樣重要。
參考文獻
- Lim, B., Arik, S.O., Loeff, N., & Pfister, T. (2021). "Temporal Fusion Transformers for Interpretable Multi-horizon Time Series Forecasting." International Journal of Forecasting, 37(4), 1748-1764. arXiv:1912.09363
- Oreshkin, B.N., Carpov, D., Chapados, N., & Bengio, Y. (2020). "N-BEATS: Neural basis expansion analysis for interpretable time series forecasting." ICLR 2020.
- Salinas, D., Flunkert, V., Gasthaus, J., & Januschowski, T. (2020). "DeepAR: Probabilistic forecasting with autoregressive recurrent networks." International Journal of Forecasting, 36(3), 1181-1191.
- pytorch-forecasting documentation —— 基於 PyTorch Lightning 的 TFT 實現。
- google-research/tft —— 原始 TFT 參考實現。
Authors
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.