← Retour aux articles
August 16, 2026
5 min de lecture

Neural ODEs: Does Continuous Time Beat a Delta-Time Feature?

Neural ODEs: Does Continuous Time Beat a Delta-Time Feature?
#deep-learning
#neural-ODE
#continuous-time
#SDE
#dynamics

Les équations différentielles ordinaires neuronales (Chen et al., NeurIPS 2018) paramétrent la dérivée d'un état caché avec un réseau neuronal et laissent un solveur ODE calculer la sortie. Le modèle devient en profondeur continue et, plus utile pour les marchés, en temps continu : l'état caché peut être évalué à tout moment. tt, pas seulement aux points de grille sur lesquels vos données se trouvent.

Cette propriété a un pitch évident pour les données financières, qui arrivent à intervalles aléatoires. Mais le discours cache une affirmation beaucoup plus faible qu’elle ne semble le faire. Un simple GRU a fourni une fonctionnalité d'entrée supplémentaire - log(Δt)\log(\Delta t) depuis l'observation précédente — « sait » également combien de temps s'est écoulé. La vraie question n’est pas de savoir si les modèles en temps continu peuvent ingérer des données irrégulières. Il s'agit de savoir si la dynamique continue apprise entre les observations extrait quelque chose qu'une fonctionnalité delta-temps ne vous donne pas déjà, pour un coût dix à cent fois supérieur à celui de l'inférence.

Cet article met en place cette expérience, donne la chaîne d'outils complète pour l'exécuter et rapporte ce que la comparaison devrait montrer pour justifier la machinerie. Le côté construction des barres de l’argument – ​​selon lequel le timing des échanges lui-même est porteur d’un signal – est établi avec des preuves mesurées sur 17 types de barres dans au-delà des barres temporelles ; ici la seule conséquence qui compte est une conséquence de modélisation : le solveur évalue l'état caché à un niveau arbitraire. tt, donc aucune interpolation ou remplissage n’est nécessaire.

La revendication en cours de test

Trois hypothèses imbriquées pour la modélisation du marché en temps continu

Trois hypothèses imbriquées, chacune strictement plus forte que la précédente :

  1. H1 — Un ajustement ODE-RNN sur un flux commercial BTC irrégulier brut bat un ajustement GRU sur le même flux sans aucune information temporelle. C’est presque certain et presque sans valeur : l’ODE-RNN contient simplement des informations qui manquent à la ligne de base.
  2. H2 — L'ODE-RNN bat le même GRU une fois le GRU donné log(Δt)\log(\Delta t) comme fonctionnalité d’entrée. C'est le test honnête. C’est l’affirmation que la littérature sur l’ODE neuronale est généralement interprétée comme faisant, et c’est celle qui n’est presque jamais démontrée dans les données financières.
  3. H3 — L'avantage H2 survit au budget de latence, c'est-à-dire qu'il est conservé lorsque l'ODE-RNN est déployé avec un solveur à pas fixe suffisamment rapide pour une inférence en direct plutôt qu'adaptative. dopri5.

Protocole d'expérimentation

Même flux de ticks, même cible, même budget de réglage pour les deux bras. Pas de rééchantillonnage à des barres de 1 m : le rééchantillonnage détruit la structure exacte testée.

Paramètre
Données Impressions commerciales BTC, délais variables entre les arrivées, non rééchantillonnés
Armes ODE-RNN ; GRU + log(Δt)\log(\Delta t); GRU sans fonction horaire
Cible Pareil pour toutes les armes ; spécifié avec l'ajustement
Métriques RMSE, log-vraisemblance maintenue, horloge murale par époque, latence d'inférence par étape
Balayage du solveur dopri5 (rtol 1e-5) vs Euler à pas fixe, comparés sur la précision de l'entraînement
Divisé Avancement, hors échantillon uniquement
Bras RMSE Log-lik s/époque Latence/étape d'inférence
GRU (pas de fonction horaire)
GRU + journal(dt)
ODE-RNN (dopri5)
ODE-RNN (Euler à pas fixe)

Un résultat négatif sur H2 est entièrement publiable et sans doute le résultat le plus précieux – la même norme appliquée dans le résultat négatif honnête et Sharpe dégonflé sous plusieurs tests.

Expérience secondaire : CNF vs Student-t

Si la comparaison ODE-RNN est trop coûteuse, l'ancre empirique la moins chère est distributionnelle : ajustez un flux de normalisation continu sur les rendements quotidiens réels du BTC et comparez sa densité ajustée à un ajustement Student-t et à la queue empirique, en signalant les erreurs de quantile de queue aux niveaux de 1 % et 5 %. Cela est directement lié au travail de distribution déjà mesuré dans GARCH volatilité prévision et assymétrique GARCH.


Le reste de cet article présente le contexte et la chaîne d'outils nécessaires pour exécuter ce qui précède.

Contexte : des ResNets à la dynamique continue

Le réseau résiduel devient un champ dynamique continu

Un réseau résiduel calcule ht+1=ht+f(ht,θt)h_{t+1} = h_t + f(h_t, \theta_t). Réduisez la taille du pas et augmentez le nombre de couches et vous approchez d'une limite continue :

dh(t)dt=f(h(t),t,θ)\frac{dh(t)}{dt} = f(h(t), t, \theta)

Au lieu de TT couches discrètes avec paramètres séparés, un seul réseau ff spécifie le taux de changement instantané. La sortie à l'heure TT résout un problème de valeur initiale :

h(T)=h(0)+0Tf(h(t),t,θ)dth(T) = h(0) + \int_0^T f(h(t), t, \theta) \, dt

Un solveur boîte noire (Euler, Runge-Kutta, Dormand-Prince) calcule l'intégrale numériquement, en choisissant de manière adaptative les tailles de pas à partir des estimations d'erreur locales.

La méthode adjointe

La rétropropagation à chaque étape du solveur stocke tous les états intermédiaires, ce qui coûte de la mémoire proportionnelle au nombre d'étapes. Chen et coll. à la place, résolvez une ODE en arrière avec O(1)O(1) mémoire. Définir l'état adjoint a(t)=L/h(t)a(t) = -\partial L / \partial h(t), ce qui satisfait

da(t)dt=a(t)Tf(h(t),t,θ)h\frac{da(t)}{dt} = -a(t)^T \frac{\partial f(h(t), t, \theta)}{\partial h}

et accumulez le gradient de paramètre le long du passage arrière :

dLdθ=T0a(t)Tf(h(t),t,θ)θdt\frac{dL}{d\theta} = -\int_T^0 a(t)^T \frac{\partial f(h(t), t, \theta)}{\partial \theta} \, dt

La passe arrière résout un système informatique augmenté h(t)h(t), a(t)a(t) et dL/dθdL/d\theta simultanément, en exécutant le solveur à l'envers de TT à 00.

Le compromis : reconstruire h(t)h(t) en arrière, l'erreur numérique s'accumule, ce qui est grave pour les dynamiques rigides ou chaotiques. Les points de contrôle sont le juste milieu — magasin h(t)h(t) à quelques instants intermédiaires, recalculez entre eux. Les processus de prix sont des semi-martingales continues et modérément fluides, de sorte que l'adjoint tient généralement le coup ; la rigidité autour des événements de microstructure peut forcer des solveurs adaptatifs ou hybrides.

ODE-RNN : État caché continu entre les observations

État caché évoluant en douceur entre des observations irrégulières

L'ODE-RNN est l'architecture sur laquelle repose l'expérience principale. Entre les observations l'état caché évolue sous l'ODE :

h(t)=ODESolve(fθ,h(ti),ti,t)h(t) = \text{ODESolve}(f_\theta, h(t_i), t_i, t)

Lorsque l'observation xi+1x_{i+1} arrive à ti+1t_{i+1}, une mise à jour discrète se déclenche :

h(ti+1+)=RNNCell(h(ti+1),xi+1)h(t_{i+1}^+) = \text{RNNCell}(h(t_{i+1}^-), x_{i+1})

Les exposants désignent l'état juste avant et juste après l'observation. Entre les observations, apprentissage de la dynamique continue ; aux observations, de nouvelles informations.

Le mécanisme étudié par l’ablation H2 est le suivant : un long écart signifie que l’état caché a évolué depuis longtemps. fθf_\theta - en déclin vers une ligne de base, ou en divergeant - et la forme de cette évolution est appris plutôt que fournie sous forme de scalaire. Il n’est pas possible de mesurer si cette expressivité s’avère rentable sur la base de données commerciales réelles.

Des ajustements naturels au-delà des ticks : des portefeuilles multi-actifs où chaque actif a son propre calendrier d'observation et l'état latent des actifs corrélés continue d'évoluer alors qu'un seul est observé ; et des signaux événementiels (actualités, bénéfices, publications macro) arrivant à des moments irréguliers.

SDE neuronaux : ajout de composants stochastiques

Dynamique continue avec diffusion stochastique contrôlée

Les ODE neuronales sont déterministes et ne peuvent pas représenter le bruit dans une trajectoire de prix. Le traitement classique – mouvement brownien géométrique, dérive sans risque et façons dont les hypothèses de volatilité constante échouent face au sourire – est abordé dans [Tarif des options Black-Scholes] (/en/blog/post/black-scholes-options-pricing). Les SDE neuronaux remplacent la forme paramétrique par un terme de diffusion appris :

dh(t)=f(h(t),t,θ)dt+g(h(t),t,ϕ)dW(t)dh(t) = f(h(t), t, \theta) \, dt + g(h(t), t, \phi) \, dW(t)

ff c'est la dérive, gg la diffusion, W(t)W(t) un processus Wiener, à la fois ff et gg réseaux de neurones.

Architecture : filet dérivant et filet de diffusion

  • Filet dérivant fθf_\theta: trajectoire attendue – tendance, retour à la moyenne, élan. Formé pour minimiser les erreurs de prédiction.
  • Filet de diffusion gϕg_\phi: ampleur du bruit, apprise en fonction de l'état. Élevé dans les régimes volatils, faible dans les régimes calmes.

Cette division reflète la finance quantique classique : la dérive est la dynamique sans risque (ou mesure P), la diffusion est la surface de volatilité.

Formation des SDE neuronaux

L'intégrale stochastique gdW\int g\,dW n’est pas classiquement différentiable. Trois approches :

  1. Gradients par chemin : astuce de reparamétrage - échantillonnez des chemins browniens, différenciez-les via le solveur traitant le bruit comme une entrée fixe.
  2. Correspondance des scores : estimation hlogp(h)\nabla_h \log p(h) et s'entraîner via des objectifs de débruitage - le même mécanisme utilisé comme modèle génératif autonome dans modèles de diffusion pour la prédiction cryptographique, ici rétrogradé à une option de formation pour le SDE.
  3. Correspondance de distribution de dimension finie : faites correspondre les marginales aux moments d'observation plutôt que les mesures de chemin complet.

Pathwise est la valeur par défaut pratique. torchsde implémente Euler-Maruyama, Milstein et Runge-Kutta stochastique avec prise en charge de la comparaison automatique.

Apprendre la surface de volatilité

Les modèles classiques (Heston, SABR) imposent des formes paramétriques au coefficient de diffusion. Un SDE neuronal apprend gϕ(S,t)g_\phi(S, t) comme fonction arbitraire :

dS(t)=μθ(S(t),t)dt+σϕ(S(t),t)S(t)dW(t)dS(t) = \mu_\theta(S(t), t) \, dt + \sigma_\phi(S(t), t) \, S(t) \, dW(t)

Il s’agit d’un approximateur universel pour les processus de diffusion – tout processus Ito avec une précision arbitraire étant donné une capacité suffisante.

ODE latentes pour les données manquantes et asynchrones

État continu latent reconstruisant les données asynchrones manquantes

L'ODE latente (Rubanova, Chen, Duvenaud, 2019) associe une ODE neuronale à une VAE : les séries financières sont des observations bruitées d'un processus sous-jacent fluide, appris dans un espace latent de basse dimension.

  1. Réseau de reconnaissance : un ODE-RNN parcourant les observations à rebours pour produire q(z0x1:N)q(z_0 | x_{1:N}).
  2. Dynamique latente : z(t)=z(t0)+t0tfθ(z(s),s)dsz(t) = z(t_0) + \int_{t_0}^{t} f_\theta(z(s), s)\, ds.
  3. Décodeur : x^(t)=Decoder(z(t))\hat{x}(t) = \text{Decoder}(z(t)), évaluable à tout moment demandé.

La perte est l'ELBO standard :

L=Eq(z0)[i=1Nlogp(xiz(ti))]KL(q(z0x1:N)p(z0))\mathcal{L} = \mathbb{E}_{q(z_0)} \left[ \sum_{i=1}^{N} \log p(x_i | z(t_i)) \right] - \text{KL}(q(z_0 | x_{1:N}) \| p(z_0))

Estimation de l'état du portefeuille : à partir d'observations asynchrones éparses sur l'ensemble des actifs, déduisez un état latent continu capturant la dynamique conjointe - essentiellement une version non linéaire et apprise du filtre de Kalman.

Imputation des données manquantes : les arrêts et les écarts de week-end obtiennent une trajectoire latente interpolée en douceur ; le décodeur produit des chemins plausibles à travers l'écart avec l'incertitude du VAE postérieur.

Fusion multifréquence : clôtures quotidiennes, données VWAP intrajournalières et ticks dans un seul modèle sans grille horaire partagée.

Flux de normalisation continus pour les distributions de retour

Flux continu façonnant une distribution de rendement à queue lourde

Les CNF utilisent une ODE neuronale pour transformer une distribution de base simple en une cible complexe. La transformation est dz(t)dt=f(z(t),t,θ)\frac{dz(t)}{dt} = f(z(t), t, \theta), et la densité log suit le changement instantané des variables :

logp(z(t))t=tr(fz(t))\frac{\partial \log p(z(t))}{\partial t} = -\text{tr}\left(\frac{\partial f}{\partial z(t)}\right)

Intégrer l'état et la densité de journalisation à partir de z(0)p0z(0) \sim p_0 obtenir z(T)z(T) et logp(z(T))\log p(z(T)). La trace jacobienne est estimée avec l'estimateur stochastique de Hutchinson pour l'évolutivité.

Les rendements de la cryptographie sont leptokurtiques et asymétriques – mesurés sur des données réelles dans Prévision de la volatilité GARCH et GARCH asymétrique et effet de levier – et un CNF apprend cette forme au lieu de l'assumer. Conditionner le flux sur des variables d'état permet à la forme de changer avec le régime. Parce que la densité est exacte plutôt qu'approximative, elle peut alimenter les métriques de queue calculées dans les backtests de Monte Carlo et d'amorçage et la construction CVaR dans le pipeline de portefeuille HRP/CVaR ; la structure de la queue commune est traitée séparément dans modèles de copule pour le risque commun.

Estimation conditionnelle de la densité

Le cadrage utile est un contraste direct entre trois approches publiées du même problème. TFT vous donne un ensemble fixe de quantiles à partir d'une couche de sortie quantile. Prédiction conforme vous donne des intervalles calibrés avec une garantie de couverture. Un CNF conditionnel vous donne une densité exacte et différentiable :

dz(t)dt=f(z(t),t,featurest,θ)\frac{dz(t)}{dt} = f(z(t), t, \text{features}_t, \theta)

La différentiabilité est la propriété distinctive : la densité peut se situer à l'intérieur d'un objectif en aval et être rétropropagée à travers, ce que ni les quantiles fixes ni les intervalles conformes ne prennent en charge. La question de savoir si la densité exacte vaut son coût par rapport aux quantiles TFT sur la même cible n'est pas testée ici.

Comparaison avec des alternatives discrètes

Modèles discrets et continus comparés sur des observations partagées

Propriété LSTM/GRU Transformateur ODE neuronale SDE neuronal
Gestion du temps irrégulière Médiocre (nécessite un rembourrage) Codage positionnel Natif Natif
Mémoire (entraînement) O(T)O(T) O(T2)O(T^2) O(1)O(1) adjoint O(1)O(1) adjoint
Quantification de l'incertitude Non (déterministe) Non (déterministe) Via-ensembles Natif
Interpolation entre observations Non Non Oui Oui
Densité en temps continu Non Non Via le CNF Via mesure de chemin
Coût de calcul Faible Modéré Variable (solveur) Élevé (solveur SDE)

La moitié LSTM contre attention de ce tableau est argumentée en détail, avec des références, dans l'article TFT — voir ses sections « TFT vs LSTM vs Vanilla Transformer » et « Quand LSTM gagne toujours ». Les colonnes qui sont nouvelles ici sont les deux de droite, et les lignes qui décident des questions H2/H3 sont les deux dernières.

Implémentation Python avec torchdiffeq

Solveur d'équation différentielle neuronale comme orbite de calcul précise

torchdiffeq fournit des solveurs ODE avec rétropropagation adjointe.

ODE neuronale de base pour la dynamique des prix

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

class PriceDynamics(nn.Module):
    """Neural network defining dh/dt = f(h, t)."""

    def __init__(self, hidden_dim: int = 64):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(hidden_dim, 128),
            nn.Tanh(),
            nn.Linear(128, 128),
            nn.Tanh(),
            nn.Linear(128, hidden_dim),
        )

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


class NeuralODEPredictor(nn.Module):
    """
    Encode observed features -> latent state,
    evolve via Neural ODE,
    decode to price prediction.
    """

    def __init__(self, input_dim: int, hidden_dim: int = 64):
        super().__init__()
        self.encoder = nn.Linear(input_dim, hidden_dim)
        self.dynamics = PriceDynamics(hidden_dim)
        self.decoder = nn.Linear(hidden_dim, 1)

    def forward(self, x0, eval_times):
        """
        x0:         (batch, input_dim) features at t=0
        eval_times: (T,) times at which to evaluate the ODE
        Returns:    (T, batch, 1) predictions
        """
        h0 = self.encoder(x0)                          # (batch, hidden_dim)
        h_traj = odeint(self.dynamics, h0, eval_times,
                        method='dopri5', rtol=1e-5, atol=1e-7)
        return self.decoder(h_traj)

ODE-RNN pour les données de ticks irrégulières

C'est le bras expérimental. La ligne de base qu'il doit battre est nn.GRUCell sur le même flux avec log(t_next - t_prev) concaténé à x.

class ODERNNCell(nn.Module):
    """Single step: ODE-evolve, then RNN-update."""

    def __init__(self, input_dim: int, hidden_dim: int = 64):
        super().__init__()
        self.dynamics = PriceDynamics(hidden_dim)
        self.gru_cell = nn.GRUCell(input_dim, hidden_dim)

    def forward(self, h, x, t_prev, t_next):
        times = torch.tensor([t_prev, t_next], dtype=torch.float32)
        h_evolved = odeint(self.dynamics, h, times,
                           method='dopri5')[-1]  # state at t_next
        h_updated = self.gru_cell(x, h_evolved)
        return h_updated


class ODERNN(nn.Module):
    """Process irregularly-sampled sequence."""

    def __init__(self, input_dim: int, hidden_dim: int = 64):
        super().__init__()
        self.cell = ODERNNCell(input_dim, hidden_dim)
        self.decoder = nn.Linear(hidden_dim, 1)
        self.hidden_dim = hidden_dim

    def forward(self, observations, times):
        """
        observations: list of (batch, input_dim) tensors
        times:        list of floats, observation timestamps
        """
        batch_size = observations[0].shape[0]
        h = torch.zeros(batch_size, self.hidden_dim)

        outputs = []
        for i in range(len(observations)):
            t_prev = 0.0 if i == 0 else times[i - 1]
            h = self.cell(h, observations[i], t_prev, times[i])
            outputs.append(self.decoder(h))

        return torch.stack(outputs)  # (seq_len, batch, 1)

Boucle d'entraînement

def train_neural_ode(model, train_loader, epochs=100, lr=1e-3):
    optimizer = torch.optim.Adam(model.parameters(), lr=lr)
    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
        optimizer, T_max=epochs
    )

    for epoch in range(epochs):
        epoch_loss = 0.0
        for batch in train_loader:
            features, times, targets = batch
            optimizer.zero_grad()

            predictions = model(features, times)
            loss = torch.nn.functional.mse_loss(predictions, targets)

            loss.backward()
            torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
            optimizer.step()

            epoch_loss += loss.item()

        scheduler.step()

        if (epoch + 1) % 10 == 0:
            avg_loss = epoch_loss / len(train_loader)
            print(f"Epoch {epoch+1}/{epochs}, Loss: {avg_loss:.6f}")

Flux de normalisation continu pour les distributions de retour

from torchdiffeq import odeint

class CNFDynamics(nn.Module):
    """Dynamics for continuous normalizing flow."""

    def __init__(self, dim: int = 1, hidden_dim: int = 64):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(dim + 1, hidden_dim),  # +1 for time
            nn.Tanh(),
            nn.Linear(hidden_dim, hidden_dim),
            nn.Tanh(),
            nn.Linear(hidden_dim, dim),
        )
        self.dim = dim

    def forward(self, t, state):
        z = state[..., :self.dim]
        t_expand = t.expand(z.shape[0], 1)
        zt = torch.cat([z, t_expand], dim=-1)
        dz = self.net(zt)

        e = torch.randn_like(z)
        e_dz = torch.autograd.grad(
            dz, z, e, create_graph=True
        )[0]
        trace_jac = (e_dz * e).sum(dim=-1, keepdim=True)

        return torch.cat([dz, -trace_jac], dim=-1)


class ReturnDistributionCNF(nn.Module):
    """Model return distributions with continuous normalizing flows."""

    def __init__(self, dim: int = 1):
        super().__init__()
        self.dynamics = CNFDynamics(dim)
        self.dim = dim

    def log_prob(self, x):
        """Compute log probability of observed returns."""
        log_p0 = torch.zeros(x.shape[0], 1)
        state0 = torch.cat([x, log_p0], dim=-1)
        state0.requires_grad_(True)

        times = torch.tensor([1.0, 0.0])  # backward
        state_T = odeint(self.dynamics, state0, times,
                         method='dopri5')[-1]

        z_T = state_T[..., :self.dim]
        delta_log_p = state_T[..., self.dim:]

        log_p_base = -0.5 * (z_T ** 2 + torch.log(
            torch.tensor(2 * torch.pi)
        )).sum(dim=-1, keepdim=True)

        return log_p_base + delta_log_p

    def sample(self, n_samples: int):
        """Generate samples from learned distribution."""
        z0 = torch.randn(n_samples, self.dim)
        log_p0 = torch.zeros(n_samples, 1)
        state0 = torch.cat([z0, log_p0], dim=-1)

        times = torch.tensor([0.0, 1.0])  # forward
        state_T = odeint(self.dynamics, state0, times,
                         method='dopri5')[-1]

        return state_T[..., :self.dim]

Notes pratiques

Compromis équilibré entre précision numérique et vitesse d'inférence

Ce sont les choses qui vous mordront lors de l’exécution de l’expérience ci-dessus.

Choix et vitesse du solveur

dopri5 donne des garanties de précision mais un coût de calcul variable, c'est pourquoi H3 est une hypothèse distincte de H2 : un avantage qui n'existe que sous un solveur adaptatif peut ne pas survivre à un budget de latence réel. Les solveurs à pas fixes (Euler, RK4) offrent une latence prévisible au détriment de la précision. Compromis pratique : s'entraîner avec dopri5, déployez avec un solveur à pas fixe calibré pour correspondre aux résultats du solveur adaptatif sur des données représentatives — et mesurez l'écart plutôt que de supposer qu'il est petit.

odeint(f, h0, t, method='dopri5', rtol=1e-6, atol=1e-8)

odeint(f, h0, t, method='euler', options={'step_size': 0.1})

Pour les problèmes de raideur à proximité des sauts discontinus, method='implicit_adams' ou method='scipy_solver'.

Stabilité numérique

Si fθf_\theta produit de grandes valeurs, l'état diverge. Atténuations :

  • normalisation spectrale sur des couches de fθf_\theta pour contrôler la constante de Lipschitz.
  • Dégradé de coupure pendant l'entraînement (affiché dans la boucle d'entraînement ci-dessus).
  • normalisation du temps : mettre à l'échelle les horodatages [0,1][0, 1].
  • Régularisation sur norme dynamique : ajout λfθ(h,t)2\lambda \|f_\theta(h, t)\|^2 à la perte.

Intervalle d'intégration

Pour les données s'étendant sur plusieurs mois, n'intégrez pas à partir de t=0t = 0 à t=10,000t = 10{,}000 minutes:

t_normalized = (timestamps - timestamps[0]) / (timestamps[-1] - timestamps[0])

Cela maintient le solveur dans un régime numériquement convivial et rend la dynamique apprise invariante à l'échelle. Cela est également important pour la comparaison : un ODE-RNN non normalisé peut perdre par rapport à la ligne de base du GRU pour des raisons purement numériques, ce qui serait un artefact de mesure plutôt qu'un résultat.

Gestion de plusieurs échelles de temps

Les marchés ont des dynamiques à l’échelle de la microseconde, de la seconde, de la minute et du jour à la fois, et une seule ODE neuronale peut avoir du mal à les contenir toutes. Options : empiler plusieurs blocs ODE à différentes échelles de temps ; étendez la dimension cachée pour la capacité rapide et lente ; ou exécutez des ODE neuronales distinctes par bande de fréquence et par fusible. (Il s'agit d'une question de capacité de modèle, distincte de la question de fidélité du backtest dans exploration en profondeur de la résolution adaptative.)

Orientations de recherche ouvertes

Ouvrir des trajectoires de recherche en temps continu rayonnant à partir d'un modèle

Neural Jump SDE : ajoutez un composant de saut appris pour les luxations soudaines (plantages flash, surprises en matière de bénéfices) :

dh=fdt+gdW+Rγ(h,z)N~(dt,dz)dh = f \, dt + g \, dW + \int_{\mathbb{R}} \gamma(h, z) \, \tilde{N}(dt, dz)

N~\tilde{N} est une mesure aléatoire de Poisson compensée et γ\gamma un noyau de saut appris.

Équations différentielles contrôlées par les neurones (CDE neuronales) : remplacez le processus de Wiener par un signal de pilotage général, permettant aux flux de données observés de piloter la dynamique. Naturel pour le flux d’ordres, où le flux de transactions et de cotations détermine l’état latent du marché.

Simulation de marché différenciable : utilisez un SDE neuronal comme modèle génératif dans un simulateur différenciable et entraînez des stratégies de bout en bout en rétropropagant à travers celui-ci via l'adjoint. La stratégie et le modèle de marché co-évoluent.

** ODE neuronales fondées sur la physique ** : les PINN intègrent un résidu d'équation différentielle dans la perte - la technique elle-même est présentée dans [l'article de Navier-Stokes] (/en/blog/post/navier-stokes-problem). L'application financière consiste à imposer des conditions de non-arbitrage, de parité put-call et de martingale comme conditions de pénalité ou de contraintes strictes sur la dynamique apprise.

Conclusion

Dynamique continue et fluide se résolvant en une conclusion mesurée

Le cadrage en temps continu est structurellement correct : les marchés sont des processus continus observés à des moments discrets et irréguliers, et les modèles doivent respecter cela. La chaîne d’outils est mature — torchdiffeq, torchsde, PyTorch simple pour le reste – et les coûts connus sont la vitesse du solveur et la stabilité numérique sur de longs intervalles d'intégration.

Ce qui n’est pas établi, c’est la partie qui décide si tout cela appartient à une pile de production. L’exactitude structurelle ne constitue pas une preuve d’un avantage prédictif, et l’avantage spécifique revendiqué pour une dynamique continue sur une log(Δt)\log(\Delta t) Cette fonctionnalité n’a pas été mesurée ici sur des données commerciales réelles. Jusqu'à ce que le tableau H2 ci-dessus soit rempli, traitez tout ce qui se trouve en dessous de la ligne de flottaison comme une hypothèse bien spécifiée avec une implémentation fonctionnelle attachée, et non comme un résultat.


Références

  • Chen, R.T.Q., Rubanova, Y., Bettencourt, J., Duvenaud, D. (2018). Équations différentielles ordinaires neuronales. NeurIPS 2018. arXiv:1806.07366
  • Rubanova, Y., Chen, R.T.Q., Duvenaud, D. (2019). ODE latentes pour les séries chronologiques à échantillonnage irrégulier. NeurIPS 2019. arXiv:1907.03907
  • Jia, J., Benson, AR. (2019). Équations différentielles stochastiques de saut neuronal. NeurIPS 2019.
  • Kidger, P., Morrill, J., Foster, J., Lyons, T. (2020). Équations différentielles contrôlées par les neurones pour les séries temporelles irrégulières. NeuroIPS 2020.
  • Hasan, A., Pereira, JM, Farsiu, S., Carin, L. (2021). Modèles d'équations différentielles stochastiques de réseau neuronal avec applications à la prévision des données financières. arXiv:2111.13164
  • torchdiffeq : github.com/rtqichen/torchdiffeq
  • Tutoriels UvA Deep Learning — ODE neuronales : uvadlc-notebooks.readthedocs.io
blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

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.

Newsletter

Gardez une longueur d'avance sur le marché

Abonnez-vous à notre newsletter pour des insights exclusifs sur le trading IA, des analyses de marché et des mises à jour de la plateforme.

Nous respectons votre vie privée. Désabonnement possible à tout moment.