Modellvalidierung im Strategy Tester

Modelle, die für Operationen auf den Finanzmärkten erstellt wurden, können im MetaTrader 5 Terminal Strategy Tester validiert werden. Dies ist die schnellste und bequemste Option, die eine zusätzliche Emulation der Marktumgebung und der Handelsbedingungen überflüssig macht.

Um das Modell zu testen, erstellen wir einen Expert Advisor, der auf dem Code des öffentlichen Projekts ONNX.Price.Prediction basiert. Dazu sind einige Änderungen erforderlich.

Verschieben Sie die Modellerstellung in die Funktion OnInit und schließen Sie die onnx-Sitzung wieder in OnDeinit. Den Hauptblock der Modelloperationen platzieren Sie in OnTick.

Fügen Sie außerdem den Schlusskurs (close) der beiden vorangegangenen Balken hinzu, der für den Vergleich zwischen dem tatsächlichen Schlusskurs und der Vorhersage benötigt wird.

Der Code des Expert Advisors ist kurz und leicht zu lesen.

 
const long   ExtInputShape [] = {1,10,4}; // Eingangsform des Modells
const long   ExtOutputShape[] = {1,1};    // die Ausgangsform des Modells
#resource "Python/model.onnx" as uchar ExtModel[];// Modell als Resource
 
long handle;         // Handle des Modells
ulong predictions=0// Prognosezähler
ulong confirmed=0;   // Prognosezähler der Erfolge
//+------------------------------------------------------------------+
//| Expert Initialisierungsfunktion                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- basic checks
   if(_Symbol!="EURUSD")
     {
      Print("Symbol must be EURUSD, testing aborted");
      return(-1);
     }
   if(_Period!=PERIOD_H1)
     {
      Print("Timeframe must be H1, testing aborted");
      return(-1);
     }
//--- Modell erstellen
   handle=OnnxCreateFromBuffer(ExtModel,ONNX_DEBUG_LOGS);
//--- Die Form der Eingangsdaten spezifizieren
   if(!OnnxSetInputShape(handle,0,ExtInputShape))
     {
      Print("OnnxSetInputShape failed, error ",GetLastError());
      OnnxRelease(handle);
      return(-1);
     }
//--- Spezifikation der Form der Ausgangsdaten
   if(!OnnxSetOutputShape(handle,0,ExtOutputShape))
     {
      Print("OnnxSetOutputShape failed, error ",GetLastError());
      OnnxRelease(handle);
      return(-1);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Deinitialisierungsfunktion des Experten                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Operation des Modells beenden
   OnnxRelease(handle);
//--- Berechnung und Ausgangs von Prognosestatistiken
   PrintFormat("Successfull predictions = %.2f %%",confirmed*100./double(predictions));
  }
//+------------------------------------------------------------------+
//| Tick-Funktion des Experten                                       |
//+------------------------------------------------------------------+
void OnTick()
  {
   static datetime open_time=0;
   static double predict;
//--- die aktuelle Öffnungszeit des Balkens überprüfen
   datetime time=iTime(_Symbol,_Period,0);
   if(time==0)
     {
      PrintFormat("Failed to get Time(0), error %d"GetLastError());
      return;
     }
//--- wenn sich der Eröffnungszeitpunkt nicht geändert hat, OnTick verlassen
   if(time==open_time)
      return;
//--- die Schlusskurse der letzten beiden geschlossenen Balken ermitteln
   double close[];
   int recieved=CopyClose(_Symbol,_Period,1,2,close);
   if(recieved!=2)
     {
      PrintFormat("CopyClose(2 bars) failed, error %d",GetLastError());
      return;
     }
   double delta_predict=predict-close[0]; // prognostizierte Preisbewegung
   double delta_actual=close[1]-close[0]; // aktuelle Preisänderung
   if((delta_predict>0 && delta_actual>0) || (delta_predict<0 && delta_actual<0))
      confirmed++;
 
//--- den Schlusskurs des neuen Balkens berechnen, um den Kurs des nächsten Balkens zu validieren
   matrix rates;
//--- Abrufen von 10 Balken
   if(!rates.CopyRates("EURUSD",PERIOD_H1,COPY_RATES_OHLC,1,10))
      return;
//--- Eingang einer Reihe von OHLC-Vektoren
   matrix x_norm=rates.Transpose();
   vector m=x_norm.Mean(0);
   vector s=x_norm.Std(0);
   matrix mm(10,4);
   matrix ms(10,4);
//--- die Normalisierungsmatrizen ausfüllen
   for(int i=0i<10i++)
     {
      mm.Row(m,i);
      ms.Row(s,i);
     }
//--- Normalisieren der Eingangsdaten
   x_norm-=mm;
   x_norm/=ms;
//--- konvertieren der normalisierten Eingänge in den Type float
   matrixf x_normf;
   x_normf.Assign(x_norm);
//--- hier die Ausgangsdaten des Modells abrufen, d. h. die Preisvorhersage
   vectorf y_norm(1);
//--- Ausführen des Modells
   if(!OnnxRun(handle,ONNX_DEBUG_LOGS | ONNX_NO_CONVERSION,x_normf,y_norm))
     {
      Print("OnnxRun failed, error ",GetLastError());
     }
//--- eine Rücktransformation durchführen, um den vorhergesagten Preis zu erhalten und ihn bei einem neuen Balken zu validieren
   predict=y_norm[0]*s[3]+m[3];
   predictions++;  // Prognosezähler erhöhen
   Print(predictions,". close prediction = ",predict);
//--- die Öffnungszeit des Balkens speichern, um sie beim nächsten Tick zu überprüfen
   open_time=time;
  }

Kompilieren Sie den Expert Advisor und führen Sie Tests im Zeitraum des Jahres 2022 durch. Geben Sie EURUSD mit dem H1-Zeitrahmen an, also den Daten, auf denen das Modell trainiert wurde. Der Tick-Modellierungsmodus kann ignoriert werden, da der Code das Erscheinen eines neuen Balkens überprüft.  

Backtest-Einstellung

 

Ausführen und das Ergebnis im Journal des Testers überprüfen. Es zeigt, dass etwas mehr als 50% der Vorhersagen im Jahr 2022 richtig waren.

Journal des Testers

 

Wenn die vorläufigen Modelltests zufriedenstellende Ergebnisse erbracht haben, können Sie mit dem Schreiben einer vollwertigen Handelsstrategie auf der Grundlage dieses Modells beginnen.