English Русский 中文 Español 日本語 Português
preview
Neuronale Netze im Trading: Verallgemeinerung von Zeitreihen ohne datenspezifische Abhängigkeit (Mamba4Cast)

Neuronale Netze im Trading: Verallgemeinerung von Zeitreihen ohne datenspezifische Abhängigkeit (Mamba4Cast)

MetaTrader 5Handelssysteme |
11 0
Dmitriy Gizlyk
Dmitriy Gizlyk

Einführung

Der Markt ist sowohl unerbittlich als auch unvorhersehbar. Er bietet denjenigen, die seine Signale falsch deuten, keine zweite Chance. Dies gilt heute besonders, wenn sich Nachrichten schneller verbreiten, als sich eine Kerze auf einem Ein-Minuten-Chart bilden kann. Moderne Trader arbeiten nicht mehr mit der Vergangenheit – sie arbeiten mit dem, was gerade erst aus dem Datenstrom hervorzugehen beginnt. Ein aufkommendes Muster vor allen anderen zu identifizieren, bedeutet, sich einen Wettbewerbsvorteil zu verschaffen. Folglich besteht die Anforderung an heutige Algorithmen darin, Ereignisse vorherzusagen, bevor sie offensichtlich werden, während idealerweise die technische Belastung durch umfangreiche Modellabstimmung und Wartung vermieden wird.

In diesem Wettlauf beginnen traditionelle Modelle, insbesondere rekurrente Architekturen, ihre Grenzen aufzuzeigen. Sie sind sehr gut darin, sich wiederholende Muster zu erkennen und sequentielle Informationen beizubehalten, tun sich jedoch oft schwer mit dem chaotischen Verhalten realer Märkte. Sie haben Schwierigkeiten, kurzfristige Marktimpulse zu erfassen, gehen schlecht mit Lücken und Ausreißern um und erfordern eine Anpassung für jede neue Umgebung. Die heutigen Märkte verlangen nach einer flexibleren und prognosestärkeren Lösung.

Transformer-basierte Architekturen haben die Prognosegenauigkeit erheblich verbessert, insbesondere bei langfristigen Zeitreihenprognosen. Diese gingen jedoch auf Kosten einer erhöhten Rechenkomplexität und eines erhöhten architektonischen Mehraufwands. Da Datensätze größer werden und Prognosehorizonte länger werden, eignen sich diese Modelle zunehmend weniger für Echtzeitanwendungen. In der Praxis bedeutet dies mehr Ressourcen, längere Laufzeiten und eine größere betriebliche Komplexität.

Vor diesem Hintergrund wurde das Mamba4Cast-Framework in der Publikation „Mamba4Cast: Efficient Zero-Shot Time Series Forecasting with State Space Models" vorgestellt. Sein Design basiert auf zwei Schlüsselideen: der leichtgewichtigen und dennoch ausdrucksstarken Mamba-Architektur und dem revolutionären Konzept der Prior-data Fitted Networks (PFNs). Gemeinsam bilden sie die Grundlage für neue Ansätze zur Zeitreihenprognose, insbesondere in hochdynamischen Bereichen wie dem Handel.

Das PFN-Konzept markiert einen grundlegenden Paradigmenwechsel. Im Gegensatz zu herkömmlichen Ansätzen, bei denen ein Modell zuerst auf einem Datensatz vortrainiert und dann auf einem anderen umfassend feinabgestimmt wird, schlagen PFNs vor, das Modell auf einer riesigen Sammlung synthetisch generierter Aufgaben vorzutrainieren. Anstatt aus einem realen Problem zu lernen, lernt das Modell aus Millionen verschiedener – wenn auch unvollkommener – Szenarien. Dies macht es wirklich vielseitig und robust gegenüber neuen Daten. Im Handel bedeutet dies, dass das Modell nicht an ein bestimmtes Finanzinstrument oder einen bestimmten Zeitrahmen gebunden ist; stattdessen kann es sich dynamisch anpassen.

Das Mamba4Cast-Framework setzt die PFN-Philosophie konsequent um. Unter Verwendung synthetisch generierter Daten, die eine Vielzahl von Marktszenarien abdecken, entwickelt es ein breites Verhaltensspektrum. Infolgedessen erhält das Modell etwas, das einer Intuition ähnelt – die Fähigkeit, Muster selbst unter Bedingungen hoher Volatilität und instabiler Dynamik zu verallgemeinern.

Das zweite definierende Merkmal ist die Mamba-Architektur, die eine lineare Rechenkomplexität in Bezug auf die Sequenzlänge aufweist. Im Gegensatz zu Transformern erfordert Mamba keine quadratischen Operationen mit Aufmerksamkeitsmatrizen und kann daher lange Eingabesequenzen effizient und wirtschaftlich verarbeiten. Am wichtigsten für Händler ist, dass Mamba4Cast ein gesamtes Prognosefenster in einem einzigen Durchgang vorhersagt. Dies reduziert drastisch Fehler, die bei autoregressiven Prognosen auftreten, und ermöglicht gleichzeitig schnellere Reaktionen auf sich ändernde Marktbedingungen.

Da das Modell zudem mehrstufige Prognosen erstellt, eignet es sich ideal für den Aufbau von End-to-End-Handelssystemen – von der Signalanalyse bis zur direkten Handelsentscheidung. Mamba4Cast kann nicht nur als Orientierung dienen, sondern auch zum vollwertigen Kern eines Vorhersagemodells in einem automatisierten Handelssystem werden.


Der Mamba4Cast-Framework-Algorithmus

Das Mamba4Cast-Framework stellt einen mutigen und vielversprechenden Schritt nach vorn in der Entwicklung von Zeitreihenprognosesystemen dar. Im Kern liegt eine Kombination aus fundierten mathematischen Grundlagen und flexiblen Deep-Learning-Algorithmen, die in der Lage sind, Märkte als komplexe Ökosysteme zu behandeln, in denen Vergangenheit, Gegenwart und Zukunft miteinander verbunden sind.

Traditionelle Modelle werden typischerweise mit den historischen Daten eines einzelnen Vermögenswerts trainiert und reproduzieren dann die gelernten Beziehungen. Dieser Ansatz lieferte in der Vergangenheit hervorragende Ergebnisse, stößt jedoch heute an Grenzen: Märkte werden dynamischer und Ereignisse unvorhersehbarer. Mamba4Cast verfolgt einen anderen Ansatz: Anstatt spezifische historische Zeitreihen auswendig zu lernen, verwendet es die Methodik der Prior-data Fitted Networks (PFN). Stellen Sie sich vor, Sie trainieren einen Analysten nicht mit echten Kursen einer einzelnen Aktie, sondern mit unzähligen synthetischen Szenarien: Trends, Seitwärtsmärkten, ruhigen Perioden vor großen Volatilitätsspitzen und plötzlichen nachrichtenbedingten Schocks. Auf diese Weise entsteht ein universelles Marktverständnis, das ohne zusätzliche Anpassung sofort für jedes Instrument einsatzbereit ist.

Im Zentrum des Systems steht die Mamba-Architektur, die auf State Space Modeling basiert. Im Gegensatz zu den intensiven Self-Attention-Schichten in Transformern arbeitet Mamba linear entlang der Sequenzlänge, was es ermöglicht, Hunderte oder sogar Tausende Zeitschritte ohne einen exponentiellen Anstieg der Rechenkosten zu verarbeiten. Diese Effizienz beschleunigt nicht nur die Berechnung, sondern ermöglicht auch eine Echtzeit-Marktanalyse, bei der jede Millisekunde zählt. Die resultierende Architektur ist recheneffizient und gut für die Verarbeitung von hochfrequenten Streaming-Daten unter volatilen Marktbedingungen geeignet.

Die erste Stufe führt eine Skalierung der Eingabezeitreihe durch, wobei eine standardmäßige Min-Max-Normalisierung verwendet wird, bei der jeder Wert xt gemäß der folgenden Gleichung transformiert wird:

wobei xmin und xmax über den Bereich im Trainingsdatensatz berechnet werden. Dies beseitigt Skalendiskrepanzen zwischen den Merkmalen und bereitet die Daten für effizientes Lernen vor.

Dann folgt der wichtigste Teil der Vorverarbeitung: die Positionskodierung. Zeitstempel, einschließlich Minute, Stunde, Wochentag, Tag des Monats, Monat und Jahr, werden separat extrahiert und in Vektordarstellungen umgewandelt. Der Algorithmus verwendet ein sinusoidales Kodierungsschema, das dem in Transformer-Architekturen verwendeten ähnelt, jedoch an die periodischen Komponenten von Zeitreihen angepasst ist. Für jede zeitliche Komponente werden mehrere Sinus- und Kosinus-Harmonische unter Verwendung der entsprechenden Periode und Zweierpotenzen berechnet:

wobei T die Periode der entsprechenden Komponente bezeichnet, i den Zeitpunkt darstellt und j der Frequenzindex im Spektrum ist.

Diese Vektoren kodieren zeitliche Abhängigkeiten über mehrere Skalen hinweg, wodurch das Modell in der Lage ist, tägliche Zyklen, saisonale Effekte und makroökonomische Phasen zu erfassen.

Danach werden sie mit den normalisierten Werten der Zeitreihe verkettet. Der resultierende Vektor stellt die Einbettung des Zeitpunkts dar.

Die Sequenz wird dann mithilfe einer Reihe kausaler Faltungsschichten verarbeitet. Mehrere parallele Faltungen mit unterschiedlichen Fenstern ermöglichen die Erfassung verschiedener Zeitskalen. Jede Faltung erfasst Informationen auf bestimmten Ebenen: von lokalen Schwankungen bis hin zu langfristigen Trends. Ihre Ausgaben werden für jeden Zeitschritt zu einer angereicherten Repräsentation zusammengeführt. Dies ist besonders wertvoll für Finanzdaten, bei denen eine einzelne Kerze zugleich einen kurzfristigen Marktimpuls darstellen und Teil eines breiteren Markttrends sein kann.

Als Nächstes wird die Repräsentation in einen höherdimensionalen Raum projiziert, wodurch die Daten vorbereitet werden, um sie in den Hauptblock des Modells einzuspeisen. In dieser Phase wird eine modifizierte Inception-Schicht angeschlossen, die Faltungskerne unterschiedlicher Größe kombiniert und sowohl lokale als auch globale Merkmale integriert. Die resultierende Aktivierung zu jedem Zeitschritt enthält Informationen aus verschiedenen Generalisierungsebenen, während die Ausgabedimensionalität erhalten bleibt und die Robustheit gegenüber fehlenden Werten und Rauschen gewahrt wird.

Der Kern der Architektur besteht aus Mamba-basierten Blöcken, einer innovativen Implementierung von State Space Models (SSMs) mit linearer Komplexität in der Sequenzlänge. Jeder Block implementiert eine verallgemeinerte SSM-Struktur, in der der verdeckte Zustand unter Verwendung der Matrizen A, B, C, D aktualisiert wird, die zusammen mit anderen Modellparametern trainiert werden:

Somit hängt jeder Zeitpunkt sowohl vom vorherigen Zustand als auch von der aktuellen Eingabe ab. Dies sorgt für ein stabiles Langzeitgedächtnis und eine flexible Anpassung an den aktuellen Marktkontext. Auf jeden dieser Blöcke folgt eine Layer Normalization, die Verzerrungen in der Verteilung entfernt und die Aktivierungsverteilung normalisiert, was zu einem stabileren Training führt. Darauf folgt eine zusätzliche kausale Faltungsschicht, die den Informationsfluss entlang der Zeitachse unterstützt.

Die Anzahl solcher Blöcke im Stack kann je nach gewünschter Generalisierungstiefe variieren. Niedrigere Schichten spezialisieren sich auf die Erfassung kurzfristigen Marktverhaltens, wie schnelle Rücksetzer, Momentum und nachrichtenbedingte Schwankungen. Höhere Schichten lernen allmählich breitere Marktzyklen, saisonale Dynamiken und wiederkehrende Formationen. Der Stack fungiert als neuronales Spektrum, wobei jede Schicht für einen bestimmten zeitlichen Frequenzbereich verantwortlich ist.

Die letzte Stufe ist der Decoder. Alle Aktivierungen werden durch eine lineare Schicht in einen oder mehrere Ausgabekanäle projiziert. Wenn eine Unsicherheitsschätzung erforderlich ist, wird ein dedizierter Vorhersagekopf verwendet, um den Logarithmus der Prognosevarianz auszugeben:

Bei Klassifizierungsaufgaben erzeugt ein Softmax-Vorhersagekopf Wahrscheinlichkeiten für die analysierten Klassen.

Eines der bestimmenden Merkmale von Mamba4Cast ist seine Fähigkeit zur Zero-Shot-Generalisierung. Um dies zu erreichen, führen die Autoren eine einzigartige Vortrainingsphase ein, die auf einem umfangreichen synthetischen Datensatz basiert. Dieser Datensatz umfasst Zeitreihen, die aus stochastischen Differentialgleichungen (SDEs), manuell entworfenen Mustern (Umkehrungen, Konsolidierungen und Momentum-Impulse) sowie zufällig generierten Regeln erstellt wurden.

Das Modell wird unter Verwendung mehrerer Verlustfunktionen trainiert: Mean Squared Error (MSE), Negative Log-Likelihood (NLL) und Cross-Entropy-Verlust für die Vorhersage von Regimewechseln. Dies ermöglicht es dem Modell, eine robuste, universelle Sicht auf Marktmuster zu entwickeln, die sich an neue Vermögenswerte und Zeitskalen anpassen kann.

Zusammengenommen machen diese Eigenschaften Mamba4Cast nicht nur zu einem experimentellen Modell, sondern bieten eine praktische Grundlage für den Aufbau prädiktiver Handelssysteme, Algorithmen zur Erkennung von Marktregimen und Lösungen zur Volatilitätsprognose.

Nachfolgend ist die Visualisierung des Mamba4Cast-Frameworks der Autoren dargestellt.


Die Implementierung in MQL5

Nachdem wir die theoretischen Grundlagen der Mamba4Cast-Architektur untersucht haben, wenden wir uns nun der praktischen Seite zu – der Implementierung ihrer Kernkomponenten in MQL5. Unsere erste Aufgabe besteht darin, das Modul für die zeitliche Positionskodierung zu erstellen, ohne das kein modernes Prognosemodell die analysierte Sequenz korrekt als echte zeitliche Abfolge interpretieren kann.

Unsere Bibliothek enthält bereits mehrere konventionelle Implementierungen für Positionskodierungen, die von einfachen sinusförmigen Kodierungen bis hin zu lernbaren Tabellen reichen. Alle behandeln eine Zeitreihe jedoch lediglich als eine geordnete Sequenz von Elementen, ohne die tatsächlichen Zeitstempel zu berücksichtigen, zu denen die Beobachtungen aufgezeichnet wurden. Die Autoren von Mamba4Cast betonen, dass jeder Zeitschritt stattdessen unter Verwendung seines wahren zeitlichen Kontexts kodiert werden sollte: Minute, Stunde, Wochentag, Tag des Monats, Monat und sogar Jahr – all dies beeinflusst die Marktdynamik. Ihrem Ansatz zufolge wird für jede zeitliche Komponente eine unabhängige sinusförmige Zerlegung konstruiert. Unser erster praktischer Block wird sich also dieser tiefen Zeitdarstellung widmen.

Diese Phase bestimmt grundlegend, wie das Modell Zeit wahrnimmt: nicht einfach als eine Abfolge von Kerzen, sondern als einen Strom von Ereignissen zu präzise definierten Zeitpunkten. Ohne eine genaue Darstellung von Zeitstempeln wird selbst der ausgefeilteste Algorithmus bedeutungslos, da Märkte je nach Minute, Stunde oder Tag unterschiedlich reagieren.

Zeitliche Kodierung im OpenCL-Kernel

Anstatt den leistungsstarken, aber umständlichen Ansatz vorberechneter harmonischer Nachschlagetabellen zu verwenden, nutzt unsere Implementierung einen OpenCL-Kernel, um Positionskodierungen direkt aus echten Zeitstempeln in Echtzeit zu berechnen. Dies macht das Speichern großer Sinus- und Kosinustabellen im Speicher überflüssig, vermeidet Stufeneffekte zwischen benachbarten Punkten und vereinfacht die Logik des Expert Advisors erheblich.

Bei diesem Ansatz geht jeder Zeitschritt mit zwei Gruppen von Informationen in den OpenCL-Kernel ein: seinen numerischen Merkmalen (Preis, Volumen, Indikatoren) und seinem Ereignis-Zeitstempel. Der Zeitstempel wird in einen Vektor umgewandelt, der dem Modell genau mitteilt, wann das Ereignis aufgetreten ist: während des Höhepunkts einer Handelssitzung oder in den ruhigen Stunden eines Wochenendes, zu Beginn eines Monats oder am Vorabend eines neuen Jahres.

Die Vorteile dieses Ansatzes sind sofort ersichtlich. Erstens erzeugt er perfekt glatte Positionskodierungen, wodurch sichergestellt wird, dass benachbarte Embeddings ohne künstliche Sprünge kontinuierlich bleiben. Zweitens führt der Wegfall von Nachschlagetabellen zu weniger Code, weniger Synchronisationsproblemen und einem geringeren Speicherverbrauch in der Plattform. Drittens macht die Berechnung in Echtzeit die Einbettung noch relevanter: Es ist nicht erforderlich, Tabellen beim Ändern von Einstellungen oder Zeiträumen neu zu erstellen – ändern Sie einfach die Periodenwerte, und das Modell passt sich sofort an die neuen Anforderungen an.

Der Algorithmus zum Hinzufügen zeitlicher Kodierungen zu analysierten Daten auf der OpenCL-Seite, weist jeder Kerze einen eigenen harmonischen Vektor zu, der ihre Position innerhalb des Zyklus beschreibt, in dem sie gebildet wurde. Der TSPositionEncoder-Kernel erhält Zeiger auf drei Arrays:

  • data mit Eingabewerten,
  • time mit Zeitstempeln,
  • period-Array, das die Dauer jedes Kalenderzyklus definiert.

__kernel void TSPositonEncoder(__global const float2* __attribute__((aligned(8))) data,
                               __global const float* time,
                               __global float2* __attribute__((aligned(8))) output,
                               __global const float* period
                              )
  {
   const int id = get_global_id(0);
   const int freq = get_global_id(1);
   const int p = get_global_id(2);
   const int total = get_global_size(0);
   const int freqs = get_global_size(1);
   const int periods = get_global_size(2);

Der Kernel wird in einem dreidimensionalen Raum ausgeführt:

  • die Länge der analysierten Sequenz (Anzahl der Zeitschritte),
  • die Anzahl der Harmonischen für jede Periode,
  • die Anzahl der Perioden.

Im Hauptteil des Kernels bestimmt jeder Ausführungs-Thread sofort seine Koordinaten über alle drei Dimensionen hinweg.

Zuerst berechnet der Kern für jeden Zeitschritt (Index id) und für jede Harmonische (freq) in der Periode (p) eine Koordinate innerhalb einer Periode: Die Echtzeit wird durch die Zykluslänge geteilt, wodurch der absolute Wert time[id] in die Anzahl der vollen Perioden umgewandelt wird. Der Bruchteil wird mit π und der Zweierpotenz 2^(freq+1) multipliziert. Der resultierende Wert val wird zum Argument der Sinus- und Kosinusfunktionen, wobei die erste Harmonische den gesamten Zyklus abbildet, die zweite ihn halbiert, die dritte viertelt und so weiter.

   const int shift = id * freqs + freq;
   const float2 d = data[shift * periods + p];
   const float t = time[id] / period[p];
   float val = M_PI_F * t * pow(2.0f, freq + 1);

Dieser Wert wird dann zum Quell-Embedding addiert. Jeder OpenCL-Thread lädt das Wertepaar aus data, das dem aktuellen Zeitschritt, der Harmonischen und dem zeitlichen Zyklus entspricht, und addiert sin(val) zum ersten Element und cos(val) zum zweiten. Der resultierende Vektor wird im Output-Puffer gespeichert. Diese Operation bereichert jeden Punkt in der Zeitreihe mit zusätzlichen Merkmalen, die seine Position innerhalb von Kalendermustern präzise kodieren.

   output[shift * periods + p] = (float2)(d.s0 + sin(val), d.s1 + cos(val));
  }

Der Vorteil dieses Ansatzes besteht darin, dass alle Berechnungen in Echtzeit innerhalb des GPU-Kernels durchgeführt werden, wodurch große Nachschlagetabellen oder zusätzliche CPU-seitige Verarbeitung entfallen. Jegliche Änderungen – zum Beispiel das Hinzufügen einer neuen zeitlichen Periode oder die Erhöhung der Anzahl der Harmonischen – erfordern nur Anpassungen der Dimensionen des dreidimensionalen Gitters und Aktualisierungen des period-Arrays. Gleichzeitig bleibt die Repräsentation dank der glatten Natur von Sinus- und Kosinusfunktionen vollkommen kontinuierlich, während die GPU-Parallelität die gleichzeitige Verarbeitung großer Mengen von Beobachtungen ohne Verzögerungen ermöglicht.

Infolgedessen erhält jedes Marktereignis sein eigenes, einzigartiges Embedding, das nicht nur seine numerischen Eigenschaften wie Preis oder Volumen widerspiegelt, sondern auch den genauen Zeitpunkt, zu dem es aufgetreten ist. Dies verleiht Mamba4Cast einen weitaus reichhaltigeren zeitlichen Kontext und macht seinen Prognoseprozess wirklich zeitlich kontextualisiert.

Da die Ereignis-Zeitstempel in unserer Implementierung keine trainierbaren Parameter sind, ist nur der Feed-Forward-Durchlauf erforderlich. Konkret müssen wir nur die Embedding-Vektoren im OpenCL-Kernel berechnen. Es ist nicht erforderlich, Gradienten durch die Zeitstempel zu propagieren oder die Zeitstempel selbst zu aktualisieren. Dies ermöglicht es uns, den Backpropagation-Durchlauf vollständig zu eliminieren, die Architektur zu vereinfachen und die Positionskodierung auf eine rein deterministische Funktion der Zeit zu reduzieren.

Objekt zur zeitlichen Kodierung

Auf der Seite des Hauptprogramms sind die Algorithmen zur zeitlichen Kodierung in der Klasse CNeuronTSPositionEncoder implementiert, deren Struktur unten dargestellt ist.

class CNeuronTSPositionEncoder   :  public CNeuronBaseOCL
  {
protected:
   CNeuronConvOCL             cProjection;
   CNeuronBatchNormOCL        cNorm;
   CBufferFloat               cPeriods;
   //---
   virtual bool               AddPE(CBufferFloat *time);
   //---
   virtual bool               feedForward(CNeuronBaseOCL *NeuronOCL) override { return false; }
   virtual bool               feedForward(CNeuronBaseOCL *NeuronOCL,
                                          CBufferFloat *SecondInput) override;
   virtual bool               updateInputWeights(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool               calcInputGradients(CNeuronBaseOCL *NeuronOCL) override;

public:
                     CNeuronTSPositionEncoder(void) {};
                    ~CNeuronTSPositionEncoder(void) {};
   //---
   virtual bool               Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                                   uint window, uint units_count, uint &periods[], uint freqs,
                                   ENUM_OPTIMIZATION optimization_type, uint batch);
   //---
   virtual int                Type(void) override  const   {  return defNeuronTSPositionEncoder;   }
   //---
   virtual bool               Save(int const file_handle) override;
   virtual bool               Load(int const file_handle) override;
   //---
   virtual bool               WeightsUpdate(CNeuronBaseOCL *source, float tau) override;
   virtual void               SetOpenCL(COpenCLMy *obj) override;
   //---
   virtual uint               GetWindow(void) const { return cProjection.GetWindow(); }
   virtual uint               GetWindowOut(void) const { return cProjection.GetFilters(); }
   virtual uint               GetUnits(void) const { return cProjection.GetUnits(); }
  };

In der dargestellten Struktur fallen sofort drei interne Objekte auf. Auf den ersten Blick mögen sie redundant erscheinen, da die zeitliche Kodierung auf der OpenCL-Seite durchgeführt wird. Diese Komponenten sind jedoch genau dafür verantwortlich, sicherzustellen, dass jede analysierte Datensequenz ordnungsgemäß verpackt und skaliert wird, bevor der zeitliche Kontext hinzugefügt wird.

Zuerst empfängt cProjection beliebige Merkmalsarrays von der vorherigen Schicht des neuronalen Netzwerks und transformiert sie in einheitliche Vektoren mit fester Dimensionalität. Dadurch müssen sich die übrigen Teile des Codes nicht um die Anzahl der Eingabemerkmale und deren interne Organisation kümmern – die Ausgabe von cProjection hat immer eine vorhersehbare Struktur, bereit für Batch-Normalisierung und Positionskodierung.

Zweitens dient cNorm als Stabilitätsmechanismus. In der Praxis können Preise, Volumina und beliebige stochastische Signale über Wertebereiche springen. Wenn Sinus- und Kosinuswerte innerhalb des Bereichs [-1,1] unmittelbar nach der Projektion addiert würden, könnten einige Informationen verloren gehen. Um dies zu verhindern, wird die Ausgabe von cProjection durch eine Batch-Normalisierung geleitet, wodurch der Mittelwert auf null und die Varianz auf eins gebracht wird. Erst danach werden die zeitlichen Harmonischen eingeführt. Diese Reihenfolge stellt sicher, dass zeitliche Merkmale zu einer organischen Erweiterung der verarbeiteten Daten werden, anstatt eine zusätzliche Quelle für unkontrolliertes Rauschen zu sein.

Schließlich speichert cPeriods den festen Satz zeitlicher Zyklusperioden.

Diese Trennung der Verantwortlichkeiten macht die Klasse gleichzeitig flexibel (sie akzeptiert beliebige Eingabedaten), robust (sie bringt Darstellungen immer in eine stabile Form) und präzise, da die zeitliche Kodierung vollständig kontinuierlich bleibt.

Um die Klasse CNeuronTSPositionEncoder von einer deklarativen Struktur in eine vollständig funktionsfähige neuronale Netzwerkkomponente umzuwandeln, müssen alle internen Module korrekt initialisiert werden. Diese Aufgabe wird von der Init-Methode übernommen.

bool CNeuronTSPositionEncoder::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                                    uint window, uint units_count, uint &periods[], uint freqs,
                                    ENUM_OPTIMIZATION optimization_type, uint batch)
  {
   if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, 2 * units_count * freqs * periods.Size(),
                                                                         optimization_type, batch))
      return false;

Die Methode folgt strikt der oben beschriebenen Architekturlogik: Projektion → Normalisierung → Hinzufügen zeitlicher Merkmale.

Im ersten Schritt rufen wir die entsprechende Methode der Elternklasse auf. Sie definiert die allgemeinen Parameter des Objekts. Beachten Sie, dass bei der Angabe der Ausgabetensorgröße das Produkt der übergebenen Parameter mit 2 multipliziert wird. Der Grund dafür ist, dass jede zeitliche Harmonische durch zwei Komponenten dargestellt wird: Sinus und Kosinus.

Als Nächstes wird der Puffer für den zeitlichen Zyklus initialisiert. Die Perioden werden in Sekunden angegeben.

   cPeriods.BufferFree();
   if(!cPeriods.AssignArray(periods) ||
      !cPeriods.BufferCreate(OpenCL))
      return false;

Als Nächstes initialisieren wir die Projektionsschicht der Eingabedaten in einen Raum mit fester Dimension von 2 × Anzahl der Frequenzen × Anzahl der Perioden. Diese Größe entspricht der Anzahl der Kanäle, die die zeitlichen Informationen aufnehmen. Im Wesentlichen konfigurieren wir die Filter, die für die Vorbereitung jedes Segments der Zeitreihe verantwortlich sind, bevor zeitliche Phasen hinzugefügt werden.

   int index = 0;
   if(!cProjection.Init(0, index, OpenCL, window, window, 2 * freqs * cPeriods.Total(), units_count,
                                                                           1, optimization, iBatch))
      return false;
   cProjection.SetActivationFunction(TANH);

Die Verwendung der Aktivierungsfunktion TANH während der Projektionsphase ist nicht nur eine stilistische Wahl, sondern dient dem praktischen Zweck, die Ausgangsamplituden auf den Bereich [-1,1] zu begrenzen. Dies bietet mehrere wichtige Vorteile.

Wenn die ursprünglichen Daten Rauschen, Sprünge oder Extremwerte enthalten, fungiert TANH als weicher Begrenzer, der große Abweichungen glättet und das Verhalten des Modells stabiler macht. Dies ist besonders wichtig für finanzielle Zeitreihen, bei denen unerwartete Kerzen oder Volumenspitzen das Verhalten eines gesamten neuronalen Netzwerks stören können.

Zusätzlich bietet TANH eine glatte Ableitung über den gesamten Eingabebereich, was bei der anschließenden Gradientenfortpflanzung wichtig ist. Dies verringert das Risiko einer Neuronensättigung und trägt zu einer schnelleren und stabileren Konvergenz bei.

Sobald der Projektionsvorgang abgeschlossen ist, wird dessen Ausgabe an cNorm weitergeleitet, wo die Mittelwerte und die Skalierung normiert werden. Dies schützt die zeitlichen Sinus-Cosinus-Signale davor, von übermäßig großen Amplituden überwältigt zu werden, und stellt eine zuverlässige zeitliche Kodierung sicher.

   index++;
   if(!cNorm.Init(0, index, OpenCL, cProjection.Neurons(), iBatch, optimization))
      return false;
   cNorm.SetActivationFunction(None);

Abschließend wird die allgemeine Aktivierungsfunktion deaktiviert, da die zeitliche Kodierung im herkömmlichen Sinne keine trainierbare Komponente ist, und Gradienten einfach von externen Schnittstellen an cNorm weitergeleitet werden.

   SetActivationFunction(None);
   if(!SetGradient(cNorm.getGradient(), true))
      return false;
//---
   return true;
  } 

Kommen wir zur Implementierung des Feed-Forward-Durchlaufs in der Klasse CNeuronTSPositionEncoder; es sollte betont werden, dass diese Stufe den logischen Abschluss des gesamten zeitlichen Kodierungsverfahrens darstellt. Hier werden die projizierten und normalisierten Informationen aus der ursprünglichen Sequenz mit der detaillierten zeitlichen Struktur kombiniert, die durch Harmonische dargestellt wird, welche aus den tatsächlichen Zeitstempeln der eingehenden Daten berechnet wurden.

Die Methode feedForward unterteilt den Prozess sorgfältig in drei aufeinanderfolgende Stufen. Es ist zu beachten, dass die Methode Zeiger auf zwei separate Datenquellen empfängt. Der primäre Informationsstrom enthält die analysierte Sequenz, während der sekundäre Strom die entsprechenden Zeitstempel enthält.

bool CNeuronTSPositionEncoder::feedForward(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput)
  {
   if(!cProjection.FeedForward(NeuronOCL))
      return false;

Zuerst wird der Feed-Forward-Durchlauf der Eingabeprojektionsschicht ausgeführt. In dieser Stufe werden Eingabedaten beliebiger Dimensionalität in die vordefinierte Anzahl von Merkmalen transformiert, wodurch die dimensionale Kompatibilität für das Hinzufügen der erforderlichen Anzahl zeitlicher Harmonischer sichergestellt wird.

Die resultierenden Projektionen werden dann durch die Normalisierungsschicht geleitet.

   if(!cNorm.FeedForward(cProjection.AsObject()))
      return false;

Der Zweck der Normalisierung besteht darin, statistische Unterschiede zwischen den Merkmalen der analysierten Daten zu glätten und sie für die Kombination mit den zeitlichen Harmonischen vorzubereiten.

Schließlich ruft die letzte Stufe die Wrapper-Methode für den zuvor beschriebenen zeitlichen Kodierungskern auf. In Echtzeit berechnet dieser Kernel Sinus-Cosinus-Harmonische für jeden Zeitschritt und jede angegebene Frequenz, basierend auf dem aktuellen Zeitstempelwert und der Menge der Perioden.

   return AddPE(SecondInput);
  }

Dieser Vorgang hängt nicht von trainierbaren Parametern ab und erfordert keine Gradientenpropagation, da die Zeit einen externen deterministischen Faktor darstellt.

Das Ergebnis ist eine reichhaltige Repräsentation, die sowohl aussagekräftige Merkmale der Eingabedaten als auch den präzisen zeitlichen Kontext kombiniert, in dem diese Beobachtungen auftraten – nicht gemäß ihrem sequenziellen Index, sondern gemäß dem tatsächlichen Rhythmus der Ereignisse.

Die Backpropagation-Prozesse in der Klasse CNeuronTSPositionEncoder sind in ihrer Struktur bewusst prägnant und bleiben dabei essenziell. Alle Berechnungen folgen dem Standardansatz, Fehlergradienten zurück zu den ursprünglichen Eingabedaten zu propagieren. Der Hauptberechnungsfluss verläuft durch zwei Schlüsselkomponenten: die Projektionsschicht (cProjection) und die Normalisierungsschicht (cNorm). Jede dieser Komponenten enthält trainierbare Parameter und erfordert daher eine Optimierung.

In der Praxis bedeutet dies, dass unser Objekt bei Aufruf der Methoden updateInputWeights und calcInputGradients die Ausführung einfach sequenziell an die entsprechenden Methoden seiner internen Komponenten delegiert.

Dieser Ansatz gewährleistet Modularität und Wiederholbarkeit der Logik: Änderungen am Optimierungsmechanismus einer einzelnen Schicht pflanzen sich automatisch durch das gesamte System fort, ohne dass Änderungen am Code höherer Ebene erforderlich sind. Dies ist besonders wichtig für skalierbare neuronale Netzwerkarchitekturen.

Ein wichtiger Punkt sollte jedoch hervorgehoben werden. Obwohl die feedForward-Methode zwei Informationsströme empfängt – die primäre Eingabesequenz und das Zeitstempel-Array –, nimmt nur der primäre Informationsstrom an der Backpropagation teil. Dies ist vollkommen gerechtfertigt.

Der Grund dafür ist, dass die zeitliche Kodierung in CNeuronTSPositionEncoder keine trainierbaren Parameter enthält. Sie stellt eine feste, deterministische Transformation dar, die auf Zeitstempel angewendet wird. Darüber hinaus propagieren wir Fehlergradienten absichtlich nicht zurück auf die Zeitstempel-Ebene. Diese Werte sind extern zum Modell und sollten während der Optimierung nicht verändert werden.

Diese Designphilosophie macht die Architektur nicht nur sauber und stabil, sondern auch logisch konsistent: Zeitliche Informationen werden zur Kontextualisierung verwendet, nicht zum Training.

Der vollständige Quellcode dieser Klasse und alle ihre Methoden ist im Anhang enthalten.

Wir haben nun die vernünftigen Grenzen dieses Artikelformats erreicht. Wir haben die grundlegenden Komponenten der zeitlichen Kodierung analysiert, Schlüsselkonzepte implementiert und die Schichtarchitektur im Code in einer klaren und strukturierten Form präsentiert. Wie das Sprichwort jedoch sagt, lässt sich nicht alles auf einmal erledigen.

Unsere Implementierung ist noch nicht abgeschlossen. Es liegt noch ein erhebliches Stück Arbeit vor uns, das einen sorgfältigen und durchdachten Ansatz erfordert. Wir werden eine kurze Pause einlegen und im nächsten Artikel weitermachen.


Schlussfolgerung

In diesem Artikel haben wir das Mamba4Cast-Framework untersucht, das entwickelt wurde, um eine der grundlegenden Herausforderungen der Zeitreihenanalyse zu bewältigen: den Aufbau eines flexiblen und skalierbaren Modells, das in der Lage ist, die komplexe Struktur dynamischer zeitlicher Daten zu erfassen. Wir haben untersucht, wie die Autoren die traditionellen Einschränkungen klassischer Modelle überwunden haben, indem sie moderne Architekturansätze integrierten, einschließlich State Space Models (SSMs), die durch Mechanismen kausaler Faltungsschichten erweitert wurden, und diese durch eine präzise Positionskodierung auf der Grundlage realer Zeitstempel ergänzten.

Während wir die Struktur des Frameworks schrittweise erkundeten, haben wir den Prozess der Konstruktion zeitlicher Merkmale im Detail analysiert. Wir haben gezeigt, wie einfache, aber leistungsstarke harmonische Funktionen unverarbeitete Zeitstempel in aussagekräftige Einbettungen umwandeln können, die die zyklische Natur der Marktdynamik widerspiegeln. Am Beispiel der OpenCL-Implementierung haben wir untersucht, wie solche Einbettungen effizient direkt innerhalb des Rechenkernels generiert werden können, ohne zusätzliche Nachschlagetabellen oder Verarbeitungsverzögerungen.

Unsere Arbeit ist jedoch noch nicht abgeschlossen. Im nächsten Artikel werden wir diese Forschung fortsetzen und zeigen, wie zeitliche Einbettungen mit den Architekturblöcken des Modells interagieren, wobei die Integrität der Analyse gewahrt und die Prognosegenauigkeit verbessert wird.


Referenzen


In diesem Artikel verwendete Programme

# Name Typ Beschreibung
1 Research.mq5 Expert Advisor Expert Advisor für die Datenerfassung
2 ResearchRealORL.mq5
Expert Advisor
Expert Advisor für die Datenerfassung mit der Methode Real-ORL
3 Study.mq5 Expert Advisor Expert Advisor für das Offline-Modelltraining
4 StudyOnline.mq5
Expert Advisor
Expert Advisor für das Online-Modelltraining
4 Test.mq5 Expert Advisor Expert Advisor für Modelltests
5 Trajectory.mqh Klassenbibliothek Struktur der Beschreibung des Systemzustands und der Modellarchitektur
6 NeuroNet.mqh Klassenbibliothek Eine Bibliothek von Klassen zur Erstellung eines neuronalen Netzes
7 NeuroNet.cl Codebibliothek OpenCL-Programmcode

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/18116

Beigefügte Dateien |
MQL5.zip (2754.59 KB)
Die Übertragung der Trading-Signale in einem universalen Expert Advisor. Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
In diesem Artikel wurden die verschiedenen Möglichkeiten beschrieben, um die Trading-Signale von einem Signalmodul des universalen EAs zum Steuermodul der Positionen und Orders zu übertragen. Es wurden die seriellen und parallelen Interfaces betrachtet.
Von der Grundstufe bis zur Mittelstufe: Objektereignisse (IV) Von der Grundstufe bis zur Mittelstufe: Objektereignisse (IV)
In diesem Artikel werden wir das vollenden, was im vorigen begonnen wurde: eine vollständig interaktive Möglichkeit, Objekte direkt im Chart in ihrer Größe zu verändern. Obwohl viele meinen, dass die Erstellung von so etwas wesentlich tiefere MQL5-Kenntnisse erfordern würde, werden Sie sehen, dass wir mit einfachen Konzepten und grundlegendem Wissen eine Möglichkeit implementieren können, direkt im Chart mit Objekten zu arbeiten. Dies führt zu einem sehr interessanten und durchaus überzeugenden Ergebnis.
Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
Neuronale Netze im Trading: Zeitreihenprognose mittels adaptiver Modenzerlegung (Abschließender Teil) Neuronale Netze im Trading: Zeitreihenprognose mittels adaptiver Modenzerlegung (Abschließender Teil)
Der Artikel erörtert die Anpassung und praktische Implementierung des ACEFormer-Frameworks mittels MQL5 im algorithmischen Handel. Er präsentiert wichtige architektonische Entscheidungen, Trainingsmerkmale und Testergebnisse des Modells auf realen Daten.