Praktische Anwendung von neuronalen Netzen im Handel. Python (Teil I)

8 Januar 2021, 08:25
Andrey Dibrov
0
247

Einführung

Im vorherigen Artikel mit dem Titel "Praktische Anwendung von neuronalen Netzen im Handel. Es wird Zeit zum Üben" haben wir die praktische Anwendung eines Moduls für neuronale Netze betrachtet, das mit Matlab neuronale Netze implementiert wurde. In diesem Artikel wurden jedoch keine Fragen behandelt, die mit der Vorbereitung der Eingabedaten und den Operationen im Zusammenhang mit dem Netzwerktraining zusammenhängen. In diesem Artikel werden wir diese Fragen anhand von Beispielen betrachten und weiteren Code unter Verwendung von neuronalen Netzen aus Bibliotheken, die mit Python arbeiten, implementieren. Dieses Mal werden die Prinzipien der Implementierung des Handelssystems anders sein. Diese Variante wurde im Abschnitt 5 des Grundlagenartikels "Praktische Anwendung von neuronalen Netzen im Handel" kurz beschrieben. Für diese Implementierung werden wir die von Google entwickelte TensorFlow-Bibliothek für maschinelles Lernen verwenden. Wir werden auch die Keras-Bibliothek zur Beschreibung neuronaler Netze verwenden.


1. Vorbereitung der Daten

Betrachten wir einige Punkte im Zusammenhang mit der Datenvorbereitung für das Training neuronaler Netzwerke.

  • Für die Entscheidungsfindung werden wir zwei neuronale Netzwerke für die Eröffnung von Positionen in einer Richtung verwenden.
  • Gemäß dem vorherigen Punkt sollten die Trainingsdaten in zwei Gruppen aufgeteilt werden - eine für jede Richtung.
  • Wie im vorherigen System wird das erste neuronale Netzwerk so trainiert, dass es Indikatoren bildet, die den technischen Standardindikatoren ähnlich sind. Wir haben diese Lösung im vorherigen System verwendet, weil wir selbstgeschriebene Indikatoren verwendet haben und den funktionierenden Expert Advisor nicht überlasten wollten. Python wird verwendet, weil nur Kurse vom Terminal empfangen werden können. Um Daten für das neuronale Netzwerk vorzubereiten, müssen wir diese Indikatoren in einem Python-Skript erstellen. Indem wir dem neuronalen Netzwerk beibringen, solche Indikatoren zu erstellen, entfällt die Notwendigkeit, sie im Skript zu duplizieren. 
  • Das zweite neuronale Netzwerk erstellt den Signalindikator, auf dessen Grundlage wir eine Handelsstrategie erstellen.
  • Das neuronale Netzwerk wird für den EURUSD H1-Chart trainiert.
  • Um das System zu erstellen, müssen wir also zwei neuronale Netzwerke für den Kauf und zwei Netzwerke für den Verkauf vorbereiten. Es werden also vier neuronale Netzwerke im System arbeiten.

Zwei Skripte werden für die Vorbereitung der Daten für das Training der Netzwerke verwendet: PythonPrices.mq5 und PythonIndicators.mq5.

//+------------------------------------------------------------------+
//|                                                 PythonPrices.mq5 |
//|                                   Copyright 2020, Andrey Dibrov. |
//|                           https://www.mql5.com/ru/users/tomcat66 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Andrey Dibrov."
#property link      "https://www.mql5.com/ru/users/tomcat66"
#property version   "1.00"
#property strict
#property script_show_inputs

input string Date="2004.07.01 00:00";
input string DateOut="2010.12.31 23:00";
input int History=0;

double inB[22];
string Date1;

int HandleInpuNet1Min;
int HandleInpuNet1Max;

double DibMin1_1[];
double DibMax1_1 [];
int DibMin1_1Handle;
int DibMax1_1Handle;

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   int k=iBars(NULL,PERIOD_H1)-1;

   DibMin1_1Handle=iCustom(NULL,PERIOD_H1,"DibMin1-1",History);
   CopyBuffer(DibMin1_1Handle,0,0,k,DibMin1_1);
   ArraySetAsSeries(DibMin1_1,true);

   DibMax1_1Handle=iCustom(NULL,PERIOD_H1,"DibMax1-1",History);
   CopyBuffer(DibMax1_1Handle,0,0,k,DibMax1_1);
   ArraySetAsSeries(DibMax1_1,true);

   HandleInpuNet1Min=FileOpen(Symbol()+"InputNet1Min.csv",FILE_CSV|FILE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");
   HandleInpuNet1Max=FileOpen(Symbol()+"InputNet1Max.csv",FILE_CSV|FILE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");
   FileSeek(HandleInpuNet1Min,0,SEEK_END);
   FileSeek(HandleInpuNet1Max,0,SEEK_END);

   if(HandleInpuNet1Min>0)
     {
      Alert("Writing to the file InputNet1Min");

      for(int i=iBars(NULL,PERIOD_H1)-1; i>=0; i--)
        {

         Date1=TimeToString(iTime(NULL,PERIOD_H1,i));

         if(DateOut>=Date1 && Date<=Date1)
           {
            if((DibMin1_1[i]==-1 && DibMin1_1[i+1]==1 && DibMax1_1[i]==1) || (DibMin1_1[i]==1 && DibMax1_1[i]==1))
              {
               for(int m=0; m<=14; m++)
                 {
                  inB[m]=inB[m+5];
                 }

               inB[15]=(iOpen(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iLow(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*100000;
               inB[16]=(iHigh(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iOpen(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*100000;
               inB[17]=(iHigh(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iLow(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*10000;
               inB[18]=(iHigh(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iOpen(NULL,PERIOD_H1,i+1))*10000;
               inB[19]=(iOpen(NULL,PERIOD_H1,i+1)-iLow(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*10000;

               inB[20]=(iHigh(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iOpen(NULL,PERIOD_H1,i))*10000;
               inB[21]=(iOpen(NULL,PERIOD_H1,i)-iLow(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*10000;

               FileWrite(HandleInpuNet1Min,

                         inB[0],inB[1],inB[2],inB[3],inB[4],inB[5],inB[6],inB[7],inB[8],inB[9],inB[10],inB[11],inB[12],inB[13],inB[14],inB[15],
                         inB[16],inB[17],inB[18],inB[19],inB[20],inB[21]);
              }
           }
        }

      FileClose(HandleInpuNet1Min);
     }
//------------------------------------------------------------------------------------------------------------------------------------------------

   if(HandleInpuNet1Max>0)
     {
      Alert("Writing the file InputNet1Max");

      for(int i=iBars(NULL,PERIOD_H1)-1; i>=0; i--)
        {

         Date1=TimeToString(iTime(NULL,PERIOD_H1,i));

         if(DateOut>=Date1 && Date<=Date1)
           {
            if((DibMax1_1[i]==-1 && DibMax1_1[i+1]==1 && DibMin1_1[i]==1)|| (DibMin1_1[i]==1 && DibMax1_1[i]==1))
              {
               for(int m=0; m<=14; m++)
                 {
                  inB[m]=inB[m+5];
                 }

               inB[15]=(iOpen(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iLow(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*100000;
               inB[16]=(iHigh(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iOpen(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*100000;
               inB[17]=(iHigh(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iLow(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*10000;
               inB[18]=(iHigh(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iOpen(NULL,PERIOD_H1,i+1))*10000;
               inB[19]=(iOpen(NULL,PERIOD_H1,i+1)-iLow(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*10000;

               inB[20]=(iHigh(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iOpen(NULL,PERIOD_H1,i))*10000;
               inB[21]=(iOpen(NULL,PERIOD_H1,i)-iLow(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*10000;

               FileWrite(HandleInpuNet1Max,

                         inB[0],inB[1],inB[2],inB[3],inB[4],inB[5],inB[6],inB[7],inB[8],inB[9],inB[10],inB[11],inB[12],inB[13],inB[14],inB[15],
                         inB[16],inB[17],inB[18],inB[19],inB[20],inB[21]);
              }
           }
        }

      FileClose(HandleInpuNet1Max);
     }
   Alert("Files written");

  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                             PythonIndicators.mq5 |
//|                                   Copyright 2020, Andrey Dibrov. |
//|                           https://www.mql5.com/ru/users/tomcat66 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Andrey Dibrov."
#property link      "https://www.mql5.com/ru/users/tomcat66"
#property version   "1.00"
#property strict
#property script_show_inputs

input string Date="2004.07.01 00:00";
input string DateOut="2010.12.31 23:00";
input int History=0;

double Stochastic0[];
double Stochastic1[];
double CCI_Open[];
double CCI_Low[];
double CCI_High[];
double Momentum_Open[];
double Momentum_Low[];
double Momentum_High[];
double RSI_Open[];
double RSI_Low[];
double RSI_High[];
double WPR[];
double MACD_Open[];
double MACD_Low[];
double MACD_High[];
double OsMA_Open[];
double OsMA_Low[];
double OsMA_High[];
double TriX_Open[];
double TriX_Low[];
double TriX_High[];
double BearsPower[];
double BullsPower[];
double ADX_MINUSDI[];
double ADX_PLUSDI[];
double StdDev_Open[];
double StdDev_Low[];
double StdDev_High[];

//--------------------------
double DibMin1_1[];
double DibMax1_1 [];

int DibMin1_1Handle;
int DibMax1_1Handle;
//--------------------------
double inB[60];
double inS[60];

string Date1;

int HandleInputNet2OutNet1Min;
int HandleOutNet2Min;
int HandleInputNet2OutNet1Max;
int HandleOutNet2Max;

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   int k=iBars(NULL,PERIOD_H1)-1;

//------ Daily Low

   DibMin1_1Handle=iCustom(NULL,PERIOD_H1,"DibMin1-1",History);
   CopyBuffer(DibMin1_1Handle,0,0,k,DibMin1_1);
   ArraySetAsSeries(DibMin1_1,true);

   DibMax1_1Handle=iCustom(NULL,PERIOD_H1,"DibMax1-1",History);
   CopyBuffer(DibMax1_1Handle,0,0,k,DibMax1_1);
   ArraySetAsSeries(DibMax1_1,true);

   int Stochastic_handle=iStochastic(NULL,PERIOD_H1,5,3,3,MODE_SMA,STO_LOWHIGH);
   CopyBuffer(Stochastic_handle,0,0,k,Stochastic0);
   CopyBuffer(Stochastic_handle,1,0,k,Stochastic1);
   ArraySetAsSeries(Stochastic0,true);
   ArraySetAsSeries(Stochastic1,true);

   int CCI_Open_handle=iCCI(NULL,PERIOD_H1,14,PRICE_OPEN);
   CopyBuffer(CCI_Open_handle,0,0,k,CCI_Open);
   ArraySetAsSeries(CCI_Open,true);

   int CCI_Low_handle=iCCI(NULL,PERIOD_H1,14,PRICE_LOW);
   CopyBuffer(CCI_Low_handle,0,0,k,CCI_Low);
   ArraySetAsSeries(CCI_Low,true);

   int Momentum_Open_handle=iMomentum(NULL,PERIOD_H1,14,PRICE_OPEN);
   CopyBuffer(Momentum_Open_handle,0,0,k,Momentum_Open);
   ArraySetAsSeries(Momentum_Open,true);

   int Momentum_Low_handle=iMomentum(NULL,PERIOD_H1,14,PRICE_LOW);
   CopyBuffer(Momentum_Low_handle,0,0,k,Momentum_Low);
   ArraySetAsSeries(Momentum_Low,true);

   int RSI_Open_handle=iRSI(NULL,PERIOD_H1,14,PRICE_OPEN);
   CopyBuffer(RSI_Open_handle,0,0,k,RSI_Open);
   ArraySetAsSeries(RSI_Open,true);

   int RSI_Low_handle=iRSI(NULL,PERIOD_H1,14,PRICE_LOW);
   CopyBuffer(RSI_Low_handle,0,0,k,RSI_Low);
   ArraySetAsSeries(RSI_Low,true);

   int WPR_handle=iWPR(NULL,PERIOD_H1,14);
   CopyBuffer(WPR_handle,0,0,k,WPR);
   ArraySetAsSeries(WPR,true);

   int MACD_Open_handle=iMACD(NULL,PERIOD_H1,12,26,9,PRICE_OPEN);
   CopyBuffer(MACD_Open_handle,0,0,k,MACD_Open);
   ArraySetAsSeries(MACD_Open,true);

   int MACD_Low_handle=iMACD(NULL,PERIOD_H1,12,26,9,PRICE_LOW);
   CopyBuffer(MACD_Low_handle,0,0,k,MACD_Low);
   ArraySetAsSeries(MACD_Low,true);

   int OsMA_Open_handle=iOsMA(NULL,PERIOD_H1,12,26,9,PRICE_OPEN);
   CopyBuffer(OsMA_Open_handle,0,0,k,OsMA_Open);
   ArraySetAsSeries(OsMA_Open,true);

   int OsMA_Low_handle=iOsMA(NULL,PERIOD_H1,12,26,9,PRICE_LOW);
   CopyBuffer(OsMA_Low_handle,0,0,k,OsMA_Low);
   ArraySetAsSeries(OsMA_Low,true);

   int TriX_Open_handle=iTriX(NULL,PERIOD_H1,14,PRICE_OPEN);
   CopyBuffer(TriX_Open_handle,0,0,k,TriX_Open);
   ArraySetAsSeries(TriX_Open,true);

   int TriX_Low_handle=iTriX(NULL,PERIOD_H1,14,PRICE_LOW);
   CopyBuffer(TriX_Low_handle,0,0,k,TriX_Low);
   ArraySetAsSeries(TriX_Low,true);

   int BearsPower_handle=iBearsPower(NULL,PERIOD_H1,13);
   CopyBuffer(BearsPower_handle,0,0,k,BearsPower);
   ArraySetAsSeries(BearsPower,true);

   int ADX_MINUSDI_handle=iADX(NULL,PERIOD_H1,14);
   CopyBuffer(ADX_MINUSDI_handle,2,0,k,ADX_MINUSDI);
   ArraySetAsSeries(ADX_MINUSDI,true);

   int StdDev_Open_handle=iStdDev(NULL,PERIOD_H1,20,0,MODE_SMA,PRICE_OPEN);
   CopyBuffer(StdDev_Open_handle,0,0,k,StdDev_Open);
   ArraySetAsSeries(StdDev_Open,true);

   int StdDev_Low_handle=iStdDev(NULL,PERIOD_H1,20,0,MODE_SMA,PRICE_LOW);
   CopyBuffer(StdDev_Low_handle,0,0,k,StdDev_Low);
   ArraySetAsSeries(StdDev_Low,true);
//---------------------------------------------------------------------------------------------------------------------------

   HandleInputNet2OutNet1Min=FileOpen(Symbol()+"InputNet2OutNet1Min.csv",FILE_CSV|FILE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");
   HandleOutNet2Min=FileOpen(Symbol()+"OutNet2Min.csv",FILE_CSV|FILE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");
   FileSeek(HandleInputNet2OutNet1Min,0,SEEK_END);
   FileSeek(HandleOutNet2Min,0,SEEK_END);

   if(HandleInputNet2OutNet1Min>0)
     {
      Alert("Writing the files InputNet2OutNet1Min and OutNet2Min");

      for(int i=iBars(NULL,PERIOD_H1)-1; i>=0; i--)
        {
         Date1=TimeToString(iTime(NULL,PERIOD_H1,i));

         if(DateOut>=Date1 && Date<=Date1)
           {
            if(((DibMin1_1[i]==-1 && DibMin1_1[i+1]==1 && DibMax1_1[i]==1)) || (DibMin1_1[i]==1 && DibMax1_1[i]==1))

              {
               for(int m=0; m<=35; m++)
                 {
                  inB[m]=inB[m+12];
                 }

               inB[36]=Stochastic0[i];
               inB[37]=Stochastic1[i];
               inB[38]=CCI_Low[i];
               inB[39]=Momentum_Low[i];
               inB[40]=RSI_Low[i];;
               inB[41]=WPR[i+1];
               inB[42]=MACD_Low[i]*10000;
               inB[43]=OsMA_Low[i]*100000;
               inB[44]=TriX_Low[i]*100000;;
               inB[45]=BearsPower[i+1]*1000;
               inB[46]=ADX_MINUSDI[i+1];
               inB[47]=StdDev_Low[i]*10000;

               inB[48]=Stochastic0[i];
               inB[49]=Stochastic1[i];
               inB[50]=CCI_Open[i];
               inB[51]=Momentum_Open[i];
               inB[52]=RSI_Open[i];;
               inB[53]=WPR[i];
               inB[54]=MACD_Open[i]*10000;
               inB[55]=OsMA_Open[i]*100000;
               inB[56]=TriX_Open[i]*100000;;
               inB[57]=BearsPower[i]*1000;
               inB[58]=ADX_MINUSDI[i];
               inB[59]=StdDev_Open[i]*10000;

               FileWrite(HandleInputNet2OutNet1Min,
                         inB[0],inB[1],inB[2],inB[3],inB[4],inB[5],inB[6],inB[7],inB[8],inB[9],inB[10],inB[11],inB[12],inB[13],
                         inB[14],inB[15],inB[16],inB[17],inB[18],inB[19],inB[20],inB[21],inB[22],inB[23],inB[24],inB[25],inB[26],
                         inB[27],inB[28],inB[29],inB[30],inB[31],inB[32],inB[33],inB[34],inB[35],inB[36],inB[37],inB[38],inB[39],
                         inB[40],inB[41],inB[42],inB[43],inB[44],inB[45],inB[46],inB[47],inB[48],inB[49],inB[50],inB[51],inB[52],
                         inB[53],inB[54],inB[55],inB[56],inB[57],inB[58],inB[59]);

               FileWrite(HandleOutNet2Min,
                         (iOpen(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)))-iOpen(NULL,PERIOD_H1,i))*10000);
              }
           }
        }
     }

   //------ Daily High

   int CCI_High_handle=iCCI(NULL,PERIOD_H1,14,PRICE_HIGH);
   CopyBuffer(CCI_High_handle,0,0,k,CCI_High);
   ArraySetAsSeries(CCI_High,true);

   int Momentum_High_handle=iMomentum(NULL,PERIOD_H1,14,PRICE_HIGH);
   CopyBuffer(Momentum_High_handle,0,0,k,Momentum_High);
   ArraySetAsSeries(Momentum_High,true);

   int RSI_High_handle=iRSI(NULL,PERIOD_H1,14,PRICE_HIGH);
   CopyBuffer(RSI_High_handle,0,0,k,RSI_High);
   ArraySetAsSeries(RSI_High,true);

   int MACD_High_handle=iMACD(NULL,PERIOD_H1,12,26,9,PRICE_HIGH);
   CopyBuffer(MACD_High_handle,0,0,k,MACD_High);
   ArraySetAsSeries(MACD_High,true);

   int OsMA_High_handle=iOsMA(NULL,PERIOD_H1,12,26,9,PRICE_HIGH);
   CopyBuffer(OsMA_High_handle,0,0,k,OsMA_High);
   ArraySetAsSeries(OsMA_High,true);

   int TriX_High_handle=iTriX(NULL,PERIOD_H1,14,PRICE_HIGH);
   CopyBuffer(TriX_High_handle,0,0,k,TriX_High);
   ArraySetAsSeries(TriX_High,true);

   int BullsPower_handle=iBullsPower(NULL,PERIOD_H1,13);
   CopyBuffer(BullsPower_handle,0,0,k,BullsPower);
   ArraySetAsSeries(BullsPower,true);

   int ADX_PLUSDI_handle=iADX(NULL,PERIOD_H1,14);
   CopyBuffer(ADX_PLUSDI_handle,1,0,k,ADX_PLUSDI);
   ArraySetAsSeries(ADX_PLUSDI,true);

   int StdDev_High_handle=iStdDev(NULL,PERIOD_H1,20,0,MODE_SMA,PRICE_HIGH);
   CopyBuffer(StdDev_High_handle,0,0,k,StdDev_High);
   ArraySetAsSeries(StdDev_High,true);
//---------------------------------------------------------------------------------------------------------------------------

   HandleInputNet2OutNet1Max=FileOpen(Symbol()+"InputNet2OutNet1Max.csv",FILE_CSV|FILE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");
   HandleOutNet2Max=FileOpen(Symbol()+"OutNet2Max.csv",FILE_CSV|FILE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");
   FileSeek(HandleInputNet2OutNet1Max,0,SEEK_END);
   FileSeek(HandleOutNet2Max,0,SEEK_END);

   if(HandleInputNet2OutNet1Max>0)
     {
      Alert("Writing the files InputNet2OutNet1Max and OutNet2Max");

      for(int i=iBars(NULL,PERIOD_H1)-1; i>=0; i--)
        {
         Date1=TimeToString(iTime(NULL,PERIOD_H1,i));

         if(DateOut>=Date1 && Date<=Date1)
           {
            if(((DibMax1_1[i]==-1 && DibMax1_1[i+1]==1 && DibMin1_1[i]==1)) || (DibMin1_1[i]==1 && DibMax1_1[i]==1))

              {
               for(int m=0; m<=35; m++)
                 {
                  inS[m]=inS[m+12];
                 }

               inS[36]=Stochastic0[i];
               inS[37]=Stochastic1[i];
               inS[38]=CCI_High[i];
               inS[39]=Momentum_High[i];
               inS[40]=RSI_High[i];;
               inS[41]=WPR[i+1];
               inS[42]=MACD_High[i]*10000;
               inS[43]=OsMA_High[i]*100000;
               inS[44]=TriX_High[i]*100000;;
               inS[45]=BullsPower[i+1]*1000;
               inS[46]=ADX_PLUSDI[i+1];
               inS[47]=StdDev_High[i]*10000;

               inS[48]=Stochastic0[i];
               inS[49]=Stochastic1[i];
               inS[50]=CCI_Open[i];
               inS[51]=Momentum_Open[i];
               inS[52]=RSI_Open[i];;
               inS[53]=WPR[i];
               inS[54]=MACD_Open[i]*10000;
               inS[55]=OsMA_Open[i]*100000;
               inS[56]=TriX_Open[i]*100000;;
               inS[57]=BullsPower[i]*1000;
               inS[58]=ADX_PLUSDI[i];
               inS[59]=StdDev_Open[i]*10000;

               FileWrite(HandleInputNet2OutNet1Max,
                         inS[0],inS[1],inS[2],inS[3],inS[4],inS[5],inS[6],inS[7],inS[8],inS[9],inS[10],inS[11],inS[12],inS[13],
                         inS[14],inS[15],inS[16],inS[17],inS[18],inS[19],inS[20],inS[21],inS[22],inS[23],inS[24],inS[25],inS[26],
                         inS[27],inS[28],inS[29],inS[30],inS[31],inS[32],inS[33],inS[34],inS[35],inS[36],inS[37],inS[38],inS[39],
                         inS[40],inS[41],inS[42],inS[43],inS[44],inS[45],inS[46],inS[47],inS[48],inS[49],inS[50],inS[51],inS[52],
                         inS[53],inS[54],inS[55],inS[56],inS[57],inS[58],inS[59]);

               FileWrite(HandleOutNet2Max,
                         (iOpen(NULL,PERIOD_H1,i)-iOpen(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i))))*10000);
              }
           }
        }
     }

   Alert("Files written");
  }
//+------------------------------------------------------------------+

Eine Stichprobe reicht vom Beginn des Arbeitstages bis zum ersten Erreichen des Tagestiefs. Die zweite Stichprobe endet beim ersten Erreichen des Tageshochs. Zu diesem Zweck werden zwei Indikatoren in Skripten verwendet: DibMin1-1.mq5 und DibMax1-1.mq5

//+------------------------------------------------------------------+
//|                                                    DibMin1-1.mq5 |
//|                                   Copyright 2020, Andrey Dibrov. |
//|                           https://www.mql5.com/ru/users/tomcat66 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Andrey Dibrov."
#property link      "https://www.mql5.com/ru/users/tomcat66"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_minimum -2
#property indicator_maximum 2
#property indicator_color1 Red
#property indicator_label1  "DibMin1-1"
//---- input parameters
input int History=500;
double Buf[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Buf,INDICATOR_DATA);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int    i,z,Calc;
   double price;

   i=iBars(NULL,PERIOD_H1)-1;
   if(i>History-1)
      i=History-1;
   if(History==0)
      i=iBars(NULL,PERIOD_H1)-1;
   ArraySetAsSeries(Buf,true);
   ArraySetAsSeries(time,true);

   while(i>=0)
     {
      int min=0;
      Calc=(int)time[i]%86400/3600;
      double min1=iLow(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)));
      for(z=0;z<=Calc;z++)
        {
          price=iLow(NULL,PERIOD_H1,i+z);
          if(min1<price)
          {
           min=1;
          }else
          {
           min=-1;
          break;
          }
         }
      Buf[i]=min;
      i--;
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                                    DibMax1-1.mq5 |
//|                                   Copyright 2020, Andrey Dibrov. |
//|                           https://www.mql5.com/ru/users/tomcat66 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Andrey Dibrov."
#property link      "https://www.mql5.com/ru/users/tomcat66"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE 
#property indicator_minimum -2
#property indicator_maximum 2
#property indicator_color1 LightSeaGreen
#property indicator_label1  "DibMax1-1"
//---- input parameters
input int History=500;
double Buf[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Buf,INDICATOR_DATA);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int    i,z,Calc;
   double price;
   
   i=iBars(NULL,PERIOD_H1)-1;
   if (i>History-1)i=History-1;
   if (History==0) i=iBars(NULL,PERIOD_H1)-1;
   ArraySetAsSeries(Buf,true);
   ArraySetAsSeries(time,true);
   
   while(i>=0)
     {
      int max=0;
      Calc=(int)time[i]%86400/3600;
      double max1=iHigh(NULL,PERIOD_D1,iBarShift(NULL,PERIOD_D1,iTime(NULL,PERIOD_H1,i)));
      for(z=0;z<=Calc;z++)
        {
          price=iHigh(NULL,PERIOD_H1,i+z);//+1-1
          if(max1>price)
          {
           max=1;
          }else
          {
           max=-1;
           break;
          }
         }   
      Buf[i]=max;
      i--;
      } 
   return(rates_total);
  }
//+------------------------------------------------------------------+

Beispielindikatoren

Wenn der Preis tägliche Extremwerte erreicht, werden die Indikatorwerte auf -1 gesetzt.

Nach der Ausführung der Skripte auf dem EURUSD H1-Chart werden sechs CSV-Dateien im Ordner \Common\Files erstellt.

  • EURUSDInputNet1Max und EURUSDInputNet1Min sind Dateien mit Preisdaten. Aus dem Dateinamen ist ersichtlich, dass z. B. EURUSDInputNet1Max die Eingabedaten für die neuronalen Netze Net1Max enthält.
  • EURUSDInputNet2OutNet1Max und EURUSDInputNet2OutNet1Min sind die Dateien mit Indikatorwerten. Diese Werte werden Eingänge für Net2 und Ausgänge für Net1 sein. Bitte beachten Sie, dass dieser Teil etwas Experimentierfreude erfordert: Net2 kann mit technischen Standardindikatoren oder mit den Antworten von Net1 trainiert werden.
  • EURUSDOutNet2Max und EURUSDOutNet2Min sind Ergebnisse für Net2: die Preisdifferenz zwischen Eröffnungspreis der Stunde und der des Tages (oder Tagesschlusskurs und Stundeneröffnungpreis).

  1. Die neuronalen Netze werden auf das Annähern des Preises an die Extremwerte trainiert, während wir nicht den Preis selbst, sondern die Indikatorwerte interpretieren werden.
  2. Das Ziel des neuronalen Netzes ist die Differenz zwischen den Preisen Stundeneröffnung und Tageseröffnung (Tagesschluss und Stundeneröffnung). Sie können hier auch andere Ziele ausprobieren, wie z. B. die Differenz zwischen anderen Preisen.
  3. Mit diesem Ansatz glätten wir die Wahrscheinlichkeiten von Fehlerreaktionen in den Modulen des neuronalen Netzes, da die neuronalen Netze nicht darauf trainiert sind, bestimmte tägliche Hoch- und Tiefstpreise zu finden, sondern sie arbeiten mit der Wahrscheinlichkeit der Annäherung von Hoch/Tief, wobei die Preisamplitude zum täglichen Extremum berücksichtigt wird. Wenn wir uns dann entscheiden, die Preisamplitude zu verwenden, können wir die Differenz zwischen dem Tagesschlusskurs und dem Stundeneröffnungpreis verwenden. Die erste Option scheint vorzuziehen zu sein, weil wir in diesem Fall das neuronale Netz anhand von erreichten Zielen und nicht anhand von Ereignissen trainieren, die eintreten sollten. Diese Option ist logischer, weil die Bewertung vergangener Ereignisse einfacher ist als das Erstellen von Vorhersagen.

2. Das Training des neuronalen Netzes mit Python

Zunächst prüfen wir den Abschnitt Integration in der MQL5-Dokumentation. Nach der Installation von Python 3.8 und dem Anschluss des MetaTrader 5 Integrationsmoduls, verbinden wir die Bibliotheken TensorFlow, Keras, Numpy und Pandas auf die gleiche Weise.

Installieren von TensorFlow


Einstellungsfesnster für TensorFlow


Die neuronalen Netze werden mit dem Python-Skript EURUSDPyTren.py trainiert.

import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import load_model

InputNet1=pd.read_csv('EURUSDInputNet1Min.csv', delimiter=';',header=None)
InputNet2OutNet1=pd.read_csv('EURUSDInputNet2OutNet1Min.csv', delimiter=';',header=None)
OutNet2=pd.read_csv('EURUSDOutNet2Min.csv', delimiter=';',header=None)

mean = InputNet1.mean(axis=0)
std = InputNet1.std(axis=0)
InputNet1 -= mean
InputNet1 /= std

mean = InputNet2OutNet1.mean(axis=0)
std = InputNet2OutNet1.std(axis=0)
InputNet2OutNet1 -= mean
InputNet2OutNet1 /= std

Net1Min = Sequential()
Net1Min.add(Dense(22, activation='relu', input_shape=(InputNet1.shape[1],)))
Net1Min.add(Dense(60))

Net1Min.compile(optimizer='adam', loss='mse', metrics=['mse'])
print(Net1Min.summary())

Net1Min.fit(InputNet1, InputNet2OutNet1, epochs=10, batch_size=10,verbose=2,validation_split=0.3)
Net1Min.save('net1Min.h5')

mean = OutNet2.mean(axis=0)
std = OutNet2.std(axis=0)
OutNet2 -= mean
OutNet2 /= std

Net2Min = Sequential()
Net2Min.add(Dense(60, activation='relu', input_shape=(InputNet2OutNet1.shape[1],)))
Net2Min.add(Dense(1))

Net2Min.compile(optimizer='adam', loss='mse', metrics=['mae'])
print(Net2Min.summary())

Net2Min.fit(InputNet2OutNet1, OutNet2, epochs=100, batch_size=10,verbose=2,validation_split=0.3)
Net2Min.save('net2Min.h5')

InputNet1=pd.read_csv('EURUSDInputNet1Max.csv', delimiter=';',header=None)
InputNet2OutNet1=pd.read_csv('EURUSDInputNet2OutNet1Max.csv', delimiter=';',header=None)
OutNet2=pd.read_csv('EURUSDOutNet2Max.csv', delimiter=';',header=None)

mean = InputNet1.mean(axis=0)
std = InputNet1.std(axis=0)
InputNet1 -= mean
InputNet1 /= std

mean = InputNet2OutNet1.mean(axis=0)
std = InputNet2OutNet1.std(axis=0)
InputNet2OutNet1 -= mean
InputNet2OutNet1 /= std

Net1Max = Sequential()
Net1Max.add(Dense(22, activation='relu', input_shape=(InputNet1.shape[1],)))
Net1Max.add(Dense(60))

Net1Max.compile(optimizer='adam', loss='mse', metrics=['mse'])
print(Net1Max.summary())

Net1Max.fit(InputNet1, InputNet2OutNet1, epochs=10, batch_size=10,verbose=2,validation_split=0.3)
Net1Max.save('net1Max.h5')

mean = OutNet2.mean(axis=0)
std = OutNet2.std(axis=0)
OutNet2 -= mean
OutNet2 /= std

Net2Max = Sequential()
Net2Max.add(Dense(60, activation='relu', input_shape=(InputNet2OutNet1.shape[1],)))
Net2Max.add(Dense(1))

Net2Max.compile(optimizer='adam', loss='mse', metrics=['mae'])
print(Net2Max.summary())

Net2Max.fit(InputNet2OutNet1, OutNet2, epochs=100, batch_size=10,verbose=2,validation_split=0.3)
Net2Max.save('net2Max.h5')

NetTest=pd.read_csv('EURUSDTest.csv', delimiter=';',header=None)
Date=pd.read_csv('EURUSDDate.csv', delimiter=';',header=None)

Net1Min = load_model('net1Min.h5')
Net2Min=  load_model('net2Min.h5')
Net1Max = load_model('net1Max.h5')
Net2Max=  load_model('net2Max.h5')
Net1Min = Net1Min.predict(NetTest)
Net2Min = Net2Min.predict(Net1Min)
Net1Max = Net1Max.predict(NetTest)
Net2Max = Net2Max.predict(Net1Max)

Date=pd.DataFrame(Date)
Date['0'] = Net2Min
Date.to_csv('IndicatorMin.csv',index=False, header=False,sep=';')
Date['0'] = Net2Max
Date.to_csv('IndicatorMax.csv',index=False, header=False,sep=';')

Date['0'] = Net2Min
Date['1'] = Net2Max
Date.to_csv('Indicator.csv',index=False, header=False,sep=';')

input('Press ENTER to exit') 

Speichern Sie dieses Skript unter \Common\Files.

Schauen wir uns das Skript genauer an.
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import load_model

Baustein zum Verbinden von Bibliotheken, Paketen und Modulen von Keras.

InputNet1=pd.read_csv('EURUSDInputNet1Min.csv', delimiter=';',header=None)
InputNet2OutNet1=pd.read_csv('EURUSDInputNet2OutNet1Min.csv', delimiter=';',header=None)
OutNet2=pd.read_csv('EURUSDOutNet2Min.csv', delimiter=';',header=None)

Bildung der Datenrahmen aus Datendateien.

mean = InputNet1.mean(axis=0)
std = InputNet1.std(axis=0)
InputNet1 -= mean
InputNet1 /= std

Die Standardisierung der Daten.
Net1Min = Sequential()
Net1Min.add(Dense(22, activation='relu', input_shape=(InputNet1.shape[1],)))
Net1Min.add(Dense(60))

Das sequentielle Netzwerkmodell mit einer Eingangsschicht aus 22 Neuronen und der Ausgangsschicht mit 60 Neuronen.

Net1Min = Sequential()
Net1Min.add(Dense(22, activation='relu', input_shape=(InputNet1.shape[1],)))
Net1Min.add(Dense(11))
Net1Min.add(Dense(60))

Außerdem können Sie versuchen, eine ausgeblendete Schicht hinzuzufügen.
Net1Max.compile(optimizer='adam', loss='mse', metrics=['mse'])
print(Net1Max.summary())

Kompilieren des Netzwerks und Ausdruck seiner Parameter.

Net1Min.fit(InputNet1, InputNet2OutNet1, epochs=10, batch_size=10,verbose=2,validation_split=0.3)
Net1Min.save('net1Min.h5')


Das Training des neuronalen Netzes: 10 Epochen; Mindeststichprobengröße ist 10; 30 % der Trainingsdaten werden für die Validierung reserviert. Diese Hyper-Parameter müssen möglicherweise auch weiter angepasst werden. Verbose - Visualisierungsparameter für die Trainingsepochen. Speichern wir das trainierte neuronale Netz.

NetTest=pd.read_csv('EURUSDTest.csv', delimiter=';',header=None)
Date=pd.read_csv('EURUSDDate.csv', delimiter=';',header=None)

Bildung des Datenrahmens für den Test.

Net1Min = load_model('net1Min.h5')
Net2Min=  load_model('net2Min.h5')
Net1Max = load_model('net1Max.h5')
Net2Max=  load_model('net2Max.h5')
Net1Min = Net1Min.predict(NetTest)
Net2Min = Net2Min.predict(Net1Min)
Net1Max = Net1Max.predict(NetTest)
Net2Max = Net2Max.predict(Net1Max)


Laden Sie die gespeicherten neuronalen Netzwerke, um das Ergebnis zu erhalten.

Date=pd.DataFrame(Date)
Date['0'] = Net2Min
Date.to_csv('IndicatorMin.csv',index=False, header=False,sep=';')
Date['0'] = Net2Max
Date.to_csv('IndicatorMax.csv',index=False, header=False,sep=';')

Date['0'] = Net2Min
Date['1'] = Net2Max
Date.to_csv('Indicator.csv',index=False, header=False,sep=';')

Speichern Sie die erhaltenen Daten in Dateien.

input('Press ENTER to exit') 
Warten Sie auf das Schließen des Fensters.

Um den normalen Ablauf des Skripts zu gewährleisten, ist es auch erforderlich, die Daten für den Empfang von Antworten des neuronalen Netzwerks vorzubereiten, die zur Bildung des Indikators und zur Analyse der Effizienz dieses Indikators für eine Handelsstrategie verwendet werden.

Dies wird mit Hilfe des PythonTestExpert Expert Advisors geschehen.

//+------------------------------------------------------------------+
//|                                             PythonTestExpert.mq5 |
//|                                   Copyright 2020, Andrey Dibrov. |
//|                           https://www.mql5.com/ru/users/tomcat66 |
//+------------------------------------------------------------------+
#property copyright " Copyright © 2019, Andrey Dibrov."
#property link      "https://www.mql5.com/ru/users/tomcat66"
#property version   "1.00"
#property strict

int handleInput;
int HandleDate;

double in[22];
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   handleInput=FileOpen(Symbol()+"Test.csv",FILE_CSV|FILE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");
   HandleDate=FileOpen(Symbol()+"Date.csv",FILE_CSV|FILE_READ|FILE_WRITE|FILE_ANSI|FILE_COMMON,";");
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   FileClose(handleInput);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   for(int i=0; i<=14; i++)
     {
      in[i]=in[i+5];
     }

   in[15]=((iOpen(NULL,PERIOD_D1,0)-iLow(NULL,PERIOD_D1,0))*100000);
   in[16]=((iHigh(NULL,PERIOD_D1,0)-iOpen(NULL,PERIOD_D1,0))*100000);
   in[17]=((iHigh(NULL,PERIOD_D1,0)-iLow(NULL,PERIOD_D1,0))*100000);
   in[18]=((iHigh(NULL,PERIOD_D1,0)-iOpen(NULL,PERIOD_H1,1))*10000);
   in[19]=((iOpen(NULL,PERIOD_H1,1)-iLow(NULL,PERIOD_D1,0))*10000);


   in[20]=((iHigh(NULL,PERIOD_D1,0)-iOpen(NULL,PERIOD_H1,0))*10000);
   in[21]=((iOpen(NULL,PERIOD_H1,0)-iLow(NULL,PERIOD_D1,0))*10000);


   FileWrite(handleInput,

             in[0],in[1],in[2],in[3],in[4],in[5],in[6],in[7],in[8],in[9],in[10],in[11],in[12],in[13],in[14],in[15],
             in[16],in[17],in[18],in[19],in[20],in[21]);

   FileWrite(HandleDate,TimeCurrent());

  }
//+------------------------------------------------------------------+

Führen Sie den Expert Advisor im Strategietester auf dem H1-Chart aus und verwenden Sie den Modus "Nur Öffnungspreise". Der Datenzeitraum für den Test: von Anfang 2011 bis zum aktuellen Datum. Dieser Expert Advisor wird Daten simulieren, die das Python-Skript auf der Grundlage der vom MetaTrader 5 empfangenen Preise im realen Betrieb bilden wird. 


Der EA wird zwei Dateien, EURUSDTest und EURUSDDate, im Ordner \Common erstellen.

Führen Sie das Python-Skript EURUSDPyTren.py aus. (Wenn es nicht funktioniert, müssen Sie eventuell die zuvor beschriebenen Zusatzpakete neu installieren und Ihren Computer neu starten). Wenn alles korrekt ist, wird das Skript durch einen Doppelklick ausgeführt.

Ablauf des Skripts

Als Ergebnis werden die folgenden Dateien im Ordner \Common\Files erstellt: 

  • net1Max.h5, net1Min.h5, net2Max.h5, net2Min.h5 — dies sind die trainierten Netze, die im Basisskript beim Handel in Echtzeit verwendet werden.
  • IndicatorMax und IndicatorMin sind zwei Netzwerkantworten für separate Tests.
  • Der Indikator ist eine kombinierte Antwort.

Der Ordner \Common\Files


Starten Sie den Indikator 1_MT5 im Terminal.

//+------------------------------------------------------------------+
//|                                                        1_MT5.mq5 |
//|                                 Copyright © 2019, Andrey Dibrov. |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2019, Andrey Dibrov."
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  Red
#property indicator_color2  DodgerBlue

int Handle;
int i;

double    ExtBuffer[];
double    SignBuffer[];

datetime Date1;
datetime Date0;

string File_Name="Indicator.csv";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
   SetIndexBuffer(0,ExtBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SignBuffer,INDICATOR_DATA);

   IndicatorSetInteger(INDICATOR_DIGITS,5);

  }
//+------------------------------------------------------------------+
//| Relative Strength Index                                          |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {

   Handle=FileOpen(File_Name,FILE_CSV|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");

   Date0=StringToTime(FileReadString(Handle));

   FileClose(Handle);

   i=iBarShift(NULL,PERIOD_H1,Date0,false);
   
   Handle=FileOpen(File_Name,FILE_CSV|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");
  
   ArraySetAsSeries(ExtBuffer,true);
   ArraySetAsSeries(SignBuffer,true);

   while(!FileIsEnding(Handle) && !IsStopped())
     {
      Date1=StringToTime(FileReadString(Handle));
      ExtBuffer[i]=StringToDouble(FileReadString(Handle));
      SignBuffer[i]=StringToDouble(FileReadString(Handle));
      i--;
     }
  
   FileClose(Handle);

   return(rates_total);
  }
//+------------------------------------------------------------------+

Indikator

Obwohl wir nicht viel Aufwand in das Training des neuronalen Netzwerks gesteckt haben, sind einige Abhängigkeiten sichtbar.

3. Die Optimierung der erhaltenen Ergebnisse.

Lassen Sie uns den PythonOptimizExpert EA verwenden, um den resultierenden Indikator zu optimieren. 

//+------------------------------------------------------------------+
//|                                          PythonOptimizExpert.mq5 |
//|                                   Copyright 2020, Andrey Dibrov. |
//|                           https://www.mql5.com/ru/users/tomcat66 |
//+------------------------------------------------------------------+
#property copyright " Copyright © 2019, Andrey Dibrov."
#property link      "https://www.mql5.com/ru/users/tomcat66"
#property version   "1.00"
#property strict

#include<Trade\Trade.mqh>

CTrade  trade;

input int H1;
input int H2;
input int H3;
input int H4;

input double Buy;
input double Buy1;
input double Sell;
input double Sell1;

input int LossBuy;
input int ProfitBuy;
input int LossSell;
input int ProfitSell;

ulong TicketBuy1;
ulong TicketSell0;

datetime Count;

double Buf_0[];
double Buf_1[];

bool send1;
bool send0;

int k;
int K;
int bars;
int Handle;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   Handle=FileOpen("Indicator.csv",FILE_CSV|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");

   while(!FileIsEnding(Handle)&& !IsStopped())
     {
      StringToTime(FileReadString(Handle));
      bars++;
     }
   FileClose(Handle);

   ArrayResize(Buf_0,bars);
   ArrayResize(Buf_1,bars);

   Handle=FileOpen("Indicator.csv",FILE_CSV|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,";");

   while(!FileIsEnding(Handle)&& !IsStopped())
     {
      Count=StringToTime(FileReadString(Handle));
      Buf_0[k]=StringToDouble(FileReadString(Handle));
      Buf_1[k]=StringToDouble(FileReadString(Handle));
      k++;
     }
   FileClose(Handle);

   int deviation=10;
   trade.SetDeviationInPoints(deviation);
   trade.SetTypeFilling(ORDER_FILLING_RETURN);
   trade.SetAsyncMode(true);
//---
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   MqlDateTime stm;
   TimeToStruct(TimeCurrent(),stm);

   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
   double PriceAsk=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double PriceBid=SymbolInfoDouble(_Symbol,SYMBOL_BID);

   double SL1=NormalizeDouble(PriceBid-LossBuy*point,digits);
   double TP1=NormalizeDouble(PriceAsk+ProfitBuy*point,digits);
   double SL0=NormalizeDouble(PriceAsk+LossSell*point,digits);
   double TP0=NormalizeDouble(PriceBid-ProfitSell*point,digits);

   if(LossBuy==0)
      SL1=0;

   if(ProfitBuy==0)
      TP1=0;

   if(LossSell==0)
      SL0=0;

   if(ProfitSell==0)
      TP0=0;

//---------Buy1
   if(send1==false && K>0 &&  Buf_0[K]<Buy && Buy<Buy1 && iLow(NULL,PERIOD_H1,1)<iLow(NULL,PERIOD_H1,2) && stm.hour>H1 && stm.hour<H2 && H1<H2)
     {
      send1=trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,1,PriceAsk,SL1,TP1);//SL1,TP1
      TicketBuy1 = trade.ResultDeal();
     }

   if(send1==true && K>0 &&  Buf_0[K]>Buy1 &&  Buy<Buy1 && iHigh(NULL,PERIOD_H1,1)>iHigh(NULL,PERIOD_H1,2) )
     {
      trade.PositionClose(TicketBuy1);
      send1=false;
     }

//---------Sell0

   if(send0==false && K>0 &&  Buf_1[K]<Sell && Sell<Sell1 && iHigh(NULL,PERIOD_H1,1)>iHigh(NULL,PERIOD_H1,2) && stm.hour>H3 && stm.hour<H4 && H3<H4)
     {
      send0=trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,1,PriceBid,SL0,TP0);//SL0,TP0
      TicketSell0 = trade.ResultDeal();
     }

   if(send0==true && K>0 &&  Buf_1[K]>Sell1 && Sell<Sell1 && iLow(NULL,PERIOD_H1,1)<iLow(NULL,PERIOD_H1,2) )
     {
      trade.PositionClose(TicketSell0);
      send0=false;
     }
   K++;
  }

//+------------------------------------------------------------------+
//| Tester function                                                  |
//+------------------------------------------------------------------+
double OnTester()
  {
//---
   double ret=0.0;
//---

//---
   return(ret);
  }
//+------------------------------------------------------------------+

Die folgenden Variablen können optimiert werden:

  • Н1, Н2 — die Stunden des Tages, zwischen denen der Kauf durchgeführt wird.
  • Н3 ,H4 — die Stunden des Tages, zwischen denen der Verkauf durchgeführt werden soll.
  • Buy, Buy1 — dies sind die Niveaus der roten Linie des Indikators Buf_0[], die die Reaktion des neuronalen Netzes ist, das auf die Daten bis zum Tagestief trainiert wurde.
  • Sell, Sell1 — diese zeigen die blauen Niveaus des Buf_1[]-Indikators an, der die Antwort des neuronalen Netzes ist, das auf den Daten bis zum Tageshoch trainiert wurde.
  • LossBuy, ProfitBuy, LossSell, ProfitSell — Preise für die Grenzwerte.

Lassen Sie uns die Optimierungsparameter wie in der Abbildung gezeigt einstellen. Das bedeutet, dass wir nur die Indikatorlevels optimieren werden.

Optimierte Indikatorniveaus

Optimierungsparameter

Die Optimierungsergebnisse



Die Testergebnisse. Der Optimierungszeitraum reicht bis zur roten Linie im Testchart. Danach erfolgt der Test mit optimierten Parametern.


Mit den erhaltenen Parametern optimieren wir weiter durch Zeit- und Stop-Orders.

Testen wir nun alle ermittelten Parameter.


Optional können Sie versuchen, jede Handelsrichtung separat zu optimieren.

Schlussfolgerungen

Das folgende Video hilft Ihnen, die Vorbereitung des Python-Skripts zu verstehen.



Übersetzt aus dem Russischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/ru/articles/8502

Beigefügte Dateien |
EURUSDPyTren.py (3.47 KB)
DibMax1-1.mq5 (5.11 KB)
DibMin1-1.mq5 (5.08 KB)
PythonPrices.mq5 (11.46 KB)
Zeitreihen in der Bibliothek DoEasy (Teil 55): Die Kollektionsklasse der Indikatoren Zeitreihen in der Bibliothek DoEasy (Teil 55): Die Kollektionsklasse der Indikatoren

Der Artikel setzt die Entwicklung von Objektklassen für die Indikatoren und deren Kollektionen fort. Für jedes Indikatorobjekt erstellen wir seine Beschreibung und die richtige Kollektionsklasse für die fehlerfreie Speicherung und das Abrufen von Indikatorobjekten aus der Kollektionsliste.

Neuronale Netze leicht gemacht (Teil 5): Parallele Berechnungen mit OpenCL Neuronale Netze leicht gemacht (Teil 5): Parallele Berechnungen mit OpenCL

Wir haben bereits einige Arten von Implementierungen neuronaler Netze besprochen. In den betrachteten Netzwerken werden die gleichen Operationen für jedes Neuron wiederholt. Ein logischer weiterer Schritt ist die Nutzung der parallelen Berechnung, die die moderne Technologie bietet, um den Lernprozess des neuronalen Netzwerks zu beschleunigen. Eine der möglichen Implementierungen wird in diesem Artikel beschrieben.

Optimale Vorgehensweise für Entwicklung und Analyse von Handelssystemen Optimale Vorgehensweise für Entwicklung und Analyse von Handelssystemen

In diesem Artikel zeige ich Ihnen die Kriterien, die Sie bei der Auswahl eines Systems oder Signals für die Investition Ihrer Gelder berücksichtigen sollten. Außerdem beschreibe ich die optimale Vorgehensweise bei der Entwicklung von Handelssystemen und zeige auf, wie wichtig diese Angelegenheit im Forex-Handel ist.

Zeitreihen in der Bibliothek DoEasy (Teil 56): Nutzerdefiniertes Indikatorobjekt, das die Daten von Indikatorobjekten aus der Kollektion holt Zeitreihen in der Bibliothek DoEasy (Teil 56): Nutzerdefiniertes Indikatorobjekt, das die Daten von Indikatorobjekten aus der Kollektion holt

In dem Artikel wird das Erstellen des nutzerdefinierten Indikatorobjekts für die Verwendung in EAs erklärt. Lassen Sie uns die Bibliotheksklassen leicht verbessern und Methoden hinzufügen, um Daten von Indikatorobjekten in EAs zu erhalten.