
神经网络在交易中的实际应用 Python (第一部分)
介绍
在前一篇题为“神经网络在交易中的实际应用-是时候进行实践了”的文章中, 研究了用 Matlab 神经网络实现的神经网络模块的实际应用。但是,这篇文章没有涉及与准备输入数据和网络训练相关业务有关的问题。在本文中,我们将使用示例来探讨这些问题,并将使用与 Python 一起工作的库的神经网络来实现进一步的代码。这一次,交易系统的实现原则将有所不同。基础文章“神经网络在交易中的实际应用”的第5段简要描述了这个变体。对于这个实现,我们将使用Google开发的 TensorFlow 机器学习库,我们还将使用 Keras 库来描述神经网络。
1. 准备数据
让我们考虑一些与神经网络训练数据准备有关的问题。
- 为了决策,我们将使用两个神经网络在一个方向上打开仓位。
- 根据前一点,训练数据应分为两组-每个方向一组。
- 与前一个系统一样,将训练第一个神经网络来构建类似于标准技术指标的指标。我们在以前的系统中使用了这个解决方案,因为我们使用了自写的指示符,我们不想让专家顾问的工作负担过重。之所以使用Python,是因为只能从终端接收报价,为了为神经网络准备数据,我们需要在 Python 脚本中构建这些指标。通过教神经网络建立这样的指标,我们消除了在脚本中复制它们的需要。
- 第二个神经网络建立信号指标,在此基础上建立交易策略。
- 神经网络将针对 EURUSD H1 图表进行训练。
- 因此,为了建立这个系统,我们需要准备两个神经网络用于买入和两个网络用于卖出。因此,系统中将有四个神经网络工作。
两个脚本将用于为网络培训准备数据:PythonPrices.mq5 文件以及 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"); } //+------------------------------------------------------------------+
一个样本将从工作日开始直到第一次到达当天的低点。第二个样本将持续到第一次达到当天的最高点。为此,脚本中将使用两个指标:DibMin1-1.mq5 和 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); } //+------------------------------------------------------------------+
当价格达到每日极值时,指标值设置为-1。
在 EURUSD H1 图表上运行脚本后,将在 \Common\files 文件夹中创建六个 CSV 文件。
- EURUSDInputNet1Max 和 EURUSDInputNet1Min 是包含价格数据的文件。我们可以从文件名中看到,例如,EURUSDInputNet1Max 包含 Net1Max 神经网络的输入数据。
- EURUSDInputNet2OutNet1Max 和 EURUSDInputNet2OutNet1Min 是具有指标值的文件。这些值将是 Net2 的输入和 Net1 的输出。请注意,这部分需要一些实验:Net2 可以使用标准技术指标或 Net1 响应进行训练。
- EURUSDOutNet2Max 和 EURUSDOutNet2Min 是用于 Net2 的输出:小时开盘和日开盘之间的价差(或日收盘和小时开盘之间的价差)。
- 神经网络是通过价格逼近极值来训练的,不是解释价格本身,而是解释指标值。
- 神经网络的目标是小时开盘价和日开盘价之间的差异(日收盘价和小时开盘)价。您也可以在这里尝试其他目标,例如其他价格之间的差异。
- 通过这种方法,我们平滑了神经网络模块中错误响应的概率,因为神经网络没有训练来寻找特定的日高和日低价格,但是它们使用高/低接近的概率,同时考虑到价格幅度到日极值。如果我们决定使用价格幅度,我们可以使用日收盘价和小时开盘价之间的差值。第一种选择似乎更可取,因为在这种情况下,我们使用实现的目标而不是应该发生的事件来训练神经网络。这个选项更符合逻辑,因为评估过去的事件比预测更容易。
2. Python 神经网络训练
首先,检查 MQL5 文档的集成部分。安装Python3.8并连接MetaTrader 5集成模块后,以相同的方式连接 TensorFlow、Keras、Numpy 和 Pandas 库。
神经网络将使用 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')
把这个脚本保存到 \Common\Files。
让我们仔细看看这个脚本。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
用于连接来自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)
从数据文件构建数据帧。
mean = InputNet1.mean(axis=0) std = InputNet1.std(axis=0) InputNet1 -= mean InputNet1 /= std数据标准化。
Net1Min = Sequential() Net1Min.add(Dense(22, activation='relu', input_shape=(InputNet1.shape[1],))) Net1Min.add(Dense(60))
序贯网络模型,输入层有22个神经元,输出层有60个神经元。
Net1Min = Sequential() Net1Min.add(Dense(22, activation='relu', input_shape=(InputNet1.shape[1],))) Net1Min.add(Dense(11)) Net1Min.add(Dense(60))此外,还可以尝试添加隐藏层。
Net1Max.compile(optimizer='adam', loss='mse', metrics=['mse']) print(Net1Max.summary())
编译网络并打印其参数。
Net1Min.fit(InputNet1, InputNet2OutNet1, epochs=10, batch_size=10,verbose=2,validation_split=0.3) Net1Min.save('net1Min.h5')
神经网络训练:10个 epoch;最小样本量为10;30%的训练数据分配用于验证。这些超参数可能还需要进一步调整。详细-训练 epoch 可视化参数。保存训练好的神经网络。
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')
等待或者关闭窗口。 为了保证脚本的正常运行,还需要准备数据以接收神经网络响应,这些数据将用于形成指标并分析该指标在交易策略中的效率。
这将使用 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()); } //+------------------------------------------------------------------+
在 H1 图表上的策略测试程序中运行专家顾问,使用仅开盘价格模式。测试时间区间:2011年初至今。这个专家顾问将模拟Python脚本将根据实际操作中从 MetaTrader 5 收到的价格形成的数据。
EA 将创建两个文件, EURUSDTest 和 EURUSDDate, 在 \Common 文件夹下。
运行 Python 脚本 EURUSDPyTren.py,(如果不起作用,您可能需要重新安装前面描述的附加软件包并重新启动计算机)。如果一切都正确,脚本将通过双击运行。
最终,将在\Common\Files文件夹中创建以下文件:
- net1Max.h5, net1Min.h5, net2Max.h5, net2Min.h5 — 这些是经过训练的网络,在实时交易时将在基本脚本中使用。
- IndicatorMax 和 IndicatorMin 是两个用于单独测试的网络,
- Indicator 是组合起来的。
在终端中载入 1_MT5 指标。
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
虽然我们对神经网络的训练还没有投入太多的精力,但是仍然存在一些明显的依赖性。
3. 优化得到的结果。
让我们使用 PythonOptimizExpert EA 来优化得到的指标。
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
可以优化以下变量:
- Н1, Н2 — 一天中进行买入的时间间隔小时数。
- Н3 ,H4 — 进行卖出的时间间隔小时数。
- Buy, Buy1 — 这表明了Buf_0[]指标的红线水平,这是对数据训练的神经网络对当天低点的响应。
- Sell, Sell1 — 这表示Buf_1[]指标的蓝线水平,这是在数据上训练的神经网络对当天高点的响应。
- LossBuy, ProfitBuy, LossSell, ProfitSell — 限价水平。
让我们设置优化参数,如图所示。这意味着我们将只优化指标水平。
优化的指标水平
优化参数
优化结果
测试结果优化周期达到测试图上的红线。然后使用优化的参数进行测试。
利用得到的参数,进一步按时间和止损挂单进行优化。
现在,让我们测试所有获得的参数。
或者,您可以尝试分别优化每个交易方向。
结论
下面的视频将帮助您理解 Python 脚本的准备工作。
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/8502


