Transformer für Zeitreihen im Trading.
Seit Transformer die Sprachmodelle dominieren, ziehen sie auch in Zeitreihen-Analysen ein. Im Trading sind die Hoffnungen groß — und die Stolperfallen zahlreich. Wer einfach einen NLP-Transformer auf OHLC-Bars wirft, wird enttäuscht. Wer die Architektur an die Eigenheiten finanzieller Daten anpasst, bekommt ein mächtiges Werkzeug.
Warum Transformer für Zeitreihen interessant sind.
Self-Attention erlaubt jedem Zeitschritt, jeden anderen direkt zu betrachten. Für ein LSTM wandert Information sequenziell durch versteckte Zustände, lange Abhängigkeiten verblassen. Ein Transformer kann unmittelbar auf einen Volatilitäts- Spike vor sechzig Bars zugreifen, ohne dass die Information durch sechzig Zellen propagieren muss.
Zweiter Vorteil: Parallelisierbarkeit. Während ein LSTM Schritt für Schritt arbeitet, kann ein Transformer ein gesamtes Fenster in einem Pass verarbeiten. Auf modernen GPUs trainiert er deutlich schneller als ein vergleichbar großes RNN.
Was bei Finanzdaten anders ist.
NLP-Transformer haben es mit diskreten Tokens, klaren Vokabularen und stark strukturierter Grammatik zu tun. Finanzdaten sind kontinuierlich, verrauscht, nicht-stationär und in der Regel sehr niedriger Signal-Anteil. Daraus folgen drei Anpassungen:
- Patch-Embeddings statt Token-Embeddings: Sequenzen werden in kleine Fenster zerschnitten und linear projiziert.
- Lernbare positionale Encodings statt fester Sinus-Encodings — die Periodizität ist nicht universal.
- Starke Regularisierung: Dropout, Stochastic-Depth, Label-Smoothing oder Sharpe-orientierte Verlustfunktionen.
Minimaler Transformer-Encoder in PyTorch.
import math
import torch
import torch.nn as nn
class TimeSeriesTransformer(nn.Module):
def __init__(self, n_features, d_model=64, nhead=4,
num_layers=3, seq_len=64, dropout=0.2):
super().__init__()
self.input_proj = nn.Linear(n_features, d_model)
self.pos_emb = nn.Parameter(torch.zeros(1, seq_len, d_model))
encoder_layer = nn.TransformerEncoderLayer(
d_model=d_model,
nhead=nhead,
dim_feedforward=4 * d_model,
dropout=dropout,
batch_first=True,
activation="gelu",
)
self.encoder = nn.TransformerEncoder(encoder_layer, num_layers=num_layers)
self.norm = nn.LayerNorm(d_model)
self.head = nn.Linear(d_model, 1)
def forward(self, x):
h = self.input_proj(x) + self.pos_emb[:, : x.size(1)]
h = self.encoder(h)
h = self.norm(h[:, -1, :])
return self.head(h).squeeze(-1)
Die Aufmerksamkeit ist hier kausal nicht maskiert — bei reiner Encoder-Nutzung mit einem Vorhersage-Kopf am letzten Token reicht das. Wenn Sie autoregressiv mehrere Schritte vorhersagen wollen, brauchen Sie eine kausale Maske.
Patch-basierte Eingaben.
PatchTST und ähnliche Architekturen haben gezeigt, dass das Aufteilen einer langen Zeitreihe in nicht überlappende Patches die Effizienz drastisch erhöht. Ein Fenster von 512 Bars wird in 32 Patches à 16 Bars zerlegt, jeder Patch wird linear in einen Embedding-Vektor projiziert. Die Sequenzlänge des Transformers wird damit von 512 auf 32 reduziert — quadratisch geringerer Aufwand für Self-Attention.
class PatchEmbedding(nn.Module):
def __init__(self, n_features, patch_len=16, stride=16, d_model=64):
super().__init__()
self.patch_len = patch_len
self.stride = stride
self.proj = nn.Linear(patch_len * n_features, d_model)
def forward(self, x):
# x: [batch, seq_len, n_features]
b, t, f = x.shape
# in Patches schneiden
patches = x.unfold(1, self.patch_len, self.stride)
# [b, n_patches, n_features, patch_len] -> flatten
patches = patches.permute(0, 1, 3, 2).contiguous()
patches = patches.view(b, patches.size(1), -1)
return self.proj(patches)
Channel-Independence vs. Multivariate-Attention.
Ein nicht-triviales Designentscheidung: Sollen alle Features eines Bars gemeinsam in ein Token projiziert werden, oder jedes Feature als eigene Sequenz behandelt werden? Die zweite Variante (Channel-Independence, wie in PatchTST) funktioniert in der Praxis erstaunlich gut, weil sie das Modell zwingt, pro Feature universelle Muster zu lernen, statt sich auf zufällige Korrelationen zwischen Features zu stützen.
Training und Regularisierung.
Transformer sind hungrige Modelle. Mit nur 5 000 Trainingsbeispielen werden sie overfittern. Empfohlene Maßnahmen:
- Multi-Asset-Training: ein Modell für 50 Aktien gleichzeitig statt eins pro Aktie.
- Augmentations: zufälliges Maskieren von Zeitschritten, leichtes Hinzufügen von Rauschen.
- Warmup und Cosine-Decay für die Lernrate.
- Early-Stopping auf einer separaten Walk-Forward-Validierung.
Wann sich der Transformer lohnt — und wann nicht.
Für reine OHLC-Daten auf Tagesbasis ist der Transformer oft Overkill. Ein gut getuntes Gradient-Boosting-Modell auf handgeprägten Features schlägt einen untrainierten Transformer locker. Wo Transformer wirklich glänzen:
- Sehr lange Sequenzen mit relevanter Langzeit-Abhängigkeit (Intraday-Patterns über mehrere Tage).
- Multi-Asset-Modelle mit Cross-Sectional-Attention.
- Multi-Modal-Setups: Preisdaten kombiniert mit News-Embeddings oder Order-Book-Features.
- Few-Shot-Adaption: vortrainierte Foundation-Modelle auf neue Märkte feinjustieren.
Sie wollen prüfen, ob Transformer Ihrem Modell-Stack einen echten Vorteil bringen? Erstgespräch buchen — wir bewerten ehrlich, ob die Komplexität gerechtfertigt ist und wie ein produktiver Aufbau aussieht.