MAE_MFE_DrawDowns

Author: Copyright � 2007, MetaQuotes Software Corp.
Price Data Components
Series array that contains open prices of each barSeries array that contains the highest prices of each barSeries array that contains the lowest prices of each barSeries array that contains open time of each bar
Orders Execution
Checks for the total of closed ordersChecks for the total of open orders
Miscellaneous
It issuies visual alerts to the screenUses files from the file systemIt writes information to file
1 Views
0 Downloads
0 Favorites
MAE_MFE_DrawDowns
//+------------------------------------------------------------------+
//|                                            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