首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >MQL5循环中的for数组耗时太长,有没有更好的方法?

MQL5循环中的for数组耗时太长,有没有更好的方法?
EN

Stack Overflow用户
提问于 2019-06-12 23:52:14
回答 1查看 594关注 0票数 0

我正在写一个EA,仅供策略测试人员使用,用于评估投资组合。所以我在一个数组中有成百上千的交易,有开盘价格和开盘时间,每隔1分钟我就会在一个for循环中检查在那一分钟内是否有任何交易要开盘。而且还需要很长的时间。

如何(以更快的方式)检查数组中是否有与当前时间重合的打开时间?

谢谢!

if(NewBar)
 {
  CopyRates(_Symbol,PERIOD_M1,0,5,candle);
  sizeAr=ArraySize(ar);
  arColumns=ArrayRange(ar,1);
  datetime candleNowTime = candle[0].time;
  datetime nextCandleTime = candle[0].time+60;      

  for(int i=0;i<sizeAr/arColumns;i++)
    {
     if(ar[i][openTime]>candleNowTime && ar[i][openTime]<nextCandleTime)
       {
        //code to open trades
       }
    }
 }

完整的代码在这里:

//+------------------------------------------------------------------+
//|                                          HedgeExperienceV001.mq5 |
//|                                                      Carlos Duna |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Carlos Duna"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property tester_file "sinais.csv"
#include <Trade\Trade.mqh>
CTrade trade;
#include <Trade\SymbolInfo.mqh>
CSymbolInfo mysymbol;
#define columns 19

input double initialVolume = 0.01;  // Volume inicial
input double slFixo = 0;            // SL fixo (pips)(zero=SL do sinal)
input double tpFixo = 0;            // TP fixo (pips)(zero=TP do sinal)
input ulong  maxSlippage = 0;       // Max Deviation/Slippage(0-não usa)
input double maxPricesVariation =10;// Max % variação Bid x TP x SL x OP

MqlRates candle[];
MqlDateTime TimeStruct;
MqlDateTime dealDay;
datetime dealDayStruct;
datetime now;
int secAnterior;
int previousDay;

bool NewBar;
datetime hj;
string orderComment;
bool orderOkToOpen;

datetime inicioHedge=0;
double profitPerMagic[][2];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct SLine
  {
   string            field[];
  };

SLine lines[];

string ar[][columns];
int sizeLine;
int sizeAr;
int arColumns;

double stopLossDelta;
double takeProfitDelta;

/*
lines[i].field[j]

** i= numero de cada trade, iniciando no zero (não há títulos de colunas), indo dinamicamente até a ultima linha
** j= valores dos campos

0 - tCanal
1 - str(msgId)
2 - dataHora HoraEntrada
3 - str(opType) CompraOuVenda
4 - ativo.upper()
5 - str(openPrice)
6 - str(stopLoss)
7 - str(takeProfit1)
8 - str(takeProfit2)
9 - str(takeProfit3)
10 - str(takeProfit4)
11 - str(takeProfit5)
12 - 'false' posição já foi aberta? true/false
13 - 'false' posição já foi fechada? true/false
14 - HalfCloseTime
15 - ManualCloseTime
16 - SLModify_Time
17 - SLModify_Price])
18 - magicCanal
*/

int xCanal = 0; // tCanal
int xOpCod = 1; // str(msgId)
int xDtEnt = 2; // dataHora HoraEntrada
int xBuySell=3; // str(opType) CompraOuVenda
int xAtv= 4; // ativo.upper()
int xOP = 5; // str(openPrice)
int xSL=6; // str(stopLoss)
int xTP1 = 7; // str(takeProfit1)
int xTP2 = 8; // str(takeProfit2)
int xTP3 = 9; // str(takeProfit3)
int xTP4 = 10; // str(takeProfit4)
int xTP5 = 11; // str(takeProfit5)
int xOpened = 12; // posição já foi aberta? true/false
int xClosed = 13; // posição já foi fechada? true/false
int xHalfC=14; // HalfCloseTime
int xManualC = 15; // ManualCloseTime
int xSLMTime = 16; // SLModify_Time
int xSLMPrice= 17; // SLModify_Price
int xMagic=18; // magicCanal
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ArraySetAsSeries(candle,true);

   if(!ReadFileToArrayCSV("sinais.csv",lines))
     {
      Alert("Error, see the \"Experts\" tab for details");
      return(INIT_FAILED);
     }

   sizeLine=ArraySize(lines);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

   ArrayFree(lines);
   ArrayFree(ar);
   double a = ProfitClosedPosition();
   Print(a);

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

   now=TimeCurrent();
   TimeToStruct(TimeCurrent(),TimeStruct);

   if(previousDay!=TimeStruct.day_of_year) //Runs once a day
     {
      previousDay=TimeStruct.day_of_year;

      // recria diariamente o array auxiliar ar
      ArrayResize(ar,sizeLine);
      for(int i=0;i<sizeLine;i++)
        {
         for(int j=0;j<columns;j++)
           {
            ar[i][j]=lines[i].field[j];
           }
        }

      // após array ar recriado, elimina-se o que não for ser usado no dia
      for(int i=sizeLine-1; i>=0; i--)
        {
         TimeToStruct((datetime)lines[i].field[xDtEnt],dealDay);

         // if temporario; o deal close não será por data, e sim pelo fechamento do trade, a ser sinalizado no futuro
         if(dealDay.day_of_year+2<TimeStruct.day_of_year && dealDay.year==TimeStruct.year) 
           {
            ArrayRemove(ar,i,1);
           }

         // remove entradas cujas datas de entrada sejam superiores ao dia de hoje ou que possuam flag 'closed'
         if((dealDay.day_of_year>TimeStruct.day_of_year && dealDay.year<=TimeStruct.year) || (lines[i].field[xClosed]==true))
           {
            ArrayRemove(ar,i,1);
           }
        } 

     } 

   NewBar=isNewBar();
   if(NewBar)
     {
      CopyRates(_Symbol,PERIOD_M1,0,5,candle);
      sizeAr=ArraySize(ar);
      arColumns=ArrayRange(ar,1);
      datetime candleNowTime = candle[0].time;
      datetime nextCandleTime = candle[0].time+60;      
      for(int i=0;i<sizeAr/arColumns;i++)
        {
         if(ar[i][xDtEnt]>candleNowTime && ar[i][xDtEnt]<nextCandleTime)
           {
            fAbrirOp(i);
            Print(ar[i][xCanal]," / ",ar[i][xOP]," / ",ar[i][xSL]," / ",ar[i][xTP1]);
           }

        }
     } 
  }  


//+------------------------------------------------------------------+
//| Função que transforma arquivo CSV em array                       |
//+------------------------------------------------------------------+
bool ReadFileToArrayCSV(string FileName,SLine  &Lines[])
  {
   ResetLastError();
   int h=FileOpen(FileName,FILE_READ|FILE_ANSI|FILE_CSV|FILE_COMMON,";");
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
   if(h==INVALID_HANDLE)
     {
      int ErrNum=GetLastError();
      printf("Error opening file %s # %i",FileName,ErrNum);
      return(false);
     }
   int lcnt=0; // variable for calculating lines 
   int fcnt=0; // variable for calculating line fields    
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
   while(!FileIsEnding(h))
     {
      string str=FileReadString(h);
      // new line (new element of the structure array)
      if(lcnt>=ArraySize(Lines))
        { // structure array completely filled
         ArrayResize(Lines,ArraySize(Lines)+1024); // increase the array size by 1024 elements
        }
      ArrayResize(Lines[lcnt].field,64);// change the array size in the structure
      Lines[lcnt].field[0]=str; // assign the first field value
                                // start reading other fields in the line
      fcnt=1; // till one element in the line array is occupied
      while(!FileIsLineEnding(h))
        { // read the rest of fields in the line
         str=FileReadString(h);
         if(fcnt>=ArraySize(Lines[lcnt].field))
           { // field array is completely filled
            ArrayResize(Lines[lcnt].field,ArraySize(Lines[lcnt].field)+64); // increase the array size by 64 elements
           }
         Lines[lcnt].field[fcnt]=str; // assign the value of the next field
         fcnt++; // increase the line counter
        }
      ArrayResize(Lines[lcnt].field,fcnt); // change the size of the field array according to the actual number of fields
      lcnt++; // increase the line counter
     }
   ArrayResize(Lines,lcnt); // change the array of structures (lines) according to the actual number of lines
   FileClose(h);
   return(true);
  }

//+------------------------------------------------------------------+
//| Função checar nova barra                                         |
//+------------------------------------------------------------------+
bool isNewBar(void)
  {
//--- memorize the time of opening of the last bar in the static variable
   static datetime last_time=0;
//--- current time
   datetime lastbar_time=(datetime)SeriesInfoInteger(Symbol(),PERIOD_M1,SERIES_LASTBAR_DATE);
//--- if it is the first call of the function
   if(last_time==0)
     {
      //--- set the time and exit
      last_time=lastbar_time;
      return(false);
     }
//--- if the time differs
   if(last_time!=lastbar_time)
     {
      //--- memorize the time and return true
      last_time=lastbar_time;
      return(true);
     }
//--- if we passed to this line, then the bar is not new; return false
   return(false);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| entrada em operação                                                                 |
//+------------------------------------------------------------------+
void fAbrirOp(int i)
  {
  if(inicioHedge==0)inicioHedge=datetime(ar[i][xDtEnt]); 
   double _TP;
   double _SL;
   orderOkToOpen=true;
   Print("iniciando ativo: ",ar[i][xAtv]);
   if(!mysymbol.Name(ar[i][xAtv]))
     {
      Print("Erro ao selecionar ativo ",ar[i][xAtv],"; operação não será aberta.");
      orderOkToOpen=false;
     }
   mysymbol.RefreshRates();
   double spread=mysymbol.Spread();
   double bid = mysymbol.Bid();
   double ask = mysymbol.Ask();
   double maxPrice = ask * (100 + maxPricesVariation)/100;
   double minPrice = bid * (100 - maxPricesVariation)/100;

//--- tuning for 3 or 5 digits
   int digits_adjust=1;
   if(mysymbol.Digits()==3 || mysymbol.Digits()==5)
      digits_adjust=10;
   stopLossDelta   = slFixo*digits_adjust;
   takeProfitDelta = tpFixo*digits_adjust;
   if(maxSlippage!=0) trade.SetDeviationInPoints(maxSlippage);

   if(double(ar[i][xOP])<minPrice || double(ar[i][xOP])>maxPrice || double(ar[i][xSL])<minPrice || double(ar[i][xSL])>maxPrice || double(ar[i][xTP1])<minPrice || double(ar[i][xTP1])>maxPrice)
     {
      Print("Erro nos níveis de preço do ativo ",ar[i][xAtv],". Bid = ",bid," / Open Price: ",ar[i][xOP]," / SL: ",ar[i][xSL]," / TP: ",ar[i][xTP1]," operação não será aberta.");
      orderOkToOpen=false;
     }

   if(orderOkToOpen)
     {
      trade.SetExpertMagicNumber(ulong(ar[i][xMagic]));
      if(ar[i][xBuySell]=="buy")
        {
         _TP = tpFixo == 0 ? double(ar[i][xTP1]) : double(ar[i][xOP]) + takeProfitDelta;
         _SL = slFixo == 0 ? double(ar[i][xSL]) : double(ar[i][xOP]) - stopLossDelta;

         if(trade.Buy(initialVolume,ar[i][xAtv],double(ar[i][xOP]),_SL,_TP,ar[i][xCanal]))
           {
            ar[i][xOpened]=true;
            Print("Ordem colocada, ticket: ",trade.ResultDeal());
            Print("preço: ",trade.ResultPrice()," , era pra ter sido por ",ar[i][xOP]);
            trade.PrintResult();
           }
         else
           {
            Print(trade.ResultRetcodeDescription());
            trade.PrintRequest();
           }
        }
      else if(ar[i][xBuySell]=="sell")
        {
         _TP = tpFixo == 0 ? double(ar[i][xTP1]) : double(ar[i][xOP]) - takeProfitDelta;
         _SL = slFixo == 0 ? double(ar[i][xSL]) : double(ar[i][xOP]) + stopLossDelta;

         if(trade.Sell(initialVolume,ar[i][xAtv],double(ar[i][xOP]),_SL,_TP,ar[i][xCanal]))
           {
            ar[i][xOpened]=true;
            Print("Ordem colocada, ticket: ",trade.ResultDeal());
            Print("preço: ",trade.ResultPrice()," , era pra ter sido por ",ar[i][xOP]);
            trade.PrintResult();
           }
         else
           {
            Print(trade.ResultRetcodeDescription());
            trade.PrintRequest();
           }
        }

     }
  } 


//+------------------------------------------------------------------+
//| Lucro acumulado do dia                                           |
//+------------------------------------------------------------------+
double ProfitClosedPosition()
  {
   int lSize;
   bool magicFound;
   double profit=0;
   int counter=1;
   HistorySelect(inicioHedge,TimeCurrent());
   int deals=HistoryDealsTotal();
   int colunas = ArrayRange(profitPerMagic,1);
//---
   for(int i=0;i<deals;i++)
     {
      ulong deal_ticket=HistoryDealGetTicket(i);
      string symbol= HistoryDealGetString(deal_ticket,DEAL_SYMBOL); 
      double _p_profit=HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
      int dealType = (int)HistoryDealGetInteger(deal_ticket,DEAL_TYPE);
      int dealMagic = (int)HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
      string   dealComment      =HistoryDealGetString(deal_ticket,DEAL_COMMENT);
      if(dealType!=0 && dealType!=1) continue;
      lSize = ArraySize(profitPerMagic);
      magicFound=false;
      if(lSize==0)ArrayResize(profitPerMagic,(lSize/colunas)+1);

      for(int j=0;j<(ArraySize(profitPerMagic)/colunas);j++)
        {
         if(profitPerMagic[j][0]==double(dealMagic))
           {
            profitPerMagic[j][1]+=_p_profit;
            magicFound=true;
            break;
           }
        }
      if(!magicFound)
        {
         ArrayResize(profitPerMagic,(lSize/colunas)+1);
         for(int j=(ArraySize(profitPerMagic)/colunas)-1;j>=0;j--)
           {
            profitPerMagic[j][0]=dealMagic;
            profitPerMagic[j][1]=profit;
            break;
           }
        }
      profit+=_p_profit;

      Print(counter+": Ativo: "+symbol+" R$ "+_p_profit+" do tipo "+dealType+" , magic: "+dealMagic," / ",dealComment);
      counter++;
     }

   for(int i=0;i<(ArraySize(profitPerMagic)/colunas);i++)
     {
      Print(profitPerMagic[i][0], " / " ,profitPerMagic[i][1]);
     }
   return(profit);
  }
//+------------------------------------------------------------------+
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56566130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档