← Makalelere geri dön
August 12, 2026
5 dakikalık okuma

Koopman Operators and DMD: Do Market Modes Survive Out-of-Sample?

Koopman Operators and DMD: Do Market Modes Survive Out-of-Sample?
#mathematics
#Koopman
#dynamical-systems
#spectral
#prediction

Dinamik Mod Ayrıştırma size bir spektrum sunar: her biri bir büyüme oranına ve frekansa sahip olan ve her biri varlık kesitiniz üzerinde bir mekansal moda bağlı olan bir avuç karmaşık özdeğer. Yapıya benziyor. Bütün soru, bunun bir yapı mı olduğu yoksa bir gürültü penceresini görev bilinciyle ezberleyen doğrusal bir operatör mü olduğudur.

Bu sorunun test edilebilir iki yarısı vardır ve bu makale bunların etrafında oluşturulmuştur:

  1. Mod kalıcılığı. DMD'yi pencereye yerleştirin tt ve pencerede t+1t+1. Baskın modlar aynı altuzayı mı kapsıyor yoksa her yeniden düzenlemede yeniden mi karıştırılıyor? Eğer değişiklik yaparlarsa, DMD örnek içi bir ayrıştırmadır ve başka bir şey değildir - ve bunu açıkça söylemek başka bir eğitimden daha faydalıdır.
  2. Öncü gösterge olarak spektral yarıçap. En büyük özdeğer modülü ρ=maxjλj\rho = \max_j |\lambda_j| takılan dinamiklerin ne kadar patlayıcı olduğunu özetleyen tek bir skalerdir. Gerçekleşmiş oynaklığa öncülük ediyor mu, geciktiriyor mu, yoksa sadece yeniden ifade ediyor mu? Her iki yanıt da yayınlanabilir; yalnızca ilki takas edilebilir.

Piyasaların burada durağan olmayan doğrusal olmayan sistemler olduğu varsayılıyor, tartışılmıyor - blog bunu zaten algotrading'deki çekiciler'deki faz-uzay geometrisi ve HMM'lerle rejim tespiti'de rejim başına ölçülen BTC istatistikleriyle tartışmıştı. Aşağıda, durağan olmamanın uygun bir Koopman operatörüne ne yaptığı ve bunun nasıl ölçüleceğine ilişkin daha dar bir soru yer almaktadır.

1. Temel Fikir: Doğrusal Olmayan Dinamikleri Doğrusallaştırmak

Doğrusal olmayan piyasa hareketi doğrusal gizli akışa dönüşüyor

Durum uzayında ayrık zamanlı bir dinamik sistemi düşünün MRn\mathcal{M} \subseteq \mathbb{R}^n:

xk+1=F(xk)x_{k+1} = F(x_k)

Neresi F:MMF: \mathcal{M} \to \mathcal{M} muhtemelen doğrusal olmayan bir haritadır. Piyasalar için, xkx_k zaman adımındaki varlık getirilerinin, oynaklıkların veya emir defteri dengesizliklerinin bir vektörüdür kk.

Koopman operatörü K\mathcal{K} devlete bağlı olmayan hareketler xx doğrudan, ancak skaler değerli gözlemlenebilir fonksiyonlarda g:MCg: \mathcal{M} \to \mathbb{C}:

[Kg](x)=g(F(x))[\mathcal{K} g](x) = g(F(x))

Anahtar özellik: K\mathcal{K} doğrusaldır, şu durumlarda bile FF değil. Fiyat boyutluluktur — K\mathcal{K} sonsuz boyutlu bir fonksiyon uzayına etki eder. İyi bir sonlu boyutlu yaklaşım, size doğrusal cebirin izlenebilirliğiyle birlikte doğrusal olmayan dinamiklerin ifade gücünü satın alır: tahmin, matris üssü haline gelir ve her mod, ağ ağırlıklarına gömülmek yerine denetlenebilir.

2. Koopman Operatörünün Spektral Ayrışımı

Piyasa dinamiklerinin tutarlı spektral modları

Eğer K\mathcal{K} özdeğerleri var λj\lambda_j ve özfonksiyonlar φj\varphi_j, Daha sonra Kφj=λjφj\mathcal{K} \varphi_j = \lambda_j \varphi_jve gözlemlenebilir herhangi bir gg bu özfonksiyonların aralığında şu şekilde ayrışır:

g(xk)=j=1φj(x0)λjkvjg(x_k) = \sum_{j=1}^{\infty} \varphi_j(x_0) \, \lambda_j^{k} \, v_j

Neresi vjv_j Koopman modları — her bir özfonksiyonun tam gözlemlenebilir vektöre nasıl katkıda bulunduğunu açıklayan vektör değerli katsayılardır.

Her bir özdeğer λj=λjeiωj\lambda_j = |\lambda_j| e^{i\omega_j} bir büyüme veya bozulma oranını kodlar (λj|\lambda_j|) ve bir salınım frekansı (ωj\omega_j):

Bileşen Özdeğer özelliği Finansal yorumlama
Eğilim λ1\lambda \approx 1, ω0\omega \approx 0 Yavaş sürüklenme, momentum
Döngüler λ1\lvert\lambda\rvert \approx 1, ω0\omega \neq 0 Salınımlar, mevsimsellik
Geçiciler λ<1\lvert\lambda\rvert < 1 Çürüyen şoklar, kısa ömürlü hamleler
Kararsız modlar λ>1\lvert\lambda\rvert > 1 Büyüyen, patlayıcı dinamikler

Bu tablo vaattir. Bölüm 4, sözün verilere göre kontrol edildiği yerdir.

3. Dinamik Mod Ayrışımı (DMD)

Dinamik modlar ayrıştırıldı ve yeniden birleştirildi

DMD, yaklaşıklaştırma için güçlü bir algoritmadır K\mathcal{K} verilerden. Matrisler halinde düzenlenmiş anlık görüntüler:

X=[x0x1xm1],X=[x1x2xm]X = \begin{bmatrix} x_0 & x_1 & \cdots & x_{m-1} \end{bmatrix}, \quad X' = \begin{bmatrix} x_1 & x_2 & \cdots & x_m \end{bmatrix}

DMD en uygun doğrusal operatörü arıyor AA ile XAXX' \approx AX:

  1. SVD'yi hesaplayın: X=UΣVX = U \Sigma V^*
  2. Proje: A~=UXVΣ1\tilde{A} = U^* X' V \Sigma^{-1}
  3. Özoluşturma: A~W=WΛ\tilde{A} W = W \Lambda
  4. Tam alan modlarını kurtarın: Φ=XVΣ1W\Phi = X' V \Sigma^{-1} W

Sütunları Φ\Phi DMD modları; köşegeni Λ\Lambda DMD özdeğerlerini tutar.

import numpy as np
from numpy.linalg import svd, eig, lstsq

def dmd(X: np.ndarray, rank: int | None = None) -> tuple:
    """
    Dynamic Mode Decomposition.

    Parameters
    ----------
    X : np.ndarray, shape (n_features, n_snapshots)
        Data matrix where each column is a state snapshot.
    rank : int or None
        Truncation rank for the SVD. None = no truncation.

    Returns
    -------
    eigenvalues : np.ndarray, shape (r,)
        DMD eigenvalues (approximating Koopman eigenvalues).
    modes : np.ndarray, shape (n_features, r)
        DMD modes (columns), L2-normalised.
    amplitudes : np.ndarray, shape (r,)
        Mode amplitudes fitted to the FINAL snapshot, so that a one-step
        forecast is simply modes @ (eigenvalues * amplitudes).
    """
    X0 = X[:, :-1]
    X1 = X[:, 1:]

    U, S, Vh = svd(X0, full_matrices=False)

    if rank is not None:
        U = U[:, :rank]
        S = S[:rank]
        Vh = Vh[:rank, :]

    S_inv = np.diag(1.0 / S)

    A_tilde = U.conj().T @ X1 @ Vh.conj().T @ S_inv
    eigenvalues, W = eig(A_tilde)

    modes = X1 @ Vh.conj().T @ S_inv @ W

    norms = np.linalg.norm(modes, axis=0)
    norms[norms == 0] = 1.0
    modes = modes / norms

    amplitudes = lstsq(modes, X[:, -1].astype(complex), rcond=None)[0]

    return eigenvalues, modes, amplitudes

Burada iki kasıtlı seçim var. Modlar L2-normalize edilmiştir, çünkü bölüm 4.2 pencerelerdeki mod altuzaylarını karşılaştırmaktadır ve normalleştirilmemiş genlikler karşılaştırmayı gölgede bırakacaktır. Genlikler, ilki yerine son anlık görüntüye uyarlanır; bu, bir tahminin hiçbir zaman bir özdeğeri büyük bir güce yükseltmediği anlamına gelir; bu, saf DMD sinyallerinin kayan nokta taşması olduklarında dinamik gibi görünmesini sağlayan sayısal patlamanın kaynağıdır.

4. Ölçüm

Durum-uzay yapısına dönüştürülen gözlemler

Bu makalenin ders kitabı olmayan kısmıdır. Yukarıdaki her şey uygun bir prosedürdür; Aşağıda uygunluğun bir anlam ifade edip etmediğini bulmaya yönelik protokol bulunmaktadır.

Veriler. Hisse senedi ETF'lerinin günlük olarak indirilmesi yerine, tutarlı bir dakika veya işaret tablosu üzerinde BTC, ETH ve likit altcoinlerin bir kesiti olan projenin kendi değişim verilerini kullanın. Blog kripto önceliklidir ve mikro yapı argümanı aktarılmaz. İnşa etmek XX satırlarda varlıklar ve sütunlarda zaman, günlük getirilerinde, her pencerede varlık başına küçültülmüş.

4.1 Özdeğer spektrumu

Temsili bir pencere için rapor: kaç tane rr özdeğerler birim çemberin toleransı dahilinde yer alır; her biri saat cinsinden (periyod) hangi salınım periyoduna karşılık gelir? =2π/ωj= 2\pi / |\omega_j| çubuklar, dönüştürülmüş) ve dönüş varyansının ne kadarı en üstte rr modlar yeniden yapılandırılır.

def spectrum_report(eigenvalues: np.ndarray, bar_minutes: float,
                    tol: float = 0.05) -> list[dict]:
    """
    Turn a DMD spectrum into human-readable rows: modulus, period in hours,
    and whether the eigenvalue sits on the unit circle within `tol`.
    """
    rows = []
    for lam in eigenvalues:
        modulus = float(np.abs(lam))
        omega = float(np.angle(lam))
        period_hours = (2 * np.pi / abs(omega)) * bar_minutes / 60 if omega else np.inf
        rows.append({
            "modulus": modulus,
            "period_hours": period_hours,
            "on_unit_circle": abs(modulus - 1.0) < tol,
            "regime": "unstable" if modulus > 1 + tol
                      else "persistent" if abs(modulus - 1.0) <= tol
                      else "decaying",
        })
    return sorted(rows, key=lambda r: -r["modulus"])


def reconstruction_r2(X: np.ndarray, modes: np.ndarray,
                      eigenvalues: np.ndarray, amplitudes: np.ndarray) -> float:
    """Fraction of in-window return variance captured by the truncated modes."""
    n_steps = X.shape[1]
    powers = eigenvalues[:, None] ** np.arange(-(n_steps - 1), 1)
    X_hat = (modes @ (amplitudes[:, None] * powers)).real
    resid = np.var(X - X_hat)
    return 1.0 - resid / np.var(X)

Dürüst bir spektrum raporu zaten makaleye değer. Birim çemberin yakınında hiçbir şey yoksa, ticaret için kalıcı döngüler yoktur ve hisse senedi literatüründeki "yıllık mevsimsellik" hikayesi, 7/24 kriptoya aktarılmaz.

4.2 Bitişik pencerelerde mod kararlılığı

Belirleyici test. DMD'yi pencereye sığdır tt, ardından pencerede t+1t+1ve baskın mod alt uzayının ne kadarının hayatta kaldığını ölçün. Doğru istatistik, mod vektörlerinin basit bir korelasyonu değil (mod sıralaması ve karmaşık faz keyfidir), iki altuzay arasındaki ana açılardır.

def subspace_stability(modes_a: np.ndarray, modes_b: np.ndarray,
                       k: int = 3) -> float:
    """
    Overlap between the leading-k DMD mode subspaces of two adjacent windows.

    Returns the mean cosine of the principal angles: 1.0 = identical subspace,
    0.0 = orthogonal. Immune to mode reordering and complex phase, both of
    which are arbitrary in a DMD fit.
    """
    Qa, _ = np.linalg.qr(modes_a[:, :k])
    Qb, _ = np.linalg.qr(modes_b[:, :k])
    sing = np.linalg.svd(Qa.conj().T @ Qb, compute_uv=False)
    return float(np.mean(np.clip(sing, 0.0, 1.0)))


def stability_curve(returns: np.ndarray, window: int, step: int,
                    rank: int, k: int = 3) -> np.ndarray:
    """Subspace overlap between every pair of adjacent windows."""
    fits = []
    for t_end in range(window, returns.shape[1], step):
        evals, modes, _ = dmd(returns[:, t_end - window:t_end], rank=rank)
        order = np.argsort(-np.abs(evals))
        fits.append(modes[:, order])
    return np.array([subspace_stability(fits[i], fits[i + 1], k=k)
                     for i in range(len(fits) - 1)])

Bu örtüşmenin dağılımını rapor edin ve bunu boş bir değere göre rapor edin: aynı getirilerin faz-rastgeleleştirilmiş ikameleri üzerinde hesaplanan aynı istatistik. Yüksek olan ancak yedek sıfırdan daha yüksek olmayan örtüşme, modların dinamikleri değil kovaryans yapısını takip ettiği anlamına gelir.

4.3 Gerçekleşen oynaklığa karşı dönen spektral yarıçap

Test etme iddiası: ρt=maxjλj\rho_t = \max_j |\lambda_j|Dönen pencerelerde yeniden hesaplanan , volatilite gerçekleşmeden önce hareket eder. Skaler mekanik olarak yenidir - blog daha önce geometrik skalerleri gerçek zamanlı olarak izlemişti, özellikle de algoritmik ticaret için karmaşık manifoldlar'deki Kobayashi eğriliği - ancak Koopman özdeğer modülü, farklı bir hata moduna sahip farklı bir miktardır ve miras alınan bir adım yerine kendi ön-gecikme testini hak eder.

def rolling_spectral_radius(returns: np.ndarray, window: int = 1440,
                            step: int = 60, rank: int = 5) -> dict:
    """
    Rolling DMD spectrum for regime monitoring.

    returns : np.ndarray, shape (n_assets, n_timesteps)
    window  : rolling window length in bars
    step    : bars between refits
    """
    idx, radii, dom_freq = [], [], []

    for t_end in range(window, returns.shape[1], step):
        X_win = returns[:, t_end - window:t_end]
        try:
            evals, _, _ = dmd(X_win, rank=rank)
        except np.linalg.LinAlgError:
            continue

        idx.append(t_end)
        radii.append(float(np.max(np.abs(evals))))

        on_circle = np.abs(np.abs(evals) - 1.0) < 0.1
        if on_circle.any():
            sel = evals[on_circle]
            dom_freq.append(float(np.abs(np.angle(sel[np.argmax(np.abs(sel))])) / (2 * np.pi)))
        else:
            dom_freq.append(0.0)

    return {"index": np.array(idx),
            "spectral_radius": np.array(radii),
            "dominant_frequency": np.array(dom_freq)}


def lead_lag(signal: np.ndarray, target: np.ndarray, max_lag: int = 24) -> dict:
    """
    Cross-correlation of `signal` against `target` over +/- max_lag steps.
    A peak at negative lag means the signal LEADS the target.
    """
    s = (signal - signal.mean()) / (signal.std() + 1e-12)
    y = (target - target.mean()) / (target.std() + 1e-12)
    lags = np.arange(-max_lag, max_lag + 1)
    corrs = []
    for L in lags:
        if L < 0:
            corrs.append(float(np.corrcoef(s[:L], y[-L:])[0, 1]))
        elif L > 0:
            corrs.append(float(np.corrcoef(s[L:], y[:-L])[0, 1]))
        else:
            corrs.append(float(np.corrcoef(s, y)[0, 1]))
    corrs = np.array(corrs)
    return {"lags": lags, "corr": corrs, "peak_lag": int(lags[np.argmax(np.abs(corrs))])}

Hizala spectral_radius aynı tablo üzerinde hesaplanan ve okunan gerçekleşen volatiliteye peak_lag. 0 gecikmede bir zirve şu anlama gelir: ρt\rho_t ekstra adımlarla volatilitenin yeniden ifade edilmesidir. Örneklem ve sıralamalar arasında istikrarlı olan negatif gecikmedeki zirve, bu makalenin içinde takas edilebilir bir iddia bulunan tek versiyonudur.

Olumlu bir sonuçtan sonra ne olacağına dair bir not

Eğer ρt\rho_t liderlik ediyorsa, bir sonraki bariz hamle kesitsel yapıdır: varlıkları DMD tarafından tahmin edilen bir sonraki adım getirisine göre sıralayın, tahmin edilen kazananlara uzun gidin ve tahmin edilen kaybedenlere kısa tutun. Bu yapı burada yeni değil; faktör-artık ticareti, halihazırda istatistiksel arbitraj ve kriptoda çift ticareti ve vektörler ve matrislerle karmaşık arbitraj bölümünün 4. bölümünde ele alınmıştır; Koopman'a özgü tek gerçek değişiklik, özportföylerin statik PCA yüklemeleri yerine zamanla değişen özdeğerler taşımasıdır.

Strateji bölümü bu makalede kasıtlı olarak yer almamaktadır çünkü burada ücretler ve kaymalar açısından tekrar test edilmemiştir. Öyle olduğunda, blogun kendi çıtasını aşması gerekir: Dürüst negatifin geçerli karşı örneğine karşı Sönük Sharpe Oranı ve çoklu testte anlamlılık testi. DMD spektrum grafiği bir sonuç değildir.

Tek adımlı tahminin kendisi için, doğru uygulama, bir özdeğeri pencere uzunluğunun kuvvetine yaymak yerine son anlık görüntüden tahmin yapar:

def dmd_one_step(returns: np.ndarray, rank: int = 4) -> np.ndarray:
    """
    One-step-ahead prediction from the final snapshot of the window.

    Never raise eigenvalues to the window length: any |lambda| != 1 then
    overflows or underflows and the "signal" becomes numerical garbage.
    """
    evals, modes, amplitudes = dmd(returns, rank=rank)
    return (modes @ (evals * amplitudes)).real

5. Genişletilmiş DMD (EDMD): Doğrusal Olmayan Gözlemlenebilirler

Dinamik modları genişleten doğrusal olmayan özellik alanı

Standart DMD ham durum vektörü üzerinde çalışır. EDMD, verileri öncelikle doğrusal olmayan temel işlevler sözlüğü aracılığıyla kaldırır.

Bir sözlük verildi D={d1,,dp}\mathbf{D} = \{d_1, \ldots, d_p\} skaler fonksiyonların di:RnRd_i: \mathbb{R}^n \to \mathbb{R}, kaldırılmış durumu tanımlayın:

zk=[d1(xk)d2(xk)dp(xk)]Rpz_k = \begin{bmatrix} d_1(x_k) \\ d_2(x_k) \\ \vdots \\ d_p(x_k) \end{bmatrix} \in \mathbb{R}^p

EDMD arıyor KRp×pK \in \mathbb{R}^{p \times p} ile zk+1Kzkz_{k+1} \approx K z_k. Aşağıdaki kodun kullandığı kuralda sütunlar olarak belirtilir, KK sol tarafta hareket ederek:

K=AG1,G=k=0m1zkzkT,A=k=0m1zk+1zkTK = A G^{-1}, \quad G = \sum_{k=0}^{m-1} z_k z_k^{T}, \quad A = \sum_{k=0}^{m-1} z_{k+1} z_k^{T}

Sözlük türü İşlevler Yakalamalar
Polinom xi, xixj, xi2,x_i,\ x_i x_j,\ x_i^2, \ldots Doğrusal olmayan çapraz varlık etkileşimleri
Radyal temel (RBF) exp(γxck2)\exp(-\gamma \lVert x - c_k \rVert^2) Yerel benzerlik, rejim kümelenmesi
Zaman gecikmeli yerleştirme xk, xk1,, xkτx_k,\ x_{k-1}, \ldots,\ x_{k-\tau} Bellek / otoregresif yapı
Fourier sin(2πfjt), cos(2πfjt)\sin(2\pi f_j t),\ \cos(2\pi f_j t) Bilinen periyodiklikler (gün içi, haftalık)
Volatilite özellikleri rt, rt2\lvert r_t \rvert,\ r_t^2 Değişken varyans, hacim kümeleme

Sözlük, alan bilgisinin devreye girdiği yerdir ve zaman gecikmesi satırı, gecikme koordinatlarını önemsemenin Koopman'a özgü nedenidir: bunlar cıvatalanmış ayrı bir teknik değildir, kaldırma haritasının bir bloğu dahadır. Gömmenin kendisi – gecikme seçimi τ\tau, gömme boyutu ddve bunun arkasındaki yeniden yapılandırma teoremi — algoritmik ticaret için karmaşık manifoldlar bölümünde zaten tanıtılmış ve kodlanmıştır; gecikme vektörlerini oradan alın ve doğrudan içine besleyin build_financial_dictionary ekstra satırlar olarak.

import numpy as np
from itertools import combinations_with_replacement

def build_financial_dictionary(X: np.ndarray, max_poly_degree: int = 2,
                               include_volatility: bool = True,
                               delay_steps: int = 0) -> np.ndarray:
    """
    Build a dictionary of nonlinear observables for EDMD.

    X : np.ndarray, shape (n_features, n_snapshots)
    Returns Z of shape (n_dict, n_snapshots - delay_steps).
    """
    n_features, n_snapshots = X.shape
    offset = max(delay_steps, 0)
    X_eff = X[:, offset:]
    n_eff = X_eff.shape[1]

    lifted = [X_eff]  # degree-1 terms (identity)

    if max_poly_degree >= 2:
        for deg in range(2, max_poly_degree + 1):
            for combo in combinations_with_replacement(range(n_features), deg):
                term = np.ones(n_eff)
                for idx in combo:
                    term *= X_eff[idx]
                lifted.append(term.reshape(1, -1))

    if include_volatility:
        lifted.append(np.abs(X_eff))   # absolute returns
        lifted.append(X_eff ** 2)      # squared returns

    for d in range(1, delay_steps + 1):
        lifted.append(X[:, offset - d : n_snapshots - d])

    return np.vstack(lifted)


def edmd(X: np.ndarray, dictionary_fn=None, reg: float = 1e-8,
         **dict_kwargs) -> tuple:
    """
    Extended Dynamic Mode Decomposition.

    Solves Z1 ~= K @ Z0 in the least-squares sense. Uses a least-squares
    solve rather than an explicit Gram inverse: `inv` on a near-singular
    dictionary Gram matrix is how EDMD spectra get silently corrupted.
    """
    if dictionary_fn is None:
        dictionary_fn = lambda x: build_financial_dictionary(x, **dict_kwargs)

    Z = dictionary_fn(X)
    Z0, Z1 = Z[:, :-1], Z[:, 1:]

    p = Z0.shape[0]
    G = Z0 @ Z0.T + reg * np.eye(p)   # regularised Gram matrix
    A = Z1 @ Z0.T

    K = np.linalg.solve(G, A.T).T

    eigenvalues, eigenvectors = np.linalg.eig(K)
    return K, eigenvalues, eigenvectors

6. Derin Koopman Ağları

Derin ağ öğreniminin gizli doğrusal dinamikleri

EDMD sözlüğü el yapımıdır ve bu, Koopman'la değişmez alt uzayın bilinmediği durumlarda gerçek bir sınırlamadır. Deep Koopman ağları kaldırma işlemini ve operatörü birlikte öğrenir.

Mimari bir otomatik kodlayıcıdır (kodlayıcı, gizli kod, kod çözücü, yeniden yapılandırma kaybı, hepsi algotrading'de anormallik tespiti bölümünde tanıtıldığı gibi - bölümün asıl amacı olan bir eklemeyle: gizli dinamikleri tek bir öğrenilmiş matris yoluyla zorlayan bir doğrusallık kaybı KK.

x_k  -->  [Encoder φ]  -->  z_k  -->  [Linear K]  -->  z_{k+1}  -->  [Decoder ψ]  -->  x̂_{k+1}
                              |                            |
                              +--- Linearity loss: ‖z_{k+1} - K z_k‖ ---+

L=xk+1ψ(Kφ(xk))2prediction+αφ(xk+1)Kφ(xk)2linearity+βxkψ(φ(xk))2reconstruction\mathcal{L} = \underbrace{\lVert x_{k+1} - \psi(K \varphi(x_k)) \rVert^2}_{\text{prediction}} + \alpha \underbrace{\lVert \varphi(x_{k+1}) - K \varphi(x_k) \rVert^2}_{\text{linearity}} + \beta \underbrace{\lVert x_k - \psi(\varphi(x_k)) \rVert^2}_{\text{reconstruction}}

olmadan α\alpha terimde, gizli alanını bir matris çarpımı takip eden sıradan bir otomatik kodlayıcınız var. Bununla birlikte ağ, evrimi doğrusal olmayan herhangi bir gizli temsil için cezalandırılır; bu da öğrenilmiş olanı yapar. KK Bölüm 4'teki DMD spektrumuyla karşılaştırılabilir bir Koopman yaklaşımı ve özdeğerleri.

import torch
import torch.nn as nn

class DeepKoopman(nn.Module):
    """Deep Koopman autoencoder: learned lifting + linear latent dynamics."""

    def __init__(self, input_dim: int, latent_dim: int, hidden_dim: int = 128):
        super().__init__()

        self.encoder = nn.Sequential(
            nn.Linear(input_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, latent_dim),
        )
        self.decoder = nn.Sequential(
            nn.Linear(latent_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, input_dim),
        )
        self.K = nn.Linear(latent_dim, latent_dim, bias=False)

    def encode(self, x: torch.Tensor) -> torch.Tensor:
        return self.encoder(x)

    def decode(self, z: torch.Tensor) -> torch.Tensor:
        return self.decoder(z)

    def forward(self, x_k: torch.Tensor) -> dict:
        z_k = self.encode(x_k)
        z_k1_pred = self.K(z_k)
        return {
            "z_k": z_k,
            "z_k1_pred": z_k1_pred,
            "x_k1_pred": self.decode(z_k1_pred),
            "x_k_recon": self.decode(z_k),
        }

    def multi_step_predict(self, x_0: torch.Tensor, n_steps: int) -> torch.Tensor:
        """Roll out by repeated application of the linear operator."""
        z = self.encode(x_0)
        preds = []
        for _ in range(n_steps):
            z = self.K(z)
            preds.append(self.decode(z))
        return torch.stack(preds, dim=1)

    def latent_spectrum(self) -> np.ndarray:
        """Eigenvalues of the learned K — directly comparable to DMD's."""
        return np.linalg.eigvals(self.K.weight.detach().cpu().numpy())


def koopman_loss(model: DeepKoopman, x_k: torch.Tensor, x_k1: torch.Tensor,
                 alpha: float = 1.0, beta: float = 0.5) -> torch.Tensor:
    out = model(x_k)
    z_k1_true = model.encode(x_k1)

    prediction = nn.functional.mse_loss(out["x_k1_pred"], x_k1)
    linearity = nn.functional.mse_loss(out["z_k1_pred"], z_k1_true)
    reconstruction = nn.functional.mse_loss(out["x_k_recon"], x_k)

    return prediction + alpha * linearity + beta * reconstruction

latent_spectrum Bunu bir dizi modeline ulaşmaktan ziyade eğitime değer kılan şey budur: öğrenilen operatör hala bir matristir, dolayısıyla bölüm 4.2 stabilite testi ve bölüm 4.3 ileri-gecikme testi derin bir modele değiştirilmeden uygulanır.

7. Pratik Hususlar ve Tuzaklar

Model sapması ve seyrek gözlemlerde gezinme

Sıra seçimi. Kesme sırası rr önyargılı bir kadrandır - çok düşük dinamikleri kaçırır, çok yüksek gürültüye uyar. Tekil değerli bir dirseğe göz atmayın; blog, vektörler ve matrislerle karmaşık arbitraj'te Rastgele Matris Teorisinden yola çıkan Marchenko-Pastur ile "gürültüyü yerleştirmeden önce kaç bileşen" sorusunu zaten doğru bir şekilde yanıtlıyor. Tekil değerleri Marchenko-Pastur kenarını aşan bileşenleri pencere şekliniz için tutun ve sonucu belirtin. rr yayınladığınız her spektrumun yanında açıkça.

Pencere uzunluğu. Koopman teorisi sabit bir pencere uzunluğunu varsayar FF; Piyasalar bir tane tedarik etmiyor. Sürekli yenilemeler zorunludur ve bölüm 4.2'nin stabilite eğrisi, seçilen pencerenin tahmin için yeterince uzun ve bir rejim içinde kalacak kadar kısa olup olmadığının tam olarak teşhisidir.

Gürültü duyarlılığı. Finansal verilerin sinyal-gürültü oranı düşüktür ve standart DMD, gürültüye karşı önyargılıdır. XX. Modların kararsız olduğu sonucuna varmadan önce denemeye değer çözümler:

  • Toplam DMD (TDMD) — her ikisini de tedavi eder XX Ve XX' toplam en küçük kareler yoluyla gürültülü.
  • Optimize edilmiş DMD — özdeğer modu ayrıştırmasını artık Frobenius normuna göre doğrudan optimize eder.
  • Çekirdek EDMD — sözlüğü oluşturmadan yüksek boyutlu bir özellik alanında örtülü olarak çalışır.

TDMD altında mod kararlılığı önemli ölçüde artarsa, kararsızlık ölçüm gürültüsüdür. Değilse, pazardı.

8. DMD'nin Olduğu Yer

Modelleme yaklaşımları arasında dinamik mod ayrıştırması

Yöntem Doğrusallık Yorumlanabilir Çok adımlı tahmin
DMD Durum uzayında doğrusal Evet (modlar + özdeğerler) Kararlı (matris gücü)
EDMD Kaldırılmış uzayda doğrusal Evet, sözlük göz önüne alındığında Kararlı (matris gücü)
Derin Koopman Öğrenilmiş uzayda doğrusal Orta (gizli K'yi inceleyin) Kararlı (matris gücü)

Volatiliteye özgü tahminler için karşılaştırma noktası GARCH ailesidir — bkz. Kripto için GARCH volatilite tahmini. Tamamen doğrusal olmayan dizi modelleri ve bunların taşıdıkları yorumlanabilirlik ve hata birikimi dengelemeleri için, bkz. Ticaretteki Geçici Füzyon Transformatörü.

DMD'nin kapladığı alan dar ama gerçektir: her modun denetlenebildiği, otoregresif dağıtım yerine tek bir matris gücüyle oluşturulan çok adımlı tahminler. Bu nişin alfa içerip içermediği bu tablonun değil, 4. bölümün sorusudur.

Sonuç

Çalkantılı yörüngeler kararlı modlara dönüşüyor

Koopman teorisi, pazar dinamiklerine bakmanın gerçekten zarif bir yoludur ve zarafet, tam da mevcut en zorlu teste ihtiyaç duymasının nedenidir. Paket servisler:

  1. DMD'yi takın, ardından hemen uyumu test edin. Bitişik pencereler arasındaki altuzay örtüşmesi, faz-rastgeleleştirilmiş bir boşluğa göre ölçülür, size bir öğleden sonra yapıyı mı bulduğunuzu yoksa bir pencereyi ezberleyip ezberlemediğinizi söyler.
  2. Dönme spektral yarıçapı izlenmeye değer tek skalerdir ve değeri tamamen ilerleme-gecikme sonucuna bağlıdır. 0 gecikmesinde bu bir volatilite göstergesidir; negatif gecikmede bu bir rejim uyarısıdır.
  3. Genlikleri son anlık görüntüye sabitleyin ve özdeğerleri hiçbir zaman pencere uzunluğuna yükseltmeyin. Doğadaki DMD "sinyallerinin" büyük bir kısmı kayan nokta yapaylıklarıdır.
  4. Sırayı gözünü dikerek değil, Marchenko-Pastur'a göre seçin ve sıralamayı her spektrumla birlikte yayınlayın.
  5. Bir spektrum grafiği bir sonuç değildir. Bunun üzerine inşa edilen herhangi bir stratejinin, geçerli olmadan önce ücretlerden, kaymalardan ve söndürülmüş bir Sharpe testinden sağ çıkması gerekir.

Bunların ötesindeki uygulamalar için, PyDMD kütüphanesi DMD varyantlarını kapsamlı bir şekilde kapsar ve Mallen ve arkadaşlarının referans kodu derin Koopman tarafını kapsar.

Piyasalar dağınık, durağan olmayan ve kısmen gözlemlenmeye devam edecek. Koopman teorisi, bu karmaşadan yapıyı çıkarmak için ilkeli bir bakış açısı sunuyor; tabii yapının önümüzdeki hafta da orada olup olmadığını kontrol etmeniz şartıyla.


Referanslar ve daha fazla okuma:- B. O. Koopman, "Hamilton Sistemleri ve Hilbert Uzayında Dönüşüm" Ulusal Bilimler Akademisi Bildirileri, 1931.

  • J. H. Tu ve diğerleri, "Dinamik Mod Ayrışımı Üzerine: Teori ve Uygulamalar" Journal of Computational Dynamics, 2014.
  • M. O. Williams, I. G. Kevrekidis, C. W. Rowley, "A Data-Driven Approximation of the Koopman Operator: Extending Dynamic Mode Decomposition" Journal of Nonlinear Science, 2015.
  • B. Lusch, J. N. Kutz, S. L. Brunton, "Doğrusal Olmayan Dinamiklerin Evrensel Doğrusal Yerleştirmeleri için Derin Öğrenme," Nature Communications, 2018.
  • J. Mann ve J. N. Kutz, "Finansal Ticaret Stratejileri için Dinamik Mod Ayrışımı", Kantitatif Finans, 2016.
  • A. Mallen ve diğerleri, "Zamansal Dağılım Kaymaları Olan Zaman Serileri için Koopman Nöral Tahminci" ICML, 2023.
  • E. Gonzalez ve M. Generelo, "Koopman operatörleri, EDMD, Takens teoremi ve Makine Öğrenimi aracılığıyla kaotik ekonomik modellerin analizi", Finans ve Ekonomide Veri Bilimi, 2022.
Sorumluluk Reddi: Bu makalede sağlanan bilgiler yalnızca eğitim ve bilgilendirme amaçlıdır ve finansal, yatırım veya ticaret tavsiyesi niteliği taşımaz. Kripto para ticareti önemli bir kayıp riski içerir.

Yazarlar

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

Piyasanın Önünde Olun

Özel yapay zeka ticaret içgörüleri, piyasa analizi ve platform güncellemeleri için bültenimize abone olun.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.