//+------------------------------------------------------------------+
//|                                            MAE_MFE_DrawDowns.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.ru/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.ru/"
// âñòàâëåíî èç ñêðèïòà SummaryReport
#define OP_BALANCE 6
#define OP_CREDIT  7
#define StatParameters 8
// âñòàâëåíî èç ñêðèïòà SummaryReport
#property show_inputs
extern int MaxTimeMissed=15;   // ìàêñèìàëüíî äîïóñòèìàÿ äûðà â çàãðóæåííîé èñòîðèè â ìèíóòàõ
//+------------------------------------------------------------------+
//| çàïîëíÿåò ìàññèâû MAE â âàëþòå äåïîçèòà                          |
//+------------------------------------------------------------------+
bool SetMAEAndMFE(double & MFE_Array[],double & MAE_Array[],int TicketsArray[])   
   {
   bool res=false;
//----
   int bar,PeriodNumber,i,limit=ArraySize(TicketsArray);
   ArrayResize(MAE_Array,limit);
   ArrayResize(MFE_Array,limit);
   int openShift,closeShift;
   int type,znak,spread,K_spread;
   double symPoint;
   double MFE_points,MAE_points;
   double currProfit,currLoss,closePriceProfit,closePriceLoss;
   double buy,sell,OPrice,PointCost;
   double deltaPricePoints;
//----
   //Print("Çàøëè 1");
   for (i=0;i<limit;i++)
      {
      //Print("Çàøëè2");
      if (OrderSelect(TicketsArray[i],SELECT_BY_TICKET))
         {
         openShift=iBarShift(OrderSymbol(),PERIOD_M1,OrderOpenTime());
         closeShift=iBarShift(OrderSymbol(),PERIOD_M1,OrderCloseTime());
         //Print("Èñòîðèè äëÿ ðàñ÷åòà MFE ïî îðäåðó #",TicketsArray[i]," åñòü ",openShift-closeShift," ìèíóòíûõ áàðîâ, à âðåìÿ â ìèíóòàõ ",DoubleToStr((OrderCloseTime()-OrderOpenTime())/60.0,0));
         //if (openShift==-1 || closeShift==-1) Print("Íå õâàòàåò èñòîðèè äëÿ ðàñ÷åòà MFE ïî îðäåðó #",TicketsArray[i]);
         type=OrderType();
         OPrice=OrderOpenPrice();
         if (type==OP_BUY) 
            {
            znak=1;
            K_spread=0;
            buy=1;
            sell=0;
            } 
         else 
            {
            znak=-1;
            K_spread=1;
            buy=0;
            sell=1;
            }
         spread=MarketInfo(OrderSymbol(),MODE_SPREAD);
         symPoint=MarketInfo(OrderSymbol(),MODE_POINT);
         //Print("spread=",spread,"   symPoint=",symPoint);
         //if (openShift-closeShift>0)
         MFE_points=-10000;
         MAE_points=-10000;
         deltaPricePoints=(OrderOpenPrice()-OrderClosePrice())/symPoint;
         if (deltaPricePoints==0) 
            {
            //Print("Áóäåò äåëåíèå íà íîëü â ôóíêöèè SetMAEAndMFE, ïðèáûëü â ïóíêòàõ ðàâíà íóëþ");
            PointCost=MarketInfo(OrderSymbol(),MODE_POINT)*MarketInfo(OrderSymbol(),MODE_LOTSIZE);
            string first   =StringSubstr(OrderSymbol(),0,3);         // ïåðâûé ñèìâîë,    íàïðèìåð EUR
            string second  =StringSubstr(OrderSymbol(),3,3);         // âòîðîé ñèìâîë,    íàïðèìåð USD
            string currency=AccountCurrency();                // âàëþòà äåïîçèòà,  íàïðèìåð USD
            if (second==currency) PointCost=PointCost*OrderLots();
            else
               {
               string crossCurrency=StringConcatenate(second,currency);
               int barCross=iBarShift(crossCurrency,PERIOD_M1,OrderOpenTime());
               double CrossRate=iOpen(crossCurrency,PERIOD_M1,barCross);
               PointCost=PointCost*OrderLots()*CrossRate;
               }
            }
         else PointCost=MathAbs((OrderProfit())/deltaPricePoints);
         //else PointCost=MathAbs((OrderProfit()+OrderSwap())/deltaPricePoints);
         //Print("Îðäåð ¹",TicketsArray[i]," îòêðûò ïî öåíå ",OPrice);
         for (bar=openShift;bar>=closeShift;bar--)
            {
            //currProfit=(OrderOpenPrice()-Low[bar])*znak-K_spread*spread*symPoint;
            currProfit=(iHigh(OrderSymbol(),PERIOD_M1,bar)-OPrice)*buy-(iLow(OrderSymbol(),PERIOD_M1,bar)+spread*symPoint-OPrice)*sell;
            currLoss=(iLow(OrderSymbol(),PERIOD_M1,bar)-OPrice)*buy-(iHigh(OrderSymbol(),PERIOD_M1,bar)+spread*symPoint-OPrice)*sell;
            if (iHigh(OrderSymbol(),PERIOD_M1,bar)==0) Print("2% Äëÿ  îðäåðà #",TicketsArray[i],"  ïî ñèìâîëó ",OrderSymbol()," openShift=",openShift," closeShift=",closeShift,"  ïðîáëåìà ñ äîñòóïîì ê iHigh(OrderSymbol(),PERIOD_M1,bar) ïî âðåìåíè ",TimeToStr(iTime(OrderSymbol(),PERIOD_M1,bar)));
            if (iLow(OrderSymbol(),PERIOD_M1,bar)==0) Print("2%Äëÿ  îðäåðà #",TicketsArray[i],"  ïî ñèìâîëó ",OrderSymbol()," openShift=",openShift," closeShift=",closeShift,"  ïðîáëåìà ñ äîñòóïîì ê iLow(OrderSymbol(),PERIOD_M1,bar) ïî âðåìåíè ",TimeToStr(iTime(OrderSymbol(),PERIOD_M1,bar)));
            //Print("currProfit=",currProfit,"   currLoss=",currLoss,"   OPrice=",OPrice);
            //if (currProfit>0 && currProfit/symPoint>MFE_points) 
            if (currProfit/symPoint>MFE_points) 
               {
               MFE_points=currProfit/symPoint;
               //Print("currProfit=",currProfit/symPoint);
               }
            //if (currLoss<0 && -currLoss/symPoint>MAE_points) 
            if ( -currLoss/symPoint>MAE_points) 
               {
               MAE_points=-currLoss/symPoint;
               //Print("currLoss=",currLoss/symPoint);
               }
            }
         MFE_Array[i]=MFE_points*PointCost; 
         MAE_Array[i]=-MAE_points*PointCost;
         if (MathAbs(MFE_Array[i])>10000) Print(OrderSymbol()," #",TicketsArray[i],"; MFE_Array[i]=",MFE_Array[i],"  MFE_points=",MFE_points,"  PointCost=",PointCost,"  symPoint=",symPoint,"  OrderProfit()=",OrderProfit(),"  deltaPrice=",deltaPricePoints);
         if (MathAbs(MAE_Array[i])>10000) Print(OrderSymbol()," #",TicketsArray[i],"; MFA_Array[i]=",MAE_Array[i],"  MAE_points=",MAE_points,"  PointCost=",PointCost,"  symPoint=",symPoint,"  OrderProfit()=",OrderProfit(),"  deltaPrice=",deltaPricePoints);
         //Print("#",TicketsArray[i],";",MFE_Array[i],";",MAE_Array[i]);
         }
      else
         {
         Alert("Íå óäàëîñü âûáðàòü îðäåð #",TicketsArray[i]);
         }   
      }
//----
   return(res);   
   }   
//+------------------------------------------------------------------+
//|  çàïîëíÿåò çíà÷åíèÿìè ïðèáûëåé è óáûòêîâ                         |
//+------------------------------------------------------------------+
void    FillOrderProfits(double & ProfitsArray[],double & NormalizedProfitsArray[],double & SwapArray[],int TicketsArray[])
   {
   int total=ArraySize(TicketsArray);
   ArrayResize(ProfitsArray,total);
   ArrayResize(SwapArray,total);
   ArrayResize(NormalizedProfitsArray,total);
//----
   for (int i=0;i<total;i++)
      {
      if (OrderSelect(TicketsArray[i],SELECT_BY_TICKET))
         {
         ProfitsArray[i]=OrderProfit()+OrderSwap()-OrderCommission();
         SwapArray[i]=OrderSwap();
         if (OrderLots()!=0) NormalizedProfitsArray[i]=0.1*ProfitsArray[i]/OrderLots();
         else Alert("Îáíàðóæåí îðäåð ñ íóëåâûì çíà÷åíèåì ëîòà #",TicketsArray[i]);
         }
      else
         {
         Alert("Íå óäàëîñü âûáðàòü îðäåð #",TicketsArray[i]);
         }   
      }
//----
   return;   
   }
//+------------------------------------------------------------------+
//| âîçâðàùàåò îòñîðòèðîâàííûé ïî âðåìåíè  çàêðûòèÿ ìàññèâ òèêåòîâ   |
//+------------------------------------------------------------------+
int LoadSortedTickets(int & Tickets[])
   {
   int i,counter;
   int TicketAndTime[][2];
//----
   if (ArraySize(Tickets)==0) return;
   ArrayResize(TicketAndTime,OrdersHistoryTotal());
   for (i=0;i<OrdersHistoryTotal();i++) 
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
         {
            if (OrderType()<=OP_SELL) 
               {
               TicketAndTime[counter][0]=OrderCloseTime();
               TicketAndTime[counter][1]=OrderTicket();
               counter++;
               }
         }
      }
   ArrayResize(TicketAndTime,counter);
   ArrayResize(Tickets,counter);
   ArraySort(TicketAndTime);
   for (i=0;i<counter;i++) 
      {
      Tickets[i]=TicketAndTime[i][1];
      }
   int err=GetLastError();
//----
   return(counter);
   }
//+------------------------------------------------------------------+
//| âîçâðàùàåò true, åñëè ñèìâîë ñ èìåíåì symbolName óæå åñòü        |
//+------------------------------------------------------------------+
bool AddSymbol(string & SimbolListArray[],string symbolName)
   {
   bool res=false;
   int size=ArraySize(SimbolListArray);
//----
   //Print("Äîáàâëÿåì ñèìâîë ",symbolName);
   ArrayResize(SimbolListArray,size+1);
   if (ArraySize(SimbolListArray)==size+1)
      {
      SimbolListArray[size]=StringTrimLeft(StringTrimRight(symbolName));
      res=true;
      }
//----
   return(res);   
   }
//+------------------------------------------------------------------+
//| âîçâðàùàåò true, åñëè ñèìâîë ñ èìåíåì symbolName óæå åñòü        |
//+------------------------------------------------------------------+
bool SymbolFoundInArray(string SimbolListArray[],string symbolName)
   {
   bool res=false;
   int pos;
//----
   for (int i=0;i<ArraySize(SimbolListArray);i++)
      {
      pos=StringFind(SimbolListArray[i],StringTrimLeft(StringTrimRight(symbolName)));
      if (pos!=-1 && pos==0) 
         {
         if (StringLen(SimbolListArray[i])!=StringLen(StringTrimLeft(StringTrimRight(symbolName)))) 
            {
            //Print("Ïîèñê íîâîãî ñèìâîëà â ìàññèâå äàë ñþðïðèç");
            //Print("ïåðâûé=|",SimbolListArray[i],"| âòîðîé=|",symbolName,"|");
            }
         res=true;
         break;
         }
      }
//----
   return(res);   
   }
//+------------------------------------------------------------------+
//| ïîäñ÷èòûâàåò ÷èñëî îòêðûòûõ è îòìåíåííûõ îðäåðîâ                 |
//+------------------------------------------------------------------+
bool GetNumberOfOrders(int & Closed,int & Cancelled, string & SymbolsArray[])
   {
   bool res=false;
   //Print("Îðäåðîâ â èñòîðèè ",OrdersHistoryTotal());
//----
   for (int i=OrdersHistoryTotal()-1;i>=0;i--) 
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
         {
         if (OrderType()==OP_BALANCE) continue;
            if (!SymbolFoundInArray(SymbolsArray,OrderSymbol())) 
               AddSymbol(SymbolsArray,OrderSymbol());
         if (OrderType()>OP_SELL) Cancelled++;
         else Closed++; 
         }
      }
   if (Cancelled+Closed>0) res=true;   
//----
   return(res);
   }
//+------------------------------------------------------------------+
//| âîçâðàùàåò èíäåêñ, íà êîòîðîé èñêîìàÿ ñòðîêà FindName            |
//+------------------------------------------------------------------+
int IndexOfName(string & StringArray[],string FindName)
   {
   int res=-1000;
//----
   int total=ArraySize(StringArray);
   for (int i=0;i<total;i++)
      if (StringArray[i]==FindName)
         {
         res=i;
         break;
         }
//----
   return(res);
   }
//+------------------------------------------------------------------+
//| ïðîâåðèì ìèíóòíóþ èñòîðèþ íà íàëè÷èå äûðîê                       |
//+------------------------------------------------------------------+
bool    CheckHistoryOnClosedOrders(int & ClosedTicketsArray[],string & SymbolsForClosedOrders[])
   {
   bool res=true;
   int errors[100][3];  // â ïåðâûé ýëåìåíò ïèøåì èíäåêñ ñèìâîëà, âî âòîðîé - òèêåò îðäåðà, â òðåòèé - äàòó/âðåìÿ îøèáêè 
   int errCounter;      // ñ÷åò÷èê îøèáîê
   int openBar_M1=iBarShift(OrderSymbol(),PERIOD_M1,OrderOpenTime());
   int closeBar_M1=iBarShift(OrderSymbol(),PERIOD_M1,OrderCloseTime());
   int TimeInterval[][2];// ïåðâûé ýëåìåíò - íà÷àëüíàÿ äàòà ïðîïóñêà, âòîðîé ýëåìåíò - êîíå÷íàÿ äàòà ïðîïóñêà
   int indexSymbol;
   datetime timeClose;
//----
   int i,number_orders=ArraySize(ClosedTicketsArray),number_symbols=ArraySize(SymbolsForClosedOrders);
   ArrayResize(TimeInterval,number_symbols);
   for (i=0;i<number_symbols;i++) TimeInterval[i][0]=TimeCurrent();
   for (i=0;i<number_orders;i++)
      {
      if (OrderSelect(ClosedTicketsArray[i],SELECT_BY_TICKET))
         {
         openBar_M1=iBarShift(OrderSymbol(),PERIOD_M1,OrderOpenTime());
         if (OrderCloseTime()!=0) closeBar_M1=iBarShift(OrderSymbol(),PERIOD_M1,OrderCloseTime());
         else closeBar_M1=iBarShift(OrderSymbol(),PERIOD_M1,TimeCurrent());
         indexSymbol=IndexOfName(SymbolsForClosedOrders,OrderSymbol());
         if (MathAbs(iTime(OrderSymbol(),PERIOD_M1,openBar_M1)-OrderOpenTime())/60>MaxTimeMissed)
            {
            errors[errCounter][0]=indexSymbol;
            errors[errCounter][1]=ClosedTicketsArray[i];
            errors[errCounter][2]=OrderOpenTime();
            res=false;
            if (OrderOpenTime()<TimeInterval[indexSymbol][0]) TimeInterval[indexSymbol][0]=OrderOpenTime();
            if (OrderOpenTime()>TimeInterval[indexSymbol][1]) TimeInterval[indexSymbol][1]=OrderOpenTime();
            //Print("Îøèáêà ïðè ïîèñêå áàðà îòêðûòèÿ íà ñèìâîëå ",OrderSymbol()," M1 äëÿ îðäåðà #",ClosedTicketsArray[i],"=>",TimeToStr(OrderOpenTime()));
            errCounter++;
            }
         if (OrderCloseTime()!=0) timeClose=OrderCloseTime();
         else timeClose=TimeCurrent();
         if (MathAbs(iTime(OrderSymbol(),PERIOD_M1,closeBar_M1)-timeClose)/60>MaxTimeMissed)
            {
            errors[errCounter][0]=indexSymbol;
            errors[errCounter][1]=ClosedTicketsArray[i];
            errors[errCounter][2]=OrderCloseTime();
            res=false;
            if (OrderCloseTime()<TimeInterval[indexSymbol][0]) TimeInterval[indexSymbol][0]=timeClose;
            if (OrderCloseTime()>TimeInterval[indexSymbol][1]) TimeInterval[indexSymbol][1]=timeClose;
            Print("Îøèáêà ïðè ïîèñêå áàðà çàêðûòèÿ íà ñèìâîëå ",OrderSymbol()," M1 äëÿ îðäåðà #",ClosedTicketsArray[i],"=>",TimeToStr(timeClose));
            errCounter++;
            }
         }
      } 
   if (!res) 
      {
      Alert("Ïðè ïðîâåðêå ñ÷åòà îáíàðóæåíî îøèáîê ïðîïóñêà ìèíóòíûõ áàðîâ â äîñòóïíîé èñòîðèè - ",errCounter, "! Ïîäðîáíîñòè ñìîòðè â çàêëàäêå Æóðíàë");
      for (i=0;i<number_symbols;i++)
         {
         if (TimeInterval[i][0]*TimeInterval[i][1]!=0) Print("Íå äîñòàåò èñòîðèè íà ",SymbolsForClosedOrders[i]," íà èíòåðâàëå:",TimeToStr(TimeInterval[i][0]),"-",TimeToStr(TimeInterval[i][1]));
         }      
      }
//----
   return(res);
   }
//+------------------------------------------------------------------+
//| âû÷èñëèì âñå ïðîñàäêè                                            |
//+------------------------------------------------------------------+
bool CalculateDD(int & ClosedTicketsArray[],string & SymbolsArray[] ,double & minEquity,double & MoneyDD,
   double & MoneyDDPer,double & RelativeDD,double & RelativeDD$)
   {
   bool res=false;
//----
  int AllOpenedOrdersTickets[];           // ìàññèâ çàðêûòûõ îðäåðîâ èç èñòîðèè + òåêóùèå íåçàêðûòûå îðäåðà
  int ConveyerArray[][2];                 // ïåðâûâé ýëåìåíò - âðåìÿ, âòîðîé ýëåìåíò - òèêåò
   int i,k,marketOrders;
   for (i=0;i<OrdersTotal();i++)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
         {
         if (OrderType()==OP_BUY || OrderType()==OP_SELL) marketOrders++;
         }
      }
   //Print("marketOrders=",marketOrders,",  îðäåðîâ â èñòîðèè=",ArraySize(ClosedTicketsArray));
   if (ArraySize(ClosedTicketsArray)+marketOrders==0) 
      {
      Print("Íåò îðäåðîâ äëÿ îáðàáîòêè");
      }
   ArrayResize(AllOpenedOrdersTickets,ArraySize(ClosedTicketsArray)+marketOrders);
   
   i=0;
   if (ArraySize(ClosedTicketsArray)>0) for (i=0;i<ArraySize(ClosedTicketsArray);i++) AllOpenedOrdersTickets[i]=ClosedTicketsArray[i];
   //Print("AllOpenedOrdersTickets=",ArraySize(AllOpenedOrdersTickets));
   if (marketOrders>0)
      {
      while (k<marketOrders) 
         {
         if (OrderSelect(k,SELECT_BY_POS,MODE_TRADES))
            {
            if (OrderType()==OP_BUY || OrderType()==OP_SELL) 
               {
               AllOpenedOrdersTickets[i]=OrderTicket();
               //Print("i=",i,"   k=",k,"  ticket=",OrderTicket());
               if (!SymbolFoundInArray(SymbolsArray,OrderSymbol()))    AddSymbol(SymbolsArray,OrderSymbol()); 
               i++;
               }
            else Alert("Íåóäà÷íàÿ ïîïûòêà âûáðàòü îðäåð!!!");               
            }
         k++;
         }
      }
   if (!CheckHistoryOnClosedOrders(AllOpenedOrdersTickets,SymbolsArray))   return(false);
   ArrayResize(ConveyerArray,ArraySize(AllOpenedOrdersTickets)*2);
   //Print("Ðàçìåð êîíâåéåðà=",ArrayRange(ConveyerArray,0));
   for (i=0;i<ArrayRange(AllOpenedOrdersTickets,0);i++)
      {
      //Print("i=",i,"   ticket=",AllOpenedOrdersTickets[i]);
      if (OrderSelect(AllOpenedOrdersTickets[i],SELECT_BY_TICKET))
         {
         //Print("i=",i,"   ticket=",AllOpenedOrdersTickets[i]," OrderOpenTime=",TimeToStr(OrderOpenTime())," OrderCloseTime=",TimeToStr(OrderCloseTime()));
         ConveyerArray[2*i][0]=OrderOpenTime();
         ConveyerArray[2*i][1]=AllOpenedOrdersTickets[i];
         if (OrderCloseTime()!=0) ConveyerArray[2*i+1][0]=OrderCloseTime();
         else ConveyerArray[2*i+1][0]=TimeCurrent()+200;
         ConveyerArray[2*i+1][1]=-AllOpenedOrdersTickets[i];
         }
      else Alert("Îøèáêà âûáîðà îðäåðà ïðè ðàñ÷åòå ïðîñàäîê!!!");
      }
   ArraySort(ConveyerArray);      // îòñîðòèðóåì êîíâåéåð ïî âðåìåíè ñîáûòèé: îòêðûòèå-çàêðûòèå îðäåðà
   //for (i=0;i<ArrayRange(ConveyerArray,0);i++) Print(TimeToStr(ConveyerArray[i][0])," - ", ConveyerArray[i][1]);
   
   int ticket=OrderSelect(ConveyerArray[0][1],SELECT_BY_TICKET);
   string SymbolName=OrderSymbol();
   int max=ArrayRange(ConveyerArray,0);
   datetime startTrade=TimeRoundeMinute(ConveyerArray[0][0]);
   datetime stopTrade=TimeRoundeMinute(ConveyerArray[max-1][0]);
   if (stopTrade>TimeCurrent()) stopTrade=TimeCurrent();
   double balance=10000;         // íà÷àëüíîå çíà÷åíèå äåïîçèòà ðàâíî 10 000
   double minimalEquity=balance; // íà÷àëüíîå çíà÷åíèå äåïîçèòà ðàâíî 10 000
   double lastPeak=balance;      // ïîñëåäíèé ìàêñèìóì ýêâèòè
   double lastMin=balance;       // ïîñëåäíèé ìèíèìóì ýêâèòè
   double equity;                // òåêóùèé ýêâèòè
   double MaxProfit,MinProfit,FixedProfit;
   double currDD, lastmaxDD,currPercentDD,lastPercentDD;
   int curr_pos;
   int stack[];
   datetime curr_minute;
   equity=balance;
   int FileHandle;
//   Print("Íà÷àëüíàÿ äàòà ",TimeToStr(startTrade,TIME_DATE|TIME_SECONDS),
//      ", êîíå÷íàÿ äàòà ",TimeToStr(stopTrade,TIME_DATE|TIME_SECONDS));
   FileHandle=FileOpen(AccountNumber()+"_equity_2.csv",FILE_CSV|FILE_WRITE);
   FileWrite(FileHandle,"Date","BALANCE","EQUITY");
   FileWrite(FileHandle,TimeToStr(startTrade-1),balance,equity);
   for (curr_minute=startTrade;curr_minute<=stopTrade;curr_minute=curr_minute+60)
      {
      SetStack(stack,ConveyerArray,curr_minute,curr_pos);
      CheckAllProfits(stack,MaxProfit,MinProfit,curr_minute);
      equity=balance+(MaxProfit+MinProfit)/2;
//      Print("balance=",balance);
      if (equity>lastPeak) 
         {
         lastPeak=equity;
         lastMin=equity;
         }
      if (equity<lastMin) 
         {
         lastMin=equity;
         currDD=lastPeak-lastMin;
         if (currDD>lastmaxDD) 
            {
            lastmaxDD=currDD;
            MoneyDDPer=(lastmaxDD)/lastPeak*100;
            MoneyDD=lastmaxDD;
            }
         currPercentDD=currDD/lastPeak*100;
         if (currPercentDD>lastPercentDD)
            {
            lastPercentDD=currPercentDD;
            RelativeDD=lastPercentDD;
            RelativeDD$=currDD;
            }   
         }
      if (lastMin<minimalEquity) 
         {
         minimalEquity=lastMin;
         }
         
      CloseTickets(stack,curr_minute,FixedProfit);
      balance=balance+FixedProfit;
      FileWrite(FileHandle,TimeToStr(curr_minute),balance,equity);
      }
   FileClose(FileHandle);   
   minEquity=minimalEquity;
//----
   return(res);   
   }
//+------------------------------------------------------------------+
//| ïðîñóììèðóåì  ïðîôèòû ïî îòêðûòûì òèêåòàì                        |
//+------------------------------------------------------------------+
bool   CheckAllProfits(int stackTickets[],double & maxProfit, double & minProfit,datetime this_minute)
   {
   bool res=false;
   maxProfit=0;
   minProfit=0;
   double thisOrderMaxProfit,thisOrderMinProfit;
//----
   int i,type,pos;
   for (i=0;i<ArraySize(stackTickets);i++)
      {
      if (GetProfit(stackTickets[i],thisOrderMaxProfit,thisOrderMinProfit,this_minute))
         {
         //Print("Ïîñ÷èòàëè ïðîôèò äëÿ îðäåðà#",stackTickets[i]," â ",TimeToStr(this_minute));
         //Print("thisOrderMaxProfit=",thisOrderMaxProfit,"   thisOrderMinProfit=",thisOrderMinProfit);
         maxProfit+=thisOrderMaxProfit;
         minProfit+=thisOrderMinProfit;
         }
      else Print("Íå óäàëîñü îïðåäåëèòü òåêóùóþ ïðèáûëü äëÿ îðäåðà#",stackTickets[i]);         
      }
//----
   return(res);   
   }
//+------------------------------------------------------------------+
//| âîçâðàùàåò ìèíèìàëüíûé ìàêñèìàëüíûé ïðîôèò äëÿ îðåäåðà           |
//+------------------------------------------------------------------+
bool GetProfit(int ticket,double & maxProf,double & minProf,datetime at_minute)
   {
   bool res=true;
//----
   string symbol,crossPair,firstCurrency,secondCurrency,baseCurrency=AccountCurrency();
   int bar,type,maxPoint,minPoint,err;
   double openPrice,maxPrice,minPrice,spread,point,pointCost,lots,price;
   datetime foundedTime;
   minProf=0;
   maxProf=0;
   //Print("Ïîëó÷èì çíà÷åíèå ïðèáûëè äëÿ îðäåðà#",ticket);
   if (ticket<0) return(res);
   if (OrderSelect(ticket,SELECT_BY_TICKET))
      {
      symbol=OrderSymbol();
      firstCurrency=StringSubstr(OrderSymbol(),0,3);
      secondCurrency=StringSubstr(OrderSymbol(),3,3);
      //Print("base=",baseCurrency,"   firstCurrency=",firstCurrency,"   secondCurrency=",secondCurrency);
      type=OrderType();
      openPrice=OrderOpenPrice();
      bar=iBarShift(symbol,PERIOD_M1,at_minute);
      foundedTime=iTime(symbol,PERIOD_M1,bar);
      spread=MarketInfo(symbol,MODE_SPREAD);
      point=MarketInfo(symbol,MODE_POINT);
      lots=OrderLots();
      if (firstCurrency==baseCurrency)
         {
         price=(iHigh(symbol,PERIOD_M1,bar)+iLow(symbol,PERIOD_M1,bar))/2;
         //Print("price=",price);
         pointCost=point*MarketInfo(symbol,MODE_LOTSIZE)/price;
         }
      if (secondCurrency==baseCurrency)
         {
         pointCost=point*MarketInfo(symbol,MODE_LOTSIZE);
         }
      if (firstCurrency!=baseCurrency && secondCurrency!=baseCurrency)
         {
         //Print("Êðîññ ",symbol);
         if (MarketInfo(secondCurrency+baseCurrency,MODE_BID)>0) 
            {
            crossPair=StringConcatenate(secondCurrency,baseCurrency);
            price=(iHigh(crossPair,PERIOD_M1,bar)+iLow(crossPair,PERIOD_M1,bar))/2;
            pointCost=point*MarketInfo(symbol,MODE_LOTSIZE)*price;
            }
         if (MarketInfo(baseCurrency+secondCurrency,MODE_BID)>0) 
            {
            crossPair=StringConcatenate(baseCurrency,secondCurrency);
            price=(iHigh(crossPair,PERIOD_M1,bar)+iLow(crossPair,PERIOD_M1,bar))/2;
            //Print(crossPair,"=",price,"   ",TimeToStr(foundedTime));
            pointCost=point*MarketInfo(symbol,MODE_LOTSIZE)/price;
            }
         err=GetLastError();
         //Print("Îøèáêà äîñòóïà ê öåíå ",crossPair," M1 â ",TimeToStr(at_minute));
         }   
      //Print("Ñòîèìîñòü ïóíêòà  äëÿ îðäåðà#",ticket," ñîñòàâëÿåò ",pointCost);
         
      if (foundedTime!=TimeRoundeMinute(at_minute)) 
         {
         //Print("Îøèáêà ðàññîãëàñîâàíèÿ âðåìåíè íà ",symbol," M1 â ",TimeToStr(at_minute));
         //Print("        foundedTime=",TimeToStr(foundedTime));
         }
      if (type==OP_BUY)
         {
         maxProf=(iHigh(symbol,PERIOD_M1,bar)-openPrice)/point;
         minProf=(iLow(symbol,PERIOD_M1,bar)-openPrice)/point;
         }
      if (type==OP_SELL)
         {
         maxProf=(openPrice-iHigh(symbol,PERIOD_M1,bar))/point+spread;
         minProf=(openPrice-iLow(symbol,PERIOD_M1,bar))/point+spread;
         }
      maxProf=maxProf*lots*pointCost;
      minProf=minProf*lots*pointCost;
      //Print("maxProf=",maxProf,"   minProf=",minProf," at ",TimeToStr(at_minute));
      }
   else
      {
      res=false;
      Print("Íå óäàëîñü âûáðàòü îðäåð#",ticket," â ",TimeToStr(at_minute),". Ôóíêöèÿ GetProfit()");
      }     
//----
   return(res);   
   }
//+------------------------------------------------------------------+
//| çàêðîåì íóæíûå è âåðíåì ðåçóëüòàò îò çàêðûòûõ îðäåðîâ            |
//+------------------------------------------------------------------+
bool CloseTickets(int & stackTickets[],datetime this_minute,double & fixedProfit)
   {
   bool res=false;
//----
   int i,type,pos,toCloseTickets[];
   int closedCounter;
   fixedProfit=0;
   for (i=0;i<ArraySize(stackTickets);i++)
      {
      if (OrderSelect(stackTickets[i],SELECT_BY_TICKET))
         {
         if (TimeRoundeMinute(OrderCloseTime())==TimeRoundeMinute(this_minute) && stackTickets[i]>=0) 
            {
            fixedProfit=fixedProfit+OrderProfit()+OrderSwap()-OrderCommission();
            AddTicketToClose(toCloseTickets,stackTickets[i]);
            //Print("Óäàëÿåì èç ñòåêà îðäåð#",stackTickets[i]," â ",TimeToStr(this_minute));
            closedCounter++;
            }
         }
      }
   if (closedCounter>0)
      {
      res=true;
      for (i=0;i<closedCounter;i++)
         {
         if (!DeleteTicketFromStack(stackTickets,toCloseTickets[i])) Print("Îøèáêà óäàëåíèÿ îðäåðà#",toCloseTickets[i]);
         if (!DeleteTicketFromStack(stackTickets,-toCloseTickets[i])) Print("Îøèáêà óäàëåíèÿ îðäåðà#",-toCloseTickets[i]);
         }
      GetLastError();
      ArrayResize(toCloseTickets,0);
      if (GetLastError()>0) Print("Îøèáêà ïðè çàäàíèè íóëåâîãî ðàçìåðà ìàññèâà");
      }      
//----
   return(res);
   }
//+------------------------------------------------------------------+
//| óäàëÿåò èç ñòåêà çàêðûòûå îðäåðà                                 |
//+------------------------------------------------------------------+
bool  DeleteTicketFromStack(int & OpenedTicketsArray[],int ñloseâTicket)
   {
   bool res=false;
//----
   int i,pos,size=ArraySize(OpenedTicketsArray);
   for (i=0;i<size;i++)
      {
      if (OpenedTicketsArray[i]==ñloseâTicket)
         {
         pos=i;
         break;
         }
      }
   GetLastError();      
   OpenedTicketsArray[pos]=OpenedTicketsArray[size-1];
   ArrayResize(OpenedTicketsArray,size-1);   // âûáðîñèëè ïîñëåäíèé ýåëåìåíò
   if (GetLastError()==0) res=true;
//----
   return(res);
   }
   
//+------------------------------------------------------------------+
//|  äîáàâèì  TicketNumber â ìàññèâ Array                            |
//+------------------------------------------------------------------+
bool  AddTicketToClose(int & Array[],int TicketNumber)
   {
   bool res=false;
//----
   GetLastError();
   int size=ArraySize(Array);
   ArrayResize(Array,size+1);
   Array[size]=TicketNumber;
   if (GetLastError()==0) res=true;
//----
   return(res);
   }
//+------------------------------------------------------------------+
//|  ïðîâåäåì îïåðàöèè ñî ñòåêîì òèêåòîâ îòêðûòûõ îðäåðîâ            |
//+------------------------------------------------------------------+
void SetStack(int & stackArray[],int Conveyer[][],datetime this_minute,int & conveyer_pos)
   {
//----
   int i,list=ArrayRange(Conveyer,0);
   while ((TimeRoundeMinute(this_minute)==TimeRoundeMinute(Conveyer[conveyer_pos][0])))
      {
      AddTicketToStack(stackArray,Conveyer[conveyer_pos][1]); 
      //Print("Äîáàâèëè â ñòåê îðäåð#",Conveyer[conveyer_pos][1]," â ",TimeToStr(this_minute));
      conveyer_pos++;
      }
//----
   return;
   }
//+------------------------------------------------------------------+
//| äîáàâèì òèêåòû âíîâü îòêðûòûõ îðäåðîâ                             |
//+------------------------------------------------------------------+
bool AddTicketToStack(int & stackArray[],int ticket) 
   {
   bool res=false;
//----
   GetLastError();
   int size=ArraySize(stackArray);
   ArrayResize(stackArray,size+1);
   stackArray[size]=ticket;
   if (GetLastError()==0) res=true;
//----
   return(res);   
   }
//+------------------------------------------------------------------+
//|  îêðóãëåíèå äàòû ñ òî÷íîñòüþ äî ìèíóòû                           |
//+------------------------------------------------------------------+
datetime TimeRoundeMinute(datetime input)
   {
   datetime res;
//----
   res=StrToTime(TimeToStr(input,TIME_DATE|TIME_MINUTES));
//----
   return(res);   
   }
//+------------------------------------------------------------------+
//|  çàïèøåì òàáëèöó ïîôèòîâ è ñîîòâåòñòâóþùèõ MAE è MFE             |
//+------------------------------------------------------------------+
bool WriteMAE_MFE(double MFE_Array[],double MAE_Array[],int TicketsArray[],string FileName)
   {
   bool res=true;
   int i,FH,total=ArraySize(TicketsArray);
   string Line;
//----
   if (total==0) return(false);
   Print("Êîëè÷åñòâî ñòðîê â òàáëèöå MAE_MFE ðàâíî ",total);
   FH=FileOpen(FileName,FILE_READ|FILE_WRITE|FILE_CSV); 
   if (FH>0)
      {
      FileWrite(FH,"Ticket #","MFE","P&L","MAE","P&L");
      for (i=0;i<total;i++) 
         if (OrderSelect(TicketsArray[i],SELECT_BY_TICKET))
            {
            FileSeek(FH,0,SEEK_END);
            FileWrite(FH,OrderTicket(),MFE_Array[i],OrderProfit(),MAE_Array[i],OrderProfit());
            }
      FileClose(FH);
      }
   else res=false;
//----
   return(res);
   }
   
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
  int ClosedOrders, CancelledOrders;      // êîëè÷åñòâî îòêðûòûõ è îòìåíåííûõ îðäåðîâ
  int ClosedTickets[],CancelledTickets[]; // ìàñèâû, ñîäåðæàùèå òèêåòû çàêðûòûõ è îòìåíåííûõ îðäåðîâ
  int AllOpenedOrdersTickets[];           // ìàññèâ çàðêûòûõ îðäåðîâ èç èñòîðèè + òåêóùèå íåçàêðûòûå îðäåðà
  string Symbols[];                       // ìàññèâ, â êîòîðîì õðàíÿòñÿ èìåíà ñèìâîëîâ, ïî êîòîðûì áûëè ñäåëêè
  double Swaps[];                         // ñîáñòâåííî, ñâîïû
  double Profits[],NormalizedProfits[];   // ìàññèâû, õðàíÿùèå èçíà÷àëüíûå ïðîôèòû è íîðìàëèçîâàííûå ê 0.1 ëîòó
  double MFE[];                           // ìàññèâ, ñîäåðæàùèé äàííûå î ìàêñèìàëüíîé ïîòåíöèàëüíîé ïðèáûëè äëÿ êàæäîãî îðäåðà
  double MAE[];                           // ìàññèâ, ñîäåðæàùèé äàííûå î ìàêñèìàëüíîé ïðîñàäêå äëÿ êàæäîãî îðäåðà
  double AccountDetails[][9]; 
  double MinimalEquity;                   // ìèíèìàëüíîå èñòîðè÷åñêîå çíà÷åíèå Ýêâèòè
  double MoneyDrawDown;                   // ìàêñèìàëüíàÿ äåíåæíàÿ ïðîñàäêà
  double MoneyDrawDownInPercent;          // ïðîöåíòíîå âûðàæåíèå äëÿ ìàêñèìàëüíîé äåíåæíîé ïðîñàäêè
  double RelativeDrawDown;                // ìàêñèìàëüíàÿ ïðîöåíòíàÿ ïðîñàäêà
  double RelativeDrawDownInMoney;         // äåíåæíîå âûðàæåíèå ìàêñèìàëüíîé ïðîöåíòíîé ïðîñàäêè
//----
   
   if (!GetNumberOfOrders(ClosedOrders, CancelledOrders,Symbols))
      {
      Print("Îðäåðà â èñòîðèè íå íàéäåíû, îáðàáîòêà ïðåêðàùåíà");
      }
   ArrayResize(ClosedTickets,ClosedOrders);
   ArrayResize(CancelledTickets,CancelledOrders);
   ArrayResize(AccountDetails,ClosedOrders);
   ArrayResize(Swaps ,ClosedOrders);
  
   LoadSortedTickets(ClosedTickets);
   FillOrderProfits(Profits,NormalizedProfits,Swaps,ClosedTickets);
      
   if (CheckHistoryOnClosedOrders(ClosedTickets,Symbols))   // ïðîâåðèì íà íàëè÷èå äûð â èñòîðèè
      {
      SetMAEAndMFE(MFE,MAE,ClosedTickets);                  // è åñëè äûð íåò - çàïîëíèì MAE è MFE
      WriteMAE_MFE(MFE,MAE,ClosedTickets,"MAE_MFE_reports\\"+AccountNumber()+"_MAE_MFE.csv");
      }
   else return;
   
   CalculateDD(ClosedTickets,Symbols,MinimalEquity,MoneyDrawDown,MoneyDrawDownInPercent,RelativeDrawDown,RelativeDrawDownInMoney);
   Print("AbsDD=",10000-MinimalEquity," MoneyDrawDown=",MoneyDrawDown,"  MoneyDrawDownInPercent=",MoneyDrawDownInPercent,
      "  RelativeDrawDown=",RelativeDrawDown," RelativeDrawDownInMoney=",RelativeDrawDownInMoney);
//----
   return(0);
  }
//+------------------------------------------------------------------+
             
            
            
            
Comments