Koopman Operators and DMD: Do Market Modes Survive Out-of-Sample?
يمنحك تحليل الأنماط الديناميكية (DMD) طيفاً: حفنة من القيم الذاتية المركبة، لكل منها معدل نمو وتردد، وكل منها مرتبط بنمط مكاني عبر مجموعة أصولك. يبدو الأمر كأنه بنية. والسؤال كله هو: هل هذه بنية فعلاً، أم أن مؤثراً خطياً يحفظ بأمانة ضوضاء نافذة واحدة؟
لهذا السؤال نصفان قابلان للاختبار، وهذه المقالة مبنية حولهما:
- استمرارية النمط. قم بملاءمة DMD على النافذة وعلى النافذة . هل تمتد الأنماط المهيمنة إلى الفضاء الجزئي نفسه، أم يعاد ترتيبها مع كل إعادة ملاءمة؟ إذا أعيد ترتيبها، فـ DMD تحليل داخل العينة ولا شيء أكثر — والتصريح بذلك بوضوح أنفع من درس تعليمي آخر.
- نصف القطر الطيفي كمؤشر متقدم. أكبر معيار لقيمة ذاتية هو عدد قياسي واحد يلخص مدى انفجار الديناميكيات الملائمة. هل يسبق التقلب المحقق، أم يتأخر عنه، أم يعيد صياغته فحسب؟ كل إجابة قابلة للنشر؛ الأولى وحدها قابلة للتداول.
من المفترض هنا أن الأسواق أنظمة غير مستقرة وغير خطية، ولا تجادل المقالة في ذلك — فقد ناقشته المدونة بالفعل، عبر هندسة فضاء الطور في الجاذبات في التداول الخوارزمي، وعبر إحصاءات BTC المقاسة لكل نظام في اكتشاف الأنظمة باستخدام HMM. وما يلي هو السؤال الأضيق: ماذا يفعل عدم الاستقرار في مؤثر كوبرمان الملائم، وكيف نقيس ذلك؟
1. الفكرة الأساسية: جعل الديناميكيات غير الخطية خطية

لنفترض نظاماً ديناميكياً متقطع الزمن على فضاء حالات :
حيث إن دالة قد تكون غير خطية. في الأسواق، يمثل متجه عوائد الأصول أو تقلباتها أو اختلالات دفتر الأوامر عند الخطوة الزمنية .
يعمل مؤثر كوبرمان ليس على الحالة مباشرة، بل على دوال رصد ذات قيمة قياسية :
الخاصية الأساسية: خطي حتى عندما لا تكون كذلك. والثمن هو الأبعاد — إذ يعمل على فضاء دوال لانهائي الأبعاد. ويمنحك التقريب الجيد محدود الأبعاد قابلية التعبير للديناميكيات غير الخطية مع قابلية التعامل مع الجبر الخطي: يصبح التنبؤ أسّاً لمصفوفة، ويمكن فحص كل نمط بدلاً من دفنه في أوزان شبكة.
2. التحليل الطيفي لمؤثر كوبرمان

إذا كان لـ قيم ذاتية ودوال ذاتية ، فإن ، وأي دالة رصد في امتداد هذه الدوال الذاتية تتحلل كما يلي:
حيث إن هي أنماط كوبرمان — معاملات ذات قيمة متجهية تصف مساهمة كل دالة ذاتية في متجه الرصد الكامل.
كل قيمة ذاتية تشفر معدل نمو أو اضمحلال () وتردد تذبذب ():
| المكوّن | خاصية القيمة الذاتية | التفسير المالي |
|---|---|---|
| الاتجاه | ، | انجراف بطيء، زخم |
| الدورات | ، | تذبذبات، موسمية |
| الانتقالات المؤقتة | صدمات متلاشية، تحركات قصيرة الأجل | |
| الأنماط غير المستقرة | ديناميكيات متنامية وانفجارية |
هذا الجدول هو الوعد. وفي القسم 4 يجري التحقق من الوعد مقابل البيانات.
3. تحليل الأنماط الديناميكية (DMD)

إن DMD هو الخوارزمية العملية لتقريب من البيانات. عند ترتيب اللقطات في مصفوفتين:
يسعى DMD إلى إيجاد مؤثر خطي بأفضل ملاءمة بحيث :
- احسب SVD:
- أسقط:
- حلل القيم الذاتية:
- استعد الأنماط في الفضاء الكامل:
أعمدة هي أنماط DMD؛ وقطر يحتوي على القيم الذاتية لـ DMD.
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
هناك خياران مقصودان هنا. الأنماط مطبّعة وفق L2، لأن القسم 4.2 يقارن الفضاءات الجزئية للأنماط عبر النوافذ، ولأن السعات غير المطبّعة ستطغى على المقارنة. أما السعات فملائمة إلى اللقطة الأخيرة لا الأولى، ما يعني أن التنبؤ لا يرفع قيمة ذاتية إلى قوة كبيرة — وهو مصدر الانفجار العددي الذي يجعل إشارات DMD الساذجة تبدو كأنها ديناميكيات بينما هي في الحقيقة فيض عددي.
4. القياس

هذا هو الجزء غير المدرسي من المقالة. كل ما سبق إجراء ملاءمة؛ وما يلي هو البروتوكول لمعرفة ما إذا كانت الملاءمة تعني شيئاً.
البيانات. استخدم بيانات المنصات الخاصة بالمشروع — مقطعاً عرضياً من BTC وETH والعملات البديلة السائلة على شبكة دقائق أو صفقات متسقة، لا تنزيل يومي لصناديق ETF للأسهم. المدونة تركز على العملات المشفرة، وحجة البنية الدقيقة لا تنتقل إلى الحالة الأخرى. ابنِ بحيث تكون الأصول على الصفوف والزمن على الأعمدة، باستخدام العوائد اللوغاريتمية بعد طرح متوسط كل أصل داخل كل نافذة.
4.1 طيف القيم الذاتية
أبلغ، لنافذة ممثلة، عن عدد القيم الذاتية البالغ عددها الذي يقع ضمن هامش من دائرة الوحدة، وعن فترة التذبذب التي تقابل كل قيمة بالساعات (الفترة من الأشرطة، بعد تحويلها)، وعن نسبة تباين العوائد التي تعيد الأنماط الأولى بناءها.
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)
إن تقريراً طيفياً صادقاً يستحق المقالة بالفعل. إذا لم يقع شيء قرب دائرة الوحدة، فلا توجد دورات مستمرة قابلة للتداول، وقصة "الموسمية السنوية" من أدبيات الأسهم لا تنتقل ببساطة إلى العملات المشفرة التي تعمل على مدار الساعة طوال أيام الأسبوع.
4.2 استقرار الأنماط عبر النوافذ المتجاورة
الاختبار الحاسم. قم بملاءمة DMD على النافذة ثم على النافذة ، وقس مقدار بقاء فضاء الأنماط المهيمنة. الإحصاء الصحيح ليس ارتباطاً ساذجاً لمتجهات الأنماط — فترتيب الأنماط والطور المركب اعتباطيان — بل هو الزوايا الرئيسية بين الفضاءين الجزئيين.
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)])
أبلغ عن توزيع هذا التداخل، وأبلغ عنه مقابل فرضية عدم: الإحصاء نفسه محسوباً على بدائل ذات أطوار عشوائية لنفس العوائد. التداخل المرتفع الذي لا يتجاوز فرضية البدائل يعني أن الأنماط تتتبع بنية التغاير لا الديناميكيات.
4.3 نصف القطر الطيفي المتحرك مقابل التقلب المحقق
الادعاء المطلوب اختباره هو: ، يعاد حسابه على نوافذ متحركة، ويتحرك قبل التقلب المحقق لا معه. هذا العدد القياسي جديد آلياً — فقد راقبت المدونة أعداداً قياسية هندسية في الزمن الحقيقي من قبل، ولا سيما انحناء كوباياشي في متشعبات مركبة للتداول الخوارزمي — لكن معيار قيمة كوبرمان الذاتية كمية مختلفة ذات نمط إخفاق مختلف، ويستحق اختبار السبق والتأخر الخاص به بدلاً من استعارة خطاب قائم.
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))])}
طابق spectral_radius مع التقلب المحقق المحسوب على الشبكة نفسها واقرأ peak_lag. تعني قمة عند الفارق 0 أن مجرد إعادة صياغة للتقلب مع خطوات إضافية. والقمة عند فارق سالب، إذا كانت مستقرة عبر العينة وعبر الرتب، هي النسخة الوحيدة من هذه المقالة التي تحمل ادعاء قابلاً للتداول.
ملاحظة حول ما يأتي بعد نتيجة إيجابية
إذا كان يسبق، فالخطوة التالية الواضحة هي البناء المقطعي: رتّب الأصول حسب العائد المتوقع للخطوة التالية من DMD، وادخل طويلاً في الأصول المتوقعة الفائزة وقصيراً في المتوقعة الخاسرة. هذا البناء ليس جديداً هنا — إنه صفقة بواقي العوامل التي غطتها المدونة بالفعل في المراجحة الإحصائية وتداول الأزواج في العملات المشفرة والقسم 4 من المراجحة المعقدة بالمتجهات والمصفوفات؛ واللمسة الخاصة بكوبرمان حقاً هي أن المحافظ الذاتية تحمل قيماً ذاتية متغيرة زمنياً بدلاً من تحميلات PCA الثابتة.
قسم الاستراتيجية غائب عمداً عن هذه المقالة لأنه لم يُختبر رجعياً هنا مع الرسوم والانزلاق. وعندما يحدث ذلك، يجب أن يجتاز معيار المدونة نفسها: اختبار الدلالة في نسبة شارب المخفّضة والاختبارات المتعددة، مقابل المثال المضاد القائم النتيجة السلبية الصادقة. مخطط طيف DMD ليس نتيجة.
أما التنبؤ بخطوة واحدة نفسه، فالتنفيذ الصحيح يتنبأ من اللقطة الأخيرة بدلاً من نشر قيمة ذاتية إلى قوة طول النافذة:
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. DMD الممتد (EDMD): مشاهدات غير خطية

يعمل DMD القياسي على متجه الحالة الخام. أما EDMD فيرفع البيانات أولاً عبر قاموس من دوال الأساس غير الخطية.
مع قاموس من الدوال القياسية ، عرّف الحالة المرفوعة:
يسعى EDMD إلى إيجاد بحيث . وبحسب الاصطلاح المستخدم في الكود أدناه — الحالات أعمدة، و يعمل من اليسار:
| نوع القاموس | الدوال | ما يلتقطه |
|---|---|---|
| متعدد الحدود | تفاعلات غير خطية بين الأصول | |
| أساس شعاعي (RBF) | تشابه محلي، تجميع الأنظمة | |
| تضمين التأخر الزمني | بنية الذاكرة / الانحدار الذاتي | |
| فورييه | دوريات معروفة (داخل اليوم، أسبوعية) | |
| سمات التقلب | عدم تجانس التباين، تجميع التقلب |
القاموس هو المكان الذي تدخل فيه معرفة المجال، وصف التأخر الزمني هو سبب كوبرمان الخاص للاهتمام بإحداثيات التأخر أصلاً: فهي ليست تقنية منفصلة أضيفت لاحقاً، بل كتلة أخرى من خريطة الرفع. أما التضمين نفسه — اختيار التأخر وبُعد التضمين ونظرية إعادة البناء التي تقف وراءه — فقد قُدم ورُمّز بالفعل في متشعبات مركبة للتداول الخوارزمي؛ خذ متجهات التأخر من هناك وأدخلها مباشرة إلى build_financial_dictionary كصفوف إضافية.
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. شبكات كوبرمان العميقة

قاموس EDMD مصمم يدوياً، وهذا قيد حقيقي عندما يكون الفضاء الجزئي الثابت لكوبرمان مجهولاً. تتعلم شبكات كوبرمان العميقة الرفع والمؤثر معاً.
البنية عبارة عن مشفّر تلقائي — مشفّر، وكود كامن، وفك ترميز، وخسارة إعادة بناء، وكلها قُدمت في اكتشاف الشذوذ في التداول الخوارزمي — مع إضافة هي جوهر هذا القسم كله: خسارة الخطية التي تجبر الديناميكيات الكامنة على المرور عبر مصفوفة متعلمة واحدة .
x_k --> [Encoder φ] --> z_k --> [Linear K] --> z_{k+1} --> [Decoder ψ] --> x̂_{k+1}
| |
+--- Linearity loss: ‖z_{k+1} - K z_k‖ ---+
من دون حد لديك مشفّر تلقائي عادي، يصادف أن فضاءه الكامن يتبعه ضرب مصفوفي. ومعه، تعاقب الشبكة على أي تمثيل كامن لا يكون تطوره خطياً — وهو ما يجعل المتعلم تقريباً لمؤثر كوبرمان، ويجعل قيمه الذاتية قابلة للمقارنة مع طيف DMD في القسم 4.
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 هو ما يجعل تدريب هذا النموذج جديراً بالاهتمام بدلاً من اللجوء إلى نموذج تسلسلي: فالمؤثر المتعلم لا يزال مصفوفة، ولذلك ينطبق اختبار الاستقرار في القسم 4.2 واختبار السبق والتأخر في القسم 4.3 دون تغيير على النموذج العميق.
7. اعتبارات عملية ومزالق

اختيار الرتبة. رتبة القطع هي قرص تحكم في التحيز والتباين — الرتبة المنخفضة جداً تفوّت الديناميكيات، والمرتفعة جداً تلائم الضوضاء. لا تحدق في كوع القيم المفردة؛ فقد أجابت المدونة بالفعل عن "كم مكوّناً قبل أن تلائم الضوضاء؟" بطريقة صحيحة، باستخدام حد مارشينكو-باستور من نظرية المصفوفات العشوائية في المراجحة المعقدة بالمتجهات والمصفوفات. احتفظ بالمكونات التي تتجاوز قيمها المفردة حافة مارشينكو-باستور لشكل نافذتك، واذكر الناتجة صراحة إلى جانب كل طيف تنشره.
طول النافذة. تفترض نظرية كوبرمان أن ثابت؛ لكن الأسواق لا توفر ذلك. إعادة الملاءمة المتحركة إلزامية، ومنحنى الاستقرار في القسم 4.2 هو بالضبط التشخيص لمعرفة ما إذا كانت النافذة المختارة طويلة بما يكفي للتقدير وقصيرة بما يكفي للبقاء داخل نظام واحد.
الحساسية للضوضاء. تتمتع البيانات المالية بنسبة إشارة إلى ضوضاء منخفضة، ويتحيز DMD القياسي بسبب الضوضاء في . تستحق العلاجات التالية التجربة قبل استنتاج أن الأنماط غير مستقرة:
- DMD الكلي (TDMD) — يعامل كلاً من و على أنهما صاخبان باستخدام المربعات الصغرى الكلية.
- DMD المحسّن — يحسّن مباشرة تحليل القيمة الذاتية والنمط مقابل معيار فرُوبينيوس للبواقي.
- EDMD بنواة — يعمل ضمنياً في فضاء سمات عالي الأبعاد دون بناء القاموس.
إذا ارتفع استقرار النمط مادياً مع TDMD، فالسبب هو ضوضاء القياس. وإذا لم يرتفع، فالسبب هو السوق.
8. موضع DMD

| المنهج | الخطية | قابلية التفسير | التنبؤ متعدد الخطوات |
|---|---|---|---|
| DMD | خطي في فضاء الحالة | نعم (الأنماط + القيم الذاتية) | مستقر (قوة المصفوفة) |
| EDMD | خطي في الفضاء المرفوع | نعم، عند توفر القاموس | مستقر (قوة المصفوفة) |
| كوبرمان العميق | خطي في الفضاء المتعلم | متوسطة (فحص K الكامن) | مستقر (قوة المصفوفة) |
بالنسبة للتنبؤ الخاص بالتقلب، فإن نقطة المقارنة هي عائلة GARCH — راجع التنبؤ بتقلب GARCH للعملات المشفرة. وبالنسبة لنماذج السلاسل غير الخطية تماماً ومقايضات قابلية التفسير وتراكم الخطأ التي تحملها، راجع المحوّل الاندماجي الزمني في التداول.
المكان الذي يشغله DMD ضيق لكنه حقيقي: تنبؤات متعددة الخطوات ناتجة من قوة مصفوفة واحدة بدلاً من نشر ذاتي انحداري، مع إمكانية فحص كل نمط. وما إذا كان هذا المكان يحتوي على ألفا هو سؤال القسم 4، لا هذا الجدول.
الخلاصة

نظرية كوبرمان طريقة أنيقة فعلاً للنظر إلى ديناميكيات السوق، والأناقة تحديداً هي سبب حاجتها إلى أقسى اختبار متاح. الخلاصات:
- لاءم DMD ثم اختبر الملاءمة فوراً. يخبرك تداخل الفضاء الجزئي بين النوافذ المتجاورة، مقاساً مقابل فرضية عدم ذات أطوار عشوائية، خلال فترة بعد ظهر واحدة ما إذا كنت وجدت بنية أم حفظت نافذة.
- نصف القطر الطيفي المتحرك هو العدد القياسي الوحيد الذي يستحق المراقبة، وتعتمد قيمته كلياً على نتيجة السبق والتأخر. عند الفارق 0 هو وكيل للتقلب؛ وعند الفارق السالب هو تحذير من النظام.
- ثبّت السعات عند اللقطة الأخيرة ولا ترفع القيم الذاتية أبداً إلى قوة طول النافذة. نسبة كبيرة من "إشارات" DMD المتداولة هي آثار فاصلة عائمة.
- اختر الرتبة باستخدام مارشينكو-باستور، لا بالتحديق في كوع، وانشر الرتبة مع كل طيف.
- مخطط الطيف ليس نتيجة. يجب على أي استراتيجية مبنية على هذا أن تصمد أمام الرسوم والانزلاق واختبار شارب مخفّض قبل أن تُحتسب.
بالنسبة للتطبيقات التي تتجاوز ذلك، تغطي مكتبة PyDMD تنويعات DMD بشكل شامل، ويغطي الكود المرجعي لـ Mallen وآخرين جانب كوبرمان العميق.
ستظل الأسواق فوضوية وغير مستقرة ومشاهداتها جزئية. تقدم نظرية كوبرمان عدسة منهجية لاستخراج البنية من هذه الفوضى — بشرط أن تتحقق من بقاء البنية هناك في الأسبوع المقبل.
المراجع والقراءة الإضافية:
- B. O. Koopman، "الأنظمة الهاملتونية والتحويل في فضاء هيلبرت"، Proceedings of the National Academy of Sciences، 1931.
- J. H. Tu وآخرون، "في تحليل الأنماط الديناميكية: النظرية والتطبيقات"، Journal of Computational Dynamics، 2014.
- M. O. Williams، I. G. Kevrekidis، C. W. Rowley، "تقريب قائم على البيانات لمؤثر كوبرمان: توسيع تحليل الأنماط الديناميكية"، Journal of Nonlinear Science، 2015.
- B. Lusch، J. N. Kutz، S. L. Brunton، "التعلم العميق للتضمينات الخطية العامة للديناميكيات غير الخطية"، Nature Communications، 2018.
- J. Mann وJ. N. Kutz، "تحليل الأنماط الديناميكية لاستراتيجيات التداول المالي"، Quantitative Finance، 2016.
- A. Mallen وآخرون، "متنبئ كوبرمان العصبي للسلاسل الزمنية مع تحولات التوزيع الزمنية"، ICML، 2023.
- E. Gonzalez وM. Generelo، "تحليل النماذج الاقتصادية الفوضوية عبر مؤثرات كوبرمان وEDMD ونظرية تاكنز والتعلم الآلي"، Data Science in Finance and Economics، 2022.
Authors
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.