← Volver a los artículos
August 5, 2026
5 min de lectura

Operador neuronal de Fourier para modelado financiero basado en PDE

Operador neuronal de Fourier para modelado financiero basado en PDE
#deep-learning
#FNO
#PDE
#operator-learning
#options

Cada red neuronal en este blog hasta ahora se ha aproximado a una función: funciones dentro, un número fuera. El operador neuronal de Fourier se aproxima a un operador: un mapa entre espacios funcionales de dimensión infinita, donde la entrada es una superficie de volatilidad completa y la salida es una superficie de precios completa. Ese es un objeto diferente, necesita maquinaria diferente, y la maquinaria es el objetivo de este artículo: un núcleo de valores complejos que se puede aprender aplicado a los modos de Fourier más bajos, evaluado a través de un viaje de ida y vuelta FFT en O(nlogn)O(n \log n).

El precio de las opciones es donde esto aterriza en las finanzas. Black-Scholes, Heston, volatilidad local: todas las PDE, todas resueltas hoy, un conjunto de parámetros a la vez. Un operador aprende toda la familia de parámetros a la vez y el paso hacia adelante resultante es un único núcleo de GPU por lotes en lugar de un bucle de marcha en el tiempo.

Esa es la promesa. La versión honesta de este artículo separa las mecánicas, que son sólidas y reproducibles del código siguiente, de las afirmaciones de rendimiento, que en la literatura de FNO se informan contra líneas de base que nadie en esta serie aceptaría sin examinar. La mecánica es lo primero; la agenda de medición aparece al final, marcada como no ejecutada.

De la aproximación de funciones al aprendizaje del operador

Funciones aproximadas de las redes neuronales clásicas: dada una entrada xRnx \in \mathbb{R}^n, producen una salida yRmy \in \mathbb{R}^m. Esto es poderoso, pero fundamentalmente limitado cuando los objetos de interés son en sí mismos funciones. En la resolución de PDE financieras, la entrada no es un solo número: es una función que describe las condiciones iniciales/de límite, una superficie de volatilidad o una estructura de términos. La producción es otra función: la superficie de precios sobre (S,t)(S, t) espacio.

El aprendizaje del operador eleva el problema a espacios de dimensiones infinitas. en lugar de aprender f:RnRmf: \mathbb{R}^n \to \mathbb{R}^m, aprendemos un operador:

G:AU\mathcal{G}: \mathcal{A} \to \mathcal{U}

dónde A\mathcal{A} y U\mathcal{U} son espacios de funciones de Banach. Para el precio de opciones, A\mathcal{A} podría ser el espacio de las superficies de volatilidad σ(S,t)\sigma(S,t) y U\mathcal{U} el espacio de las superficies de precios correspondientes V(S,t)V(S,t).

Dos arquitecturas dominan el panorama del aprendizaje del operador:

  1. DeepONet (Lu et al., 2021): utiliza una red de sucursales para codificar la función de entrada y una red troncal para codificar la ubicación de la consulta. La salida es su producto interior. Basado en el teorema de aproximación universal para operadores de Chen y Chen (1995).

  2. Operador neuronal de Fourier (Li et al., 2021): parametriza el núcleo integral en el espacio de Fourier, utilizando la FFT para una convolución global eficiente. Resolución invariante por construcción.

Ambos son aproximadores universales para operadores continuos, pero FNO tiene una ventaja estructural para los problemas de PDE: su sesgo espectral captura naturalmente la estructura global y fluida de las soluciones de PDE. También tiene una desventaja estructural específicamente para los pagos de opciones, sobre lo que volveremos: una base de Fourier truncada y un problema en el strike no son aliados naturales.

Arquitectura FNO en detalle

El operador neuronal de Fourier, presentado por Li et al. en ICLR 2021, se basa en una observación simple pero poderosa: la función de Green (núcleo integral) de muchas PDE tiene una representación compacta en el espacio de Fourier. En lugar de aprender un núcleo en el espacio físico, lo que requiere O(n2)O(n^2) parámetros para nn puntos de la cuadrícula: FNO lo aprende en el espacio de frecuencia con solo el más bajo kmaxk_{\max} modos, reduciendo la complejidad a O(nlogn)O(n \log n) a través de la FFT.

La arquitectura iterativa

Un FNO consta de:

  1. Capa de elevación PP: Un mapa lineal puntual que proyecta la entrada desde su dimensión de canal original a una representación latente de dimensión superior: v0(x)=P(a(x))v_0(x) = P(a(x)).

  2. Capas de Fourier (repetidas LL veces): Cada capa se aplica:

vl+1(x)=σ(Wlvl(x)+Kl(vl)(x))v_{l+1}(x) = \sigma\left(W_l \, v_l(x) + \mathcal{K}_l(v_l)(x)\right)

dónde WlW_l es una transformada lineal local (puntual 1×11 \times 1 convolución) y Kl\mathcal{K}_l es un operador integral global implementado a través de la FFT:

Kl(vl)(x)=F1(RlF(vl))(x)\mathcal{K}_l(v_l)(x) = \mathcal{F}^{-1}\left(R_l \cdot \mathcal{F}(v_l)\right)(x)

Aquí F\mathcal{F} denota la FFT, RlR_l es un tensor de peso de valor complejo que se puede aprender y se aplica al nivel más bajo kmaxk_{\max} Modos de Fourier y σ\sigma es una activación no lineal puntual (típicamente GELU).

  1. Capa de proyección QQ: Asigna la representación latente a la dimensión de salida: u(x)=Q(vL(x))u(x) = Q(v_L(x)).

¿Por qué el espacio de Fourier?

La convolución espectral RlF(vl)R_l \cdot \mathcal{F}(v_l) es una multiplicación en el dominio de la frecuencia, que es equivalente a una convolución global en el espacio físico, pero calculada en O(nlogn)O(n \log n) en lugar de O(n2)O(n^2). Esto no es sólo un truco de eficiencia. Las soluciones PDE suelen ser fluidas y dominadas por componentes de baja frecuencia. Al truncar a kmaxk_{\max} En estos modos, FNO actúa como un filtro de paso bajo que se puede aprender y que regulariza naturalmente la solución y evita artefactos de alta frecuencia.

Fundamentalmente, se afirma que FNO es invariante de discretización: una vez entrenado en una cuadrícula de tamaño nn, se puede evaluar en cualquier resolución mnm \neq n simplemente ajustando el tamaño de FFT y rellenando con ceros o truncando los pesos espectrales. Esta propiedad de superresolución de disparo cero es única entre los solucionadores de PDE neuronales, y es la primera afirmación de este artículo que merece una medición en lugar de una cita. Consulte la agenda de mediciones a continuación.

La PDE para la que estamos aprendiendo el operador

La PDE de Black-Scholes, derivada, analizada término por término y presentada con su solución call/put de forma cerrada en La fórmula de Black-Scholes, es el objetivo del operador:

Vt+12σ2S22VS2+rSVSrV=0\frac{\partial V}{\partial t} + \frac{1}{2}\sigma^2 S^2 \frac{\partial^2 V}{\partial S^2} + rS\frac{\partial V}{\partial S} - rV = 0

Todo lo que sigue lo trata como una caja negra con una respuesta conocida. Esa respuesta conocida es exactamente la razón por la cual es el caso de prueba correcto: un operador capacitado en salidas de diferencias finitas puede ser calificado contra norm.cdf precios exactos, algo que casi ningún punto de referencia de FNO en la literatura puede hacer.

Formulación de FNO

Replanteamos el problema como aprendizaje del operador. Definir:

  • Función de entrada a(S,t)a(S, t): codifica los parámetros de PDE. Esto puede incluir la superficie de volatilidad. σ(S,t)\sigma(S, t), la función de pago y la tasa libre de riesgo como canales apilados en el (S,t)(S, t) red.
  • Función de salida u(S,t)=V(S,t)u(S, t) = V(S, t): la superficie del precio de la opción.

La FNO aprende Gθ:au\mathcal{G}_\theta: a \mapsto u de un conjunto de datos de (a(i),u(i))(a^{(i)}, u^{(i)}) pares generados por un solucionador tradicional. Después del entrenamiento, la inferencia para cualquier configuración de parámetro nueva es de un solo paso hacia adelante.

Generación de datos de entrenamiento

import numpy as np
from scipy.stats import norm

def black_scholes_fd(sigma, r, K, T, S_max=300, N_S=256, N_t=256):
    """Solve Black-Scholes PDE via explicit finite differences.

    NOTE: this is an interpreted double loop — the *worst* CPU baseline,
    exactly the kind called out in /en/blog/post/when-gpu-pays-off-sweep-roofline.
    It is fine for generating training data offline. It is NOT the baseline
    any speedup claim should be measured against; vectorize the inner loop
    over i (or use scipy sparse + implicit stepping) before timing anything.
    """
    dS = S_max / N_S
    dt = T / N_t
    S = np.linspace(0, S_max, N_S + 1)

    V = np.maximum(S - K, 0).astype(np.float64)

    for j in range(N_t):
        V_new = V.copy()
        for i in range(1, N_S):
            delta = (V[i+1] - V[i-1]) / (2 * dS)
            gamma = (V[i+1] - 2*V[i] + V[i-1]) / (dS**2)
            V_new[i] = V[i] + dt * (
                0.5 * sigma**2 * S[i]**2 * gamma
                + r * S[i] * delta
                - r * V[i]
            )
        V_new[0] = 0
        V_new[N_S] = S_max - K * np.exp(-r * (T - (j+1)*dt))
        V = V_new

    return S, V

Para la capacitación, tomamos muestras de miles de configuraciones de parámetros, que varían σ[0.05,0.80]\sigma \in [0.05, 0.80], r[0.01,0.10]r \in [0.01, 0.10], K[50,150]K \in [50, 150], T[0.1,2.0]T \in [0.1, 2.0] - y resuelve cada uno con el método de diferencias finitas. El conjunto de datos resultante de pares entrada-salida es de lo que aprende el FNO.

Ampliación: el modelo de volatilidad estocástica de Heston

La volatilidad constante es una suposición falsa, y por qué falla (la sonrisa, las colas gordas) es el tema de la sección "Dura realidad" de La fórmula Black-Scholes. Heston lo soluciona haciendo de la varianza una segunda variable de estado:

dS=rSdt+vSdW1dS = rS\,dt + \sqrt{v}\,S\,dW_1 dv=κ(θv)dt+ξvdW2dv = \kappa(\theta - v)\,dt + \xi\sqrt{v}\,dW_2

con Corr(dW1,dW2)=ρ\text{Corr}(dW_1, dW_2) = \rho. La PDE correspondiente al precio de la opción. V(S,v,t)V(S, v, t) es bidimensional en el espacio:

Vt+12vS22VS2+ρξvS2VSv+12ξ2v2Vv2+rSVS+κ(θv)VvrV=0\frac{\partial V}{\partial t} + \frac{1}{2}vS^2\frac{\partial^2 V}{\partial S^2} + \rho\xi vS\frac{\partial^2 V}{\partial S \partial v} + \frac{1}{2}\xi^2 v\frac{\partial^2 V}{\partial v^2} + rS\frac{\partial V}{\partial S} + \kappa(\theta - v)\frac{\partial V}{\partial v} - rV = 0

Aquí es donde el aprendizaje del operador se gana la vida, y el argumento es más estructural que empírico. Esquemas de diferencias finitas en un (S,v,t)(S, v, t) escala de cuadrícula como O(NS×Nv×Nt)O(N_S \times N_v \times N_t), el término de derivada cruzada 2V/Sv\partial^2 V / \partial S \partial v complica la discretización, y cada nuevo conjunto de parámetros (κ,θ,ξ,ρ,r)(\kappa, \theta, \xi, \rho, r) paga el costo total nuevamente. Un operador lo paga una vez en el momento de la formación. La estructura espacial 2D del PDE de Heston también se asigna directamente a la FFT 2D en las capas de Fourier, por lo que la arquitectura siguiente se generaliza con un cambio de dimensión en lugar de un rediseño.

FNO para precios de opciones: implementación de PyTorch

A continuación se muestra una implementación FNO completa e independiente para aprender el operador Black-Scholes. La arquitectura sigue a Li et al. (2021) con adaptaciones al entorno financiero.

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.fft import rfft, irfft

class SpectralConv1d(nn.Module):
    """1D Fourier layer: spectral convolution via FFT."""

    def __init__(self, in_channels: int, out_channels: int, modes: int):
        super().__init__()
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.modes = modes  # Number of Fourier modes to keep

        scale = 1.0 / (in_channels * out_channels)
        self.weights = nn.Parameter(
            scale * torch.randn(in_channels, out_channels, modes, dtype=torch.cfloat)
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        batch_size = x.shape[0]

        x_ft = rfft(x, dim=-1)

        out_ft = torch.zeros(
            batch_size, self.out_channels, x_ft.size(-1),
            dtype=torch.cfloat, device=x.device
        )
        out_ft[:, :, :self.modes] = torch.einsum(
            "bix,iox->box", x_ft[:, :, :self.modes], self.weights
        )

        return irfft(out_ft, n=x.size(-1), dim=-1)


class FNOBlock(nn.Module):
    """Single Fourier Neural Operator block."""

    def __init__(self, channels: int, modes: int):
        super().__init__()
        self.spectral_conv = SpectralConv1d(channels, channels, modes)
        self.pointwise = nn.Conv1d(channels, channels, kernel_size=1)
        self.norm = nn.InstanceNorm1d(channels)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return F.gelu(self.norm(self.spectral_conv(x) + self.pointwise(x)))


class FNO1d(nn.Module):
    """
    Fourier Neural Operator for 1D PDE problems.

    Learns the mapping: PDE parameters -> solution function
    """

    def __init__(
        self,
        in_channels: int = 3,    # e.g., sigma(S), payoff(S), grid(S)
        out_channels: int = 1,   # V(S)
        hidden_channels: int = 64,
        modes: int = 32,
        num_layers: int = 4,
    ):
        super().__init__()
        self.lift = nn.Linear(in_channels, hidden_channels)
        self.blocks = nn.ModuleList(
            [FNOBlock(hidden_channels, modes) for _ in range(num_layers)]
        )
        self.proj = nn.Sequential(
            nn.Linear(hidden_channels, 128),
            nn.GELU(),
            nn.Linear(128, out_channels),
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = self.lift(x)                    # -> (batch, spatial, hidden)
        x = x.permute(0, 2, 1)              # -> (batch, hidden, spatial)

        for block in self.blocks:
            x = block(x)

        x = x.permute(0, 2, 1)              # -> (batch, spatial, hidden)
        return self.proj(x)                  # -> (batch, spatial, out_channels)

Bucle de entrenamiento

import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset

def train_fno_black_scholes():
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    N_samples = 5000
    N_S = 256
    S_max = 300.0
    S_grid = np.linspace(0, S_max, N_S + 1)

    inputs, targets = [], []
    for _ in range(N_samples):
        sigma = np.random.uniform(0.05, 0.80)
        r = np.random.uniform(0.01, 0.10)
        K = np.random.uniform(50, 150)
        T = np.random.uniform(0.1, 2.0)

        _, V = black_scholes_fd(sigma, r, K, T, S_max=S_max, N_S=N_S)

        sigma_field = np.full(N_S + 1, sigma)
        payoff = np.maximum(S_grid - K, 0)
        grid_norm = S_grid / S_max

        inp = np.stack([sigma_field, payoff, grid_norm], axis=-1)
        inputs.append(inp)
        targets.append(V[:, None])

    X = torch.tensor(np.array(inputs), dtype=torch.float32)
    Y = torch.tensor(np.array(targets), dtype=torch.float32)

    dataset = TensorDataset(X, Y)
    loader = DataLoader(dataset, batch_size=64, shuffle=True)

    model = FNO1d(in_channels=3, out_channels=1, hidden_channels=64, modes=32).to(device)
    optimizer = optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-4)
    scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=200)

    for epoch in range(200):
        model.train()
        total_loss = 0.0
        for batch_x, batch_y in loader:
            batch_x, batch_y = batch_x.to(device), batch_y.to(device)

            pred = model(batch_x)
            loss = torch.mean(
                torch.norm(pred - batch_y, dim=1)
                / torch.norm(batch_y, dim=1).clamp(min=1e-8)
            )

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            total_loss += loss.item()

        scheduler.step()
        if (epoch + 1) % 20 == 0:
            avg = total_loss / len(loader)
            print(f"Epoch {epoch+1:3d} | Relative L2 Loss: {avg:.6f}")

    return model

Inferencia: fijación de precios en tiempo real

@torch.no_grad()
def price_option(model, sigma, K, S_grid, device="cuda"):
    """
    Price a European call for given sigma and strike.
    Returns prices for all S in S_grid — single forward pass.
    """
    S_max = S_grid[-1]
    payoff = np.maximum(S_grid - K, 0)
    grid_norm = S_grid / S_max
    sigma_field = np.full_like(S_grid, sigma)

    inp = np.stack([sigma_field, payoff, grid_norm], axis=-1)
    x = torch.tensor(inp, dtype=torch.float32).unsqueeze(0).to(device)

    pred = model(x)
    return pred.squeeze().cpu().numpy()

FNO frente a PINN: una comparación práctica

Las redes neuronales basadas en la física y los operadores neuronales de Fourier representan filosofías fundamentalmente diferentes para resolver PDE con redes neuronales. Comprender sus compensaciones es la razón práctica para preocuparse por el aprendizaje del operador.

PINN: optimización por instancia

Los PINN colocan el residuo de PDE directamente en la pérdida: El problema de Navier-Stokes cubre el mecanismo, el autodiff physics_loss implementación y el resultado de la búsqueda de singularidad de DeepMind. La única propiedad que importa aquí es estructural: se entrena un PINN por conjunto de parámetros. Cambiar σ\sigma, rr, KK o TT y optimizas nuevamente desde cero.

Fortalezas: No se requieren datos etiquetados. Hace cumplir directamente la estructura PDE. Funciona para cualquier PDE que puedas anotar.

Debilidades: Debe volver a capacitarse para cada nuevo conjunto de parámetros (σ,r,K,T)(\sigma, r, K, T). La formación implica equilibrar múltiples términos de pérdida (PDE residual, condiciones de contorno, condiciones iniciales), lo que a menudo conduce a patologías de optimización. La convergencia puede ser lenta: normalmente entre 10.000 y 100.000 pasos de gradiente por instancia de problema. Falla en sistemas caóticos y de múltiples escalas donde el panorama de pérdidas se vuelve muy no convexo.

FNO: Aprendizaje de Operador Amortizado

FNO aprende el operador de la solución a partir de los datos. Requiere un conjunto de datos de entrenamiento generado por un solucionador clásico, pero una vez entrenado, se generaliza en todo el espacio de parámetros.

Fortalezas: Inferencia de submilisegundos en los puntos de referencia publicados. Generaliza a parámetros invisibles sin volver a entrenar. Invariante de resolución: entrene a baja resolución, evalúe a alta resolución. Maneja de forma natural soluciones PDE fluidas mediante polarización espectral.

Debilidades: Requiere datos de entrenamiento de un solucionador clásico (problema del huevo y la gallina para PDE verdaderamente novedosas). El error de aproximación es acotado pero distinto de cero. Menos interpretable que los enfoques restringidos por PDE. Y el sesgo espectral que ayuda a lograr soluciones fluidas es un inconveniente en el caso de los beneficios.

Comparación directa

La siguiente tabla está informada en la literatura, no medida aquí; las filas de precisión y aceleración en particular provienen de Li et al. (2021) y trabajo de seguimiento sobre puntos de referencia fluidos, no sobre precios de opciones en nuestro hardware. Lea las filas estructurales (datos necesarios, generalización, invariancia de resolución) como confiables.

Criterio PIN FNO
Se necesitan datos de entrenamiento Ninguno (sin supervisión) Pares generados por solucionador
Costo de inferencia Reentrenamiento completo por instancia Pase único hacia delante
Generalización Conjunto de parámetros únicos Toda la familia de parámetros
Invariancia de resolución No Afirmó que sí: consulte la agenda a continuación
PDE multiescala A menudo falla Reportado robusto
Precisión (relativa L2L^2, literatura) 10310^{-3} a 10210^{-2} 10410^{-4} a 10310^{-3}

El híbrido: operadores neuronales basados en la física (PINO)

PINO (Li et al., 2024) combina ambos enfoques. Utiliza la arquitectura FNO pero aumenta la pérdida basada en datos con un término residual PDE:

LPINO=Ldata+λLPDE\mathcal{L}_{\text{PINO}} = \mathcal{L}_{\text{data}} + \lambda \, \mathcal{L}_{\text{PDE}}

La descomposición es la parte útil. Ldata\mathcal{L}_{\text{data}} ancla el operador a la salida del solucionador dondequiera que lo tenga; λLPDE\lambda \mathcal{L}_{\text{PDE}} lo restringe en todos los lugares donde no lo hace, incluidas las regiones del espacio de parámetros que nunca muestreó. Para la fijación de precios de opciones, ese segundo término es atractivo por una razón específica de las finanzas: el residual de la PDE es una restricción dura que también se puede evaluar en el momento de la inferencia como una autoverificación, que es la base del respaldo de monitoreo de residuos que se presenta a continuación.

Consideraciones prácticas para la implementación de producción

La mitad genérica de esto (presupuestos de latencia de inferencia, construcción de la canalización de datos, monitoreo de deriva, reentrenamiento periódico) ya está cubierta para un modelo neuronal en un sistema comercial en la sección de producción de DeepLOB: Deep Learning on Limit Order Books, y se aplica sin cambios. Lo que sigue es sólo lo que es específico de un operador.

Canalización de datos: muestreo del espacio de parámetros

La generación de datos de entrenamiento es el principal cuello de botella y, a diferencia de un modelo de datos de mercado, usted elige su propia distribución, lo que significa que puede equivocarse de una manera que es invisible en la pérdida. Para el operador de Black-Scholes con 4 parámetros, son suficientes entre 5.000 y 10.000 muestras. Para Heston con 5 parámetros más un dominio espacial 2D, lo típico son entre 20.000 y 50.000 muestras. Utilice muestreo adaptativo: concentre las muestras en regiones de parámetros donde la solución varía rápidamente (cerca del dinero, vencimientos cortos, alta volatilidad) porque el muestreo uniforme de la caja gasta la mayor parte de su presupuesto en regiones de ITM profundo y OTM profundo donde el operador es casi lineal y aprende bien de muy pocos ejemplos.

Ajuste de arquitectura

  • Modos (kmaxk_{\max}): Comience con N/4N/4 dónde NN es el tamaño de la cuadrícula espacial. Para N=256N=256, utilice 32–64 modos. Muy pocos modos pierden detalles cerca de los límites del ataque; demasiados sobreadaptados al ruido.
  • Capas: 4 capas de Fourier son estándar. Las redes más profundas (6–8) ayudan para problemas 2D como Heston pero aumentan la memoria.
  • Canales ocultos: 64 para 1D Black-Scholes, 128 para 2D Heston. Escale con la complejidad del problema.

Precisión: la cuestión del fp32

SpectralConv1d asigna torch.cfloat - complejo de precisión simple - y cada viaje de ida y vuelta de FFT se ejecuta con esa precisión. Este blog ya ha observado cómo un canal financiero fp32 devuelve basura silenciosa en The GPU Precision Trap, donde una formulación de suma de prefijo matemáticamente correcta perdió catastróficamente en magnitudes fp32. La pregunta análoga aquí es directa: en S100S \approx 100 con precios cotizados al centavo, ¿se mantiene un viaje espectral de ida y vuelta fp32 a 10210^{-2} absoluta, o el crecimiento de magnitud intermedia de la FFT se come los últimos dígitos significativos?

Control de errores

Para fijar el precio de las opciones de producción, necesita límites de error que pueda defender.

  1. Incertidumbre calibrada: una desviación estándar del conjunto no es una garantía de cobertura, y este blog tiene la maquinaria para hacerlo correctamente: dividir la conformidad sobre una cuadrícula de parámetros retenidos, con ACI/DtACI para el caso no intercambiable, en Predicción conforme para el tamaño de posiciones conscientes del riesgo. Envolviendo el FNO en split conformal sobre el (σ,r,K,T)(\sigma, r, K, T) grid proporciona intervalos libres de distribución en el precio.
  2. Monitoreo residual: Calcule el PDE residual de la predicción FNO como una verificación post-hoc. Si residual>ϵ\|\text{residual}\| > \epsilon, recurra a un solucionador clásico. Esto es gratis en la inferencia: el residual es una plantilla de diferencias finitas en una matriz que ya tiene.
  3. Aprendizaje activo: enrute entradas de alta incertidumbre al solucionador clásico, agregue los resultados al conjunto de entrenamiento y vuelva a entrenar periódicamente. El ancho del intervalo conforme de (1) es la señal de enrutamiento natural.

La agenda de medición

Esta es la parte que decide si vale la pena implementar la arquitectura anterior, y nada de eso está hecho todavía. Se incluye aquí en lugar de estar enterrado porque la alternativa (afirmar una aceleración de los titulares) es precisamente el registro que este blog pretende evitar.

1. La aceleración es una curva, no un número. Cuando la GPU da resultados establece la forma: S(B)=aB/(O+bB)S(B) = aB/(O + bB), pasando de estar dominado por los gastos generales B=1B=1 a una meseta vinculada a la computación, y muestra un título de 167x que se descompone en 27x de algoritmo multiplicado por 6,2x de hardware. La medición de FNO debe seguir ese modelo: marcar en la pared el pase hacia adelante en B{1,8,64,512}B \in \{1, 8, 64, 512\} y reportar toda la curva. Fundamentalmente, la línea de base debe ser un solucionador de diferencias finitas vectorizado y multinúcleo: el black_scholes_fd Lo anterior es un bucle doble interpretado, la línea de base exacta de la "peor implementación de CPU" que nombra el artículo, y comparar un operador de GPU por lotes con él produciría un número que no significa nada.

2. Precisión frente a la forma cerrada. Este es el experimento que Black-Scholes hace casi gratis y que los puntos de referencia de dinámica de fluidos no pueden hacer en absoluto: entrenar con datos generados por FD, luego calificar contra datos exactos. norm.cdf precios en todo el (σ,r,K,T)(\sigma, r, K, T) caja. Reportar al familiar L2L^2, e informar el error distribución, específicamente cerca del strike y cerca del vencimiento, donde la solución es menos fluida y la base espectral truncada debería tener más dificultades.

3. Violaciones de no arbitraje. Un operador aprendido no tiene ninguna razón estructural para respetar las restricciones de forma que una superficie de precios debe satisfacer: monotonicidad en KK, convexidad en KK, y Vmax(SK,0)V \geq \max(S-K, 0). Medir la tasa de infracción en el cuadro de parámetros convierte la pregunta abierta de este artículo (¿podemos garantizar condiciones de no arbitraje en el operador aprendido?) de un gesto con la mano a un número.

4. Invariancia de discretización, probada en lugar de afirmada. Entrene en NS=128N_S = 128, evaluar en NS=512N_S = 512, reporta el error. El modo de falla esperado tiene un nombre y es específico: Gibbs sonando en la torcedura max(SK,0)\max(S-K, 0). Una base de Fourier truncada que reconstruye una función con una primera derivada discontinua oscila a su alrededor, y la superresolución de disparo cero puede empeorar eso en lugar de mejorar al exponer modos que la resolución de entrenamiento nunca vio. Si la superresolución se degrada cerca del strike, ese resultado negativo es más valioso que la afirmación de marketing que reemplaza: nadie en la literatura de FNO valora opciones con un problema de rentabilidad.

Si no se pueden realizar los experimentos 1 a 4, este artículo no debería enviarse. Lo que queda sin ellos es una exposición bien escrita del artículo de ICLR de otra persona.

Más allá de las opciones estándar

Suponiendo que la agenda anterior sobreviva al contacto con la medición, el marco FNO se extiende naturalmente a instrumentos más complejos:

  • Opciones americanas: Añadir un límite de ejercicio temprano como canal de salida adicional. El FNO aprende simultáneamente tanto la superficie de precios como el límite de ejercicio óptimo.
  • Opciones de barrera: codifica niveles de barrera como canales de entrada. Obsérvese que una barrera es una segunda discontinuidad, y la preocupación de Gibbs sobre la agenda de medición se aplica con más fuerza, no menos.
  • Cestas de activos múltiples: utilice FNO 2D o 3D para opciones de cesta sobre 2 o 3 subyacentes. La maldición de la dimensionalidad es menos grave que para los solucionadores basados ​​en cuadrículas porque el FNO opera en un número fijo de modos.
  • Volatilidad local: ingrese la superficie de volatilidad local completa de Dupire σloc(S,t)\sigma_{\text{loc}}(S,t) como función espacial. Este es el caso de uso más natural para el aprendizaje de operadores: la entrada es una función, no un parámetro escalar.

Conclusión

La contribución del operador neuronal de Fourier es conceptual antes que computacional: en lugar de resolver una PDE a la vez, se parametriza el operador de solución en sí, y al hacerlo en el espacio de Fourier se obtiene una arquitectura que es O(nlogn)O(n \log n), universal en operadores continuos y resolución flexible por construcción. Esto se desprende de Li et al. (2021) y del código anterior, que se ejecuta.

Lo que no sigue es un número de aceleración. Las cifras de 100x-1000x de la literatura se miden en puntos de referencia fluidos contra líneas de base cuya calidad rara vez se indica, y esta serie ha dedicado un artículo completo a mostrar cuánto de ese titular suele ser algorítmico en lugar de hardware. Las afirmaciones que justificarían poner a un operador en un motor de precios (precisión fp32 a nivel de centavo, una tasa de violación limitada sin arbitraje, súper resolución que sobrevive a un problema de rentabilidad y una curva de aceleración frente a un solucionador de CPU competente) son todas mensurables, todas baratas en Black-Scholes porque existe la forma cerrada, y todas aún no se miden aquí.

Ése es el estado de este borrador: el mecanismo es real, la promesa es plausible y las pruebas están pendientes.


Referencias y lecturas adicionales:

  • Li, Z., Kovachki, N., Azizzadenesheli, K., et al. "Operador neuronal de Fourier para ecuaciones diferenciales parciales paramétricas". ICLR 2021. arXiv:2010.08895
  • Lu, L., Jin, P., Pang, G., Zhang, Z. y Karniadakis, GE. "Aprendizaje de operadores no lineales a través de DeepONet". Inteligencia de máquinas naturales, 2021. doi:10.1038/s42256-021-00302-5
  • Li, Z., et al. "Operador neuronal basado en la física para aprender ecuaciones diferenciales parciales". Revista ACM/IMS de ciencia de datos, 2024. OpenReview
  • neuraloperator Biblioteca PyTorch: github.com/neuraloperator/neuraloperator
  • Salvador, M., et al. "Aprendizaje de redes neuronales de la ecuación de Black-Scholes para la fijación de precios de opciones". arXiv:2405.05780
  • Bai, Y., et al. "La IA Black-Scholes: red neuronal basada en finanzas". arXiv:2412.12213
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

Mantente a la vanguardia

Suscríbete a nuestro boletín para recibir información exclusiva sobre trading con IA, análisis de mercado y actualizaciones de la plataforma.

Respetamos tu privacidad. Puedes darte de baja en cualquier momento.