← Alle Insights

Neural ODEs: Continuous-Time-Modeling für Finanzzeitreihen.

Klassische neuronale Netze denken in diskreten Schritten. Märkte tun das nicht. Trades kommen unregelmäßig, News-Events schlagen zwischen den Bars ein, Order-Books updaten sich mikrosekundenweise. Neural ODEs lernen die Dynamik selbst — eine kontinuierliche Funktion der Zeit. Klingt elegant. Ist auch elegant. Aber nicht überall die richtige Wahl.

Die Grundidee.

Chen et al. (2018, „Neural Ordinary Differential Equations") haben gezeigt: ein ResNet mit unendlich vielen Layern ist äquivalent zu einer ODE. Statt diskrete Schichten zu definieren, lernt man eine Funktion f(h, t), die die Veränderung des verborgenen Zustands h über die Zeit t beschreibt:

dh/dt = f(h, t, θ)

Den Zustand zu jedem beliebigen Zeitpunkt t₁ erhält man durch numerische Integration eines beliebigen ODE-Solvers (Runge-Kutta, Dormand-Prince, etc.) ab einem Initialzustand h(t₀). Trainieren funktioniert über den adjoint method — eine elegante Form von Backprop durch den Solver.

Warum das für Finanzdaten interessant ist.

Die meisten ML-Tools im Trading nehmen eine regelmäßige Abtastrate an: Daily-Bars, 5-Minuten-Bars, etc. Reale Marktdaten sehen anders aus:

Klassische LSTMs erzwingen einheitliche Sample-Abstände. Wer auf 1-Minuten-Bars samplet, verliert Information; wer auf Tick-Ebene samplet, bekommt riesige Sequenzen mit fast leeren Schritten. Neural ODEs haben diese Probleme nicht — der Zustand entwickelt sich kontinuierlich, Beobachtungen kommen rein, wann sie reinkommen.

Latent ODE — die praktische Architektur.

Die in der Praxis am häufigsten verwendete Architektur ist die Latent ODE (Rubanova, Chen, Duvenaud 2019). Aufbau:

  1. Encoder (meist ein RNN, das die beobachteten Zeitpunkte rückwärts liest): liefert den Initialzustand z(t₀) der ODE.
  2. ODE-Solver integriert dz/dt = f(z, t, θ) von t₀ bis zu jedem gewünschten Zeitpunkt tᵢ.
  3. Decoder mappt den latenten Zustand z(tᵢ) auf den Output x(tᵢ) (z. B. Volatilitätsprognose).

Die Architektur kann auf unregelmäßigen Zeitstempeln trainieren und an jedem beliebigen Punkt auswerten — ein technisch sauberer Match zum Tick-Daten-Problem.

Minimal-Implementation mit torchdiffeq.

import torch
import torch.nn as nn
from torchdiffeq import odeint

class ODEFunc(nn.Module):
    def __init__(self, dim=32):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(dim, 64), nn.Tanh(),
            nn.Linear(64, 64), nn.Tanh(),
            nn.Linear(64, dim))

    def forward(self, t, z):
        return self.net(z)

class LatentODE(nn.Module):
    def __init__(self, d_obs=1, d_latent=32):
        super().__init__()
        self.encoder = nn.GRU(d_obs, d_latent, batch_first=True)
        self.odefunc = ODEFunc(d_latent)
        self.decoder = nn.Linear(d_latent, d_obs)

    def forward(self, obs, times_obs, times_out):
        _, h0 = self.encoder(obs.flip(1))   # reverse RNN
        z0 = h0.squeeze(0)
        z_traj = odeint(self.odefunc, z0, times_out, method='dopri5')
        return self.decoder(z_traj)

torchdiffeq liefert die ODE-Solver und den Adjoint-Backprop. Wichtig: method='dopri5' ist adaptiver Runge-Kutta — robust, aber teuer. Für schnelle Experimente reicht 'rk4'.

Konkrete Anwendung: Volatilitäts-Forecast bei unregelmäßigen Updates.

Mein produktivster Use-Case für Neural ODEs: intraday Volatilitätsprognose, in der Updates an unregelmäßigen Punkten reinkommen — Auction-Phasen, News-Events, Earnings-Calls. Die Forecasts müssen zu beliebigen Zeitpunkten verfügbar sein, nicht nur an gesampelten Bar-Grenzen.

Das Latent-ODE-Modell konsumiert Tick-Daten und Event-Marker, hält einen kontinuierlichen latenten Zustand und gibt zu jeder Anfrage einen Volatilitätswert heraus. Klassisches LSTM auf 1-Minuten-Bars liefert vergleichbare Genauigkeit für regelmäßige Zeitpunkte, ist aber blind für Sub-Minuten-Events.

Wo Neural ODEs scheitern.

Drei reale Probleme, die ich in eigenen Experimenten und in der Literatur durchgängig sehe:

Trainings-Instabilität. Die ODE-Funktion lernt mitunter Dynamiken, die der Solver nicht stabil integrieren kann — Steifheit, hohe Lipschitz-Konstanten. Folge: NaN-Loss, divergierende Trajektorien, lange Trainingsläufe ohne Konvergenz. Mitigation: Gradient-Clipping, Weight-Decay, niedrigere Lernrate, Solver-Toleranzen anpassen.

Solver-Wahl ist kritisch. Adaptiver Solver = robust aber langsam. Fester Solver = schnell aber risikobehaftet. In Production bedeutet das: Latenz-Budget für ODE-Inferenz ist eine harte Constraint, die man früh einplanen muss.

Skalierung. Lange Trajektorien sind teuer, weil jeder Solver-Schritt ein NN-Forward-Pass ist. Bei 10.000 Ticks ist das spürbar. Mitigation: Truncated Backprop, Mini-Trajektorien, oder Übergang zu „Latent Continuous-Time RNNs", die ähnliche Eigenschaften zu geringeren Kosten liefern.

Vergleich gegen LSTM und GRU.

In meinen Benchmarks gegen sauber engineerte GRUs sehe ich folgendes Muster:

Meine Praxis.

Neural ODEs nutze ich gezielt dort, wo unregelmäßige Sampling-Intervalle ein strukturelles Problem sind — intraday Tick-Daten, Event-driven Setups, Mixed-Frequency Macro-Daten. Für klassische OHLCV-Bar-Setups bleibe ich bei GRU/LSTM oder Transformer. Der Compute- und Komplexitäts-Overhead von Neural ODEs lohnt sich nur, wenn der Use-Case kontinuierliche Zeit wirklich braucht.

Wer Neural ODEs als „nächste Trading-Revolution" angepriesen bekommt, sollte zwei Fragen stellen: (1) Brauchen wir wirklich Continuous-Time, oder ist das Problem zwischen den Bars gar nicht relevant? (2) Wie sieht die Stabilität des Solvers im Walk-Forward über Regime-Wechsel aus? In den meisten Anwendungen sind die Antworten ernüchternd genug, um zur GRU-Baseline zurückzukehren.

Sie haben einen Use-Case mit unregelmäßigen Tick-Daten oder Event-Streams und überlegen, ob Neural ODEs passen? Erstgespräch buchen — wir bewerten ehrlich.