Price Data Components
Orders Execution
Miscellaneous
0
Views
0
Downloads
0
Favorites
MAE_MFE_DrawDowns_v1
//+------------------------------------------------------------------+
//| 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/"
// pasted from the SummaryReport script
#define OP_BALANCE 6
#define OP_CREDIT 7
#define StatParameters 8
// pasted from the SummaryReport script
#property show_inputs
#property strict
extern int MaxTimeMissed=15; // max allowed gap in loaded M1 history
//+------------------------------------------------------------------+
//| Fill the MAE arrays in deposit currency |
//+------------------------------------------------------------------+
bool SetMAEAndMFE(double &MFE_Array[],double &MAE_Array[],const int &TicketsArray[])
{
bool res=false;
//----
int bar,i,limit=ArraySize(TicketsArray);
ArrayResize(MAE_Array,limit);
ArrayResize(MFE_Array,limit);
int openShift,closeShift;
int type,znak,K_spread;
double spread,symPoint;
double MFE_points,MAE_points;
double currProfit,currLoss;
double buy,sell,OPrice,PointCost;
double deltaPricePoints;
//----
//Print("Step into 1");
for(i=0;i<limit;i++)
{
//Print("Step into 2");
if(OrderSelect(TicketsArray[i],SELECT_BY_TICKET))
{
openShift=iBarShift(OrderSymbol(),PERIOD_M1,OrderOpenTime());
closeShift=iBarShift(OrderSymbol(),PERIOD_M1,OrderCloseTime());
//Print("History to calculate MFE by order #",TicketsArray[i]," there are ",openShift-closeShift," M1 bars, time in minutes ",DoubleToStr((OrderCloseTime()-OrderOpenTime())/60.0,0));
//if (openShift==-1 || closeShift==-1) Print("Not enough history to calculate MFE by order #",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("If there will be division by zero in the SetMAEAndMFE function, profit will be equal to zero");
PointCost=MarketInfo(OrderSymbol(),MODE_POINT)*MarketInfo(OrderSymbol(),MODE_LOTSIZE);
string first =StringSubstr(OrderSymbol(),0,3); // first symbol, e.g. EUR
string second =StringSubstr(OrderSymbol(),3,3); // second symbol, e.g. USD
string currency=AccountCurrency(); // deposit currency, e.g. 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("Order #",TicketsArray[i]," opened by price ",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% For order #",TicketsArray[i]," by symbol ",OrderSymbol()," openShift=",openShift," closeShift=",closeShift," problem accessing iHigh(OrderSymbol(),PERIOD_M1,bar) by time ",TimeToStr(iTime(OrderSymbol(),PERIOD_M1,bar)));
if(iLow(OrderSymbol(),PERIOD_M1,bar)==0) Print("2%For order #",TicketsArray[i]," by symbol ",OrderSymbol()," openShift=",openShift," closeShift=",closeShift," problem accessing iLow(OrderSymbol(),PERIOD_M1,bar) by time ",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("Failed to select order #",TicketsArray[i]);
}
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| Fills values of profits and losses |
//+------------------------------------------------------------------+
void FillOrderProfits(double &ProfitsArray[],double &NormalizedProfitsArray[],double &SwapArray[],const 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("Found order with zero value of lot #",TicketsArray[i]);
}
else
{
Alert("Failed to select order #",TicketsArray[i]);
}
}
//----
return;
}
//+------------------------------------------------------------------+
//| Returns array of tickets sorted by close time |
//+------------------------------------------------------------------+
int LoadSortedTickets(int &Tickets[])
{
int i,counter=0;
int TicketAndTime[][2];
//----
if(ArraySize(Tickets)==0) return(0);
ArrayResize(TicketAndTime,OrdersHistoryTotal());
for(i=0;i<OrdersHistoryTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
{
if(OrderType()<=OP_SELL)
{
TicketAndTime[counter][0]=(int)OrderCloseTime();
TicketAndTime[counter][1]=(int)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);
}
//+------------------------------------------------------------------+
//| Returns true, if symbol with the symbolName is already present |
//+------------------------------------------------------------------+
bool AddSymbol(string &SimbolListArray[],string symbolName)
{
bool res=false;
int size=ArraySize(SimbolListArray);
//----
//Print("Add symbol ",symbolName);
ArrayResize(SimbolListArray,size+1);
if(ArraySize(SimbolListArray)==size+1)
{
SimbolListArray[size]=StringTrimLeft(StringTrimRight(symbolName));
res=true;
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| Returns true, if symbol with the symbolName is already present |
//+------------------------------------------------------------------+
bool SymbolFoundInArray(const 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("Finding new symbol in array ended up with surprise");
//Print("first=|",SimbolListArray[i],"| second=|",symbolName,"|");
}
res=true;
break;
}
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| Calculates number of open and canceled orders |
//+------------------------------------------------------------------+
bool GetNumberOfOrders(int &Closed,int &Cancelled,string &SymbolsArray[])
{
bool res=false;
//Print("Orders in history ",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);
}
//+------------------------------------------------------------------+
//| Returns index of the found FindName string |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| Check M1 history for gaps |
//+------------------------------------------------------------------+
bool CheckHistoryOnClosedOrders(int &ClosedTicketsArray[],string &SymbolsForClosedOrders[])
{
bool res=true;
int errors[][3]; // first element - index of symbol, second - ticket of order, third - date/time of error
ArrayResize(errors,1000);
int errCounter=0; // errors counter
int openBar_M1=iBarShift(OrderSymbol(),PERIOD_M1,OrderOpenTime());
int closeBar_M1=iBarShift(OrderSymbol(),PERIOD_M1,OrderCloseTime());
int TimeInterval[][2];// first element - start date of gap, second element - end date of gap
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]=(int)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)
{
if(errCounter==ArraySize(errors)/3)
{
ArrayResize(errors,errCounter+10);
}
errors[errCounter][0]=indexSymbol;
errors[errCounter][1]=ClosedTicketsArray[i];
errors[errCounter][2]=(int)OrderOpenTime();
res=false;
if(OrderOpenTime()<TimeInterval[indexSymbol][0]) TimeInterval[indexSymbol][0]=(int)OrderOpenTime();
if(OrderOpenTime()>TimeInterval[indexSymbol][1]) TimeInterval[indexSymbol][1]=(int)OrderOpenTime();
//Print("Error finding the opening bar on symbol ",OrderSymbol()," M1 for order #",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]=(int)OrderCloseTime();
res=false;
if(OrderCloseTime()<TimeInterval[indexSymbol][0]) TimeInterval[indexSymbol][0]=(int)timeClose;
if(OrderCloseTime()>TimeInterval[indexSymbol][1]) TimeInterval[indexSymbol][1]=(int)timeClose;
Print("Error finding the closing bar on symbol ",OrderSymbol()," M1 for order #",ClosedTicketsArray[i],"=>",TimeToStr(timeClose));
errCounter++;
}
}
}
//----
if(!res)
{
Alert("Found errors of M1 gaps in available history, when checking account - ",errCounter,"! See the Journal tab for more details");
for(i=0;i<number_symbols;i++)
{
if(TimeInterval[i][0]*TimeInterval[i][1]!=0) Print("Not enough history for ",SymbolsForClosedOrders[i]," on the interval: ",TimeToStr(TimeInterval[i][0]),"-",TimeToStr(TimeInterval[i][1]));
}
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| Calculate all drawdowns |
//+------------------------------------------------------------------+
bool CalculateDD(int &ClosedTicketsArray[],string &SymbolsArray[],double &minEquity,double &MoneyDD,
double &MoneyDDPer,double &RelativeDD,double &RelativeDDMoney)
{
bool res=false;
//----
int AllOpenedOrdersTickets[]; // array of closed orders from history + currently open orders
int ConveyerArray[][2]; // first element - time, second - ticket
//----
int i,k=0,marketOrders=0;
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,", orders in history=",ArraySize(ClosedTicketsArray));
if(ArraySize(ClosedTicketsArray)+marketOrders==0)
{
Print("No orders for processing");
}
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("Failed to select order!!!");
}
k++;
}
}
if(!CheckHistoryOnClosedOrders(AllOpenedOrdersTickets,SymbolsArray)) return(false);
ArrayResize(ConveyerArray,ArraySize(AllOpenedOrdersTickets)*2);
//Print("Size of conveyor=",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]=(int)OrderOpenTime();
ConveyerArray[2*i][1]=AllOpenedOrdersTickets[i];
if(OrderCloseTime()!=0) ConveyerArray[2*i+1][0]=(int)OrderCloseTime();
else ConveyerArray[2*i+1][0]=(int)TimeCurrent()+200;
ConveyerArray[2*i+1][1]=-AllOpenedOrdersTickets[i];
}
else Alert("Failed to select orders when calculating drawdowns!!!");
}
ArraySort(ConveyerArray); // sort conveyor by time of events: opening-closing orders
//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; // initial deposit value equals to 10 000
double minimalEquity=balance; // initial deposit value equals to 10 000
double lastPeak=balance; // last maximum of equity
double lastMin=balance; // last minimum of equity
double equity; // current equity
double MaxProfit,MinProfit,FixedProfit;
double currDD,lastmaxDD=0,currPercentDD,lastPercentDD=0;
int curr_pos;
int stack[];
datetime curr_minute;
equity=balance;
int FileHandle;
// Print("Start date ",TimeToStr(startTrade,TIME_DATE|TIME_SECONDS),
// ", end date ",TimeToStr(stopTrade,TIME_DATE|TIME_SECONDS));
FileHandle=FileOpen(IntegerToString(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;
RelativeDDMoney=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);
}
//+------------------------------------------------------------------+
//| Summarize profits by opened tickets |
//+------------------------------------------------------------------+
bool CheckAllProfits(const int &stackTickets[],double &maxProfit,double &minProfit,datetime this_minute)
{
bool res=false;
maxProfit=0;
minProfit=0;
double thisOrderMaxProfit,thisOrderMinProfit;
//----
int i;
for(i=0;i<ArraySize(stackTickets);i++)
{
if(GetProfit(stackTickets[i],thisOrderMaxProfit,thisOrderMinProfit,this_minute))
{
//Print("Calculated profit for order #",stackTickets[i]," at ",TimeToStr(this_minute));
//Print("thisOrderMaxProfit=",thisOrderMaxProfit," thisOrderMinProfit=",thisOrderMinProfit);
maxProfit+=thisOrderMaxProfit;
minProfit+=thisOrderMinProfit;
}
else Print("Failed to determine current profit for order #",stackTickets[i]);
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| Returns minimum/maximum profit for order |
//+------------------------------------------------------------------+
bool GetProfit(int ticket,double &maxProf,double &minProf,datetime at_minute)
{
bool res=true;
//----
string symbol,crossPair,firstCurrency,secondCurrency,baseCurrency=AccountCurrency();
int bar,type,err;
double openPrice,spread,point,pointCost=0,lots,price;
datetime foundedTime;
minProf=0;
maxProf=0;
//Print("Get value of profit for order #",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("Cross ",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("Error accessing price ",crossPair," M1 at ",TimeToStr(at_minute));
}
//Print("Point cost for order #",ticket," is ",pointCost);
if(foundedTime!=TimeRoundeMinute(at_minute))
{
//Print("Error of time mismatch for ",symbol," M1 at ",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("Failed to select order #",ticket," at ",TimeToStr(at_minute),". GetProfit() function");
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| Close needed orders and return result of closed orders |
//+------------------------------------------------------------------+
bool CloseTickets(int &stackTickets[],datetime this_minute,double &fixedProfit)
{
bool res=false;
//----
int toCloseTickets[];
int closedCounter=0;
fixedProfit=0;
for(int 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("Remove from stack order #",stackTickets[i]," at ",TimeToStr(this_minute));
closedCounter++;
}
}
}
if(closedCounter>0)
{
res=true;
for(int i=0;i<closedCounter;i++)
{
if(!DeleteTicketFromStack(stackTickets,toCloseTickets[i])) Print("Failed to delete order #",toCloseTickets[i]);
if(!DeleteTicketFromStack(stackTickets,-toCloseTickets[i])) Print("Failed to delete order #",-toCloseTickets[i]);
}
GetLastError();
ArrayResize(toCloseTickets,0);
if(GetLastError()>0) Print("Error setting zero size of array");
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| Deletes closed orders from stack |
//+------------------------------------------------------------------+
bool DeleteTicketFromStack(int &OpenedTicketsArray[],int ñlosedTicket)
{
bool res=false;
//----
int i,pos,size=ArraySize(OpenedTicketsArray);
for(i=0;i<size;i++)
{
if(OpenedTicketsArray[i]==ñlosedTicket)
{
pos=i;
break;
}
}
GetLastError();
OpenedTicketsArray[pos]=OpenedTicketsArray[size-1];
ArrayResize(OpenedTicketsArray,size-1); // remove last element
if(GetLastError()==0) res=true;
//----
return(res);
}
//+------------------------------------------------------------------+
//| Add TicketNumber to the Array 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);
}
//+------------------------------------------------------------------+
//| Proceed operations with tickets stack of opened orders |
//+------------------------------------------------------------------+
void SetStack(int &stackArray[],const int &Conveyer[][],datetime this_minute,int &conveyer_pos)
{
//----
int list=ArrayRange(Conveyer,0);
//----
while((TimeRoundeMinute(this_minute)==TimeRoundeMinute(Conveyer[conveyer_pos][0])))
{
AddTicketToStack(stackArray,Conveyer[conveyer_pos][1]);
//Print("Add to stack order #",Conveyer[conveyer_pos][1]," at ",TimeToStr(this_minute));
conveyer_pos++;
if(conveyer_pos>=ArrayRange(Conveyer,0))
{
break;
}
}
//----
return;
}
//+------------------------------------------------------------------+
//| Add tickets once again opened orders |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| Round date with minute precision |
//+------------------------------------------------------------------+
datetime TimeRoundeMinute(datetime in)
{
datetime res;
//----
res=StrToTime(TimeToStr(in,TIME_DATE|TIME_MINUTES));
//----
return(res);
}
//+------------------------------------------------------------------+
//| Write table of profits and corresponding MAE and MFE |
//+------------------------------------------------------------------+
bool WriteMAE_MFE(const double &MFE_Array[],const double &MAE_Array[],const int &TicketsArray[],string FileName)
{
bool res=true;
int i,FH,total=ArraySize(TicketsArray);
string Line;
//----
if(total==0) return(false);
Print("Number of rows in MAE_MFE table is ",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()
{
Print(AccountName());
int ClosedOrders, CancelledOrders; // number of opened and canceled orders
int ClosedTickets[],CancelledTickets[]; // arrays of tickets of closed and canceled orders
int AllOpenedOrdersTickets[]; // array of closed orders from history + currently open orders
string Symbols[]; // array of symbols by which there were deals
double Swaps[]; // swaps
double Profits[],NormalizedProfits[]; // arrays of initial profits and profits normalized to 0.1 lot
double MFE[]; // array of maximum potential profits for each order
double MAE[]; // array of maximum drawdowns for each orders
double AccountDetails[][9];
double MinimalEquity; // minimum historical value of equity
double MoneyDrawDown; // maximum money drawdown
double MoneyDrawDownInPercent; // maximum money drawdown in percents
double RelativeDrawDown; // maximum relative drawdown
double RelativeDrawDownInMoney; // maximum relative drawdown in money
//----
if(!GetNumberOfOrders(ClosedOrders,CancelledOrders,Symbols))
{
Print("No orders found in history, processing has been canceled");
}
//----
ArrayResize(ClosedTickets,ClosedOrders);
ArrayResize(CancelledTickets,CancelledOrders);
ArrayResize(AccountDetails,ClosedOrders);
ArrayResize(Swaps,ClosedOrders);
//----
LoadSortedTickets(ClosedTickets);
FillOrderProfits(Profits,NormalizedProfits,Swaps,ClosedTickets);
if(CheckHistoryOnClosedOrders(ClosedTickets,Symbols)) // check for gaps in history
{
SetMAEAndMFE(MFE,MAE,ClosedTickets); // if there are now gaps - fill MAE and MFE
WriteMAE_MFE(MFE,MAE,ClosedTickets,"MAE_MFE_reports\\"+IntegerToString(AccountNumber())+"_MAE_MFE.csv");
}
else return (0);
//----
CalculateDD(ClosedTickets,Symbols,MinimalEquity,MoneyDrawDown,MoneyDrawDownInPercent,RelativeDrawDown,RelativeDrawDownInMoney);
Print("AbsDD=",10000-MinimalEquity," MoneyDrawDown=",MoneyDrawDown," MoneyDrawDownInPercent=",MoneyDrawDownInPercent,
" RelativeDrawDown=",RelativeDrawDown," RelativeDrawDownInMoney=",RelativeDrawDownInMoney);
//----
return(0);
}
//+------------------------------------------------------------------+
Comments
Markdown Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---