Aplicação prática de redes neurais no trading. Python (Parte I)
Introdução
No artigo anterior "Aplicação prática de redes neurais no trading. Embarquemos na prática“ consideramos o uso prático de um módulo de rede neural implementado em redes neurais Matlab, só que nele omitimos a preparação de dados de entrada, e o trabalho a nível de treinamento de redes neurais. Neste artigo, essas questões serão levantadas em exemplos concretos e implementadas em redes neurais de bibliotecas que trabalham com Python. No entanto, o princípio para implementar o sistema de negociação será um pouco diferente. Tal regra foi brevemente descrita no parágrafo 5 do artigo base "Aplicação prática de redes neurais no trading". Para isso, usamos a biblioteca de aprendizado de máquina TensorFlow desenvolvida pelo Google. Para descrever as redes neurais, usamos a biblioteca Keras.
1. Preparação de dados
Vejamos alguns pontos de preparação para o treinamento de redes neurais.
- Neste desenvolvimento, para tomar uma decisão, vamos usar dois redes neurais para abrir posições numa direção.
- Com base no ponto anterior, também dividiremos os dados de treinamento em duas direções.
- Como no sistema anterior, nossa primeira rede neural será treinada para construir indicadores semelhantes aos indicadores técnicos padrão. Usamos esta variante no sistema anterior porque usamos indicadores escritos por nós e não queríamos sobrecarregar funcionamento do Expert Advisor. Em Python, isso acontece porque desde o terminal podemos obter só cotações e, só depois disso, precisamos construir esses indicadores num script Python para preparar dados da rede neural. Porém, após ensinar a rede neural a construir indicadores desse tipo, contornamos a necessidade de repeti-los no script.
- A segunda rede neural constrói diretamente o indicador de sinal que usamos para realizar a estratégia de negociação.
- Treinar a rede neural com base no gráfico horário do par EURUSD.
- Como resultado, para construir o sistema, precisamos preparar dois RN para transações de compra e dois para transações de venda. No total, no sistema funcionarão quatro redes neurais.
Para preparar dados que permitirão treinar as redes, usaremos dois scripts - PythonPrices.mq5 e 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("Идет запись файлf 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("Идет запись файлf 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("Файлы записаны"); } //+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //| 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; //------ Дневной минимум 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("Идет запись файлов InputNet2OutNet1Min и 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); } } } } //------ Дневной максимум 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("Идет запись файлов InputNet2OutNet1Max и 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("Файлы записаны"); } //+------------------------------------------------------------------+
Faremos uma primeira amostra desde o início do pregão até a obtenção do primeiro mínimo do dia, realizaremos uma segunda até a consecução do primeiro máximo do dia. Para fazer isso, nos scripts, usaremos os dois indicadores DibMin1-1.mq5 e 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); } //+------------------------------------------------------------------+
Quando o preço atinge os extremos diários, os indicadores assumem valores iguais a -1.
Depois de trabalhar esses scripts no gráfico EURUSDH1 na pasta \Common\Files obteremos seis arquivos no formato CSV.
- EURUSDInputNet1Max e EURUSDInputNet1Min são arquivos com dados de preços. No nome do arquivo, vemos que, por exemplo, o arquivo EURUSDInputNet1Max é um arquivo de dados de entrada para a rede neural Net1Max.
- EURUSDInputNet2OutNet1Max e EURUSDInputNet2OutNet1Min são arquivos com valores de indicadores. Esses valores serão entradas para Net2 e saídas para Net1. Note imediatamente que você precisa experimentar, portanto, você pode treinar a Net2 usando indicadores técnicos padrão ou respostas da Net1.
- EURUSDOutNet2Max e EURUSDOutNet2Min são saídas para Net2: diferença de preços entre o de abertura da hora e o de abertura do dia (ou fechamento do dia e abertura da hora).
- Treinamos redes neurais com base na aproximação do preço aos seus extremos, interpretando não o preço em si, mas os valores do indicador.
- O objetivo da RN é a diferença dos preços para abertura da hora e abertura do dia (fechamento do dia e abertura da hora). Você também pode experimentar definindo outros objetivos para a RN, como a diferença entre outros preços.
- Com esta abordagem, suavizamos as probabilidades de respostas erradas em todos os módulos da rede neural, uma vez que treinamos a rede neural não especificamente para encontrar os preços máximos ou mínimos do dia, mas, sim, para descobrir a probabilidade de nos aproximar a eles, levando em consideração a amplitude dos preços até o extremo diário. Se depois decidirmos focar na amplitude do preço, podemos usar a diferença de preço entre fechamento do dia e abertura da hora. Acho que a primeira opção é preferível, pois neste caso estaremos treinando a rede neural com base nos objetivos alcançados, e não nos eventos que estão prestes a acontecer. O que você vê é mais lógico. Afinal, avaliar eventos passados é mais fácil do que fazer previsões.
2. Treinamento de rede neural Python
A primeira coisa que precisamos fazer é usar a seção de referência da MQL5 "Integração". Depois de instalar o Python 3.8 e conectar o módulo de integração MetaTrader5, anexe as bibliotecas TensorFlow, Keras, Numpy e Pandas da mesma maneira.
Para treinar redes neurais, usaremos o script Python EURUSDPyTren.py
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')
Também colocaremos este script na pasta \Common\Files .
Vamos dar uma olhada no script.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
Bloco para anexar bibliotecas, pacotes e módulos a partir de 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)
Geramos o dataframe a partir de arquivos de dados.
mean = InputNet1.mean(axis=0) std = InputNet1.std(axis=0) InputNet1 -= mean InputNet1 /= stdPadronizamos os dados.
Net1Min = Sequential() Net1Min.add(Dense(22, activation='relu', input_shape=(InputNet1.shape[1],))) Net1Min.add(Dense(60))
Modelo de rede sequencial, camada de entrada de 22 neurônios, camada de saída de 60.
Net1Min = Sequential() Net1Min.add(Dense(22, activation='relu', input_shape=(InputNet1.shape[1],))) Net1Min.add(Dense(11)) Net1Min.add(Dense(60))Podemos experimentar e adicionar uma camada oculta.
Net1Max.compile(optimizer='adam', loss='mse', metrics=['mse']) print(Net1Max.summary())
Compilamos a rede e imprimimos seus parâmetros.
Net1Min.fit(InputNet1, InputNet2OutNet1, epochs=10, batch_size=10,verbose=2,validation_split=0.3) Net1Min.save('net1Min.h5')
Treinamos a rede neural para 10 épocas, o tamanho da mini-amostra é 10, 30 por cento dos dados de treinamento são alocados para validation. Esses hiperparâmetros de rede também precisam ser experimentados. Verbose é um parâmetro para visualizar épocas de aprendizagem. Salvamos a rede neural treinada.
NetTest=pd.read_csv('EURUSDTest.csv', delimiter=';',header=None) Date=pd.read_csv('EURUSDDate.csv', delimiter=';',header=None)
Formamos um dataframe para teste.
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)
Carregamos as redes neurais salvas e obtemos o resultado.
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=';')
Salvamos os dados recebidos em arquivos.
input('Press ENTER to exit')
Esperamos a janela fechar. Para o processamento normal do script, também precisamos preparar os dados para receber respostas das redes neurais que usaremos para gerar o indicador e pesquisas subsequentes para determinar se é aconselhável usá-lo na construção de uma estratégia de negociação.
Para isso, usamos o Expert Advisor PythonTestExpert.
//+------------------------------------------------------------------+ //| 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()); } //+------------------------------------------------------------------+
Vamos iniciar o EA no testador de estratégia em H1 a preços de abertura. Vamos ver o período desde o início de 2011 até os dias atuais. Com a ajuda deste Expert Advisor, simulamos dados que, no trabalho real, serão gerados por um script Python a partir dos preços que entram desde o MT5.
Na pasta \Common, este Expert Advisor criará os dois arquivos EURUSDTest e EURUSDDate.
Executamos o script Python EURUSDPyTren.py (Se não funcionar, pode ser necessário reinstalar os pacotes adicionais que instalamos anteriormente e reiniciar o computador). Se fizermos tudo corretamente, o script será executado com um clique duplo.
Como resultado, na pasta \Common\Files, teremos os seguintes arquivos:
- net1Max.h5, net1Min.h5, net2Max.h5, net2Min.h5 - redes neurais treinadas que serão usadas num script de trabalho ao negociar em tempo real.
- IndicatorMax e IndicatorMin são duas respostas NS para testes separados.
- Indicator é uma resposta combinada.
Vamos iniciar o indicador 1_MT5 no terminal de negociação.
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Não nos esforçamos muito ao treinar redes neurais, mas certas dependências já são visíveis.
3. Otimização dos resultados obtidos.
Para otimizar o indicador resultante, usaremos o Expert Advisor PythonOptimizExpert.
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Temos variáveis como essa que podemos otimizar
- Н1, Н2 — horas do dia entre as que será realizada a compra.
- Н3 ,H4 — horas do dia entre as que ocorrerá a venda.
- Buy, Buy1 — nesta variante, os níveis da linha vermelha do indicador Buf_0[] são a resposta da RN treinada com base nos dados até o mínimo do dia.
- Sell, Sell1 — nesta variante, os níveis da linha azul do indicador Buf_1[] são a resposta da RN treinada com base nos dados até o máximo do dia.
- LossBuy, ProfitBuy, LossSell, ProfitSell — níveis restritivos.
Vamos definir os parâmetros de otimização conforme mostrado na imagem. Ou seja, vamos otimizar apenas os níveis do indicador.
Níveis de indicador otimizados
Parâmetros de otimização
Resultados da otimização
Resultados do teste. Até a linha vermelha no gráfico de teste: o período de otimização, depois, o teste com base nos parâmetros otimizados.
Com os parâmetros obtidos iremos realizar uma otimização adicional em termos de tempo e ordens stop.
Testamos usando todos os parâmetros.
É claro que podemos otimizar cada direção de negociação separadamente.
Fim do artigo
O vídeo a seguir ajudará você a entender rapidamente como se preparar para executar um script Python.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/8502
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso