//+------------------------------------------------------------------+
//| TesterEquity.mq4 | v.1.0
//| Copyright 2013, Navoykov Alexey |
//| alemail@yandex.ru |
//+------------------------------------------------------------------+
#property copyright "Navoykov Alexey"
#property link "alemail@yandex.ru"
#property indicator_separate_window
#property indicator_buffers 7
#import "user32.dll"
int GetParent (int hWnd);
int GetAncestor (int hwnd, int gaFlags);
int GetDlgItem (int hDlg, int nIDDlgItem);
#import "kernel32.dll"
int lstrcpyn (string a, string b, int count); // èñïîëüçóåì äëÿ ïîëó÷åíèÿ àäðåñà ñòðîêè
int lstrcpynA (int a[], int b[], int count); // èñïîëüçóåì äëÿ ïîëó÷åíèÿ àäðåñà ìàññèâà int
int lstrcpynW (double a[], double b[], int count); // èñïîëüçóåì äëÿ ïîëó÷åíèÿ àäðåñà ìàññèâà double
#import "msvcrt.dll"
int fopen (string filename, string mode);
int fclose (int stream);
int fread (int ptr, int size, int count, int stream);
int fgets (string str, int num, int stream);
int memcpy (int destination, int source, int size);
#include <WinUser32.mqh>
//========= ÂÍÅØÍÈÅ ÏÀÐÀÌÅÒÐÛ ===============================
extern bool ChartMode_Profit = 1;
extern string Spread = "";
extern string Comission = "";
extern string Swap = "";
extern bool ReverseTrades = 0;
extern bool RealTickValue = 0;
extern bool AddSkippedTicks = 0; //true;
extern color ChartColor = Aqua;
extern color TextColor = White;
extern bool SaveToFile = 0;
extern string FileName = "TesterEquity__%expert%__%symbol%.csv";
extern bool FileType_Binary = 0;
extern string FileDelimiter = ";";
//==========================================================
#define GA_ROOT 2
#define CB_GETCURSEL 0x0147
#define LVM_GETITEMCOUNT 4100
#define LVM_GETITEMTEXT 4141
#define LVIF_TEXT 1
#define MODE_SWAP3DAY 50
#define MODE_COMISSION 52
#define MODE_COMISSIONTYPE 53
#define MODE_COMISSIONPERDEAL 54
//#define MODE_BASECURRENCYVALUE 55
//#define MODE_MARGINCURRENCYVALUE 56
//#define MODE_QUOTECURRENCYVALUE 56
double BufferOpen[], BufferLow[], BufferHigh[], BufferClose[], BufferShadow[], BufferVolume[], BufferFuture[];
string ComissionType="";
string LabelCaption[3];
string LabelResults[10];
string DrowdownMark[2]= { "TesterEquity_AbsoluteDrowdown", "TesterEquity__RelativeDrowdown" };
string IndicatorName="";
string IndicatorPrefix= "TesterEquity";
string ModelName[3]= { "Âñå òèêè", "Êîíòðîëüíûå òî÷êè", "Öåíû îòêðûòèÿ" };
string ExpertName="";
int Window=0;
int FutureBufferShift=0;
bool ThisIndicator=0;
string MySymbols[];
int MySymbolsCount=0;
double MySymbolsParam[][4];
#define _Spread 0
#define _Comission 1
#define _ComissionType 2
#define _Swap 3
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
}
//--------------------------------------------------------------------
int IndicatorInit()
{
SetIndexBuffer(0, BufferHigh);
SetIndexBuffer(1, BufferLow);
SetIndexBuffer(2, BufferShadow);
SetIndexBuffer(4, BufferOpen);
SetIndexBuffer(5, BufferClose);
SetIndexStyle(0, DRAW_HISTOGRAM, STYLE_SOLID, 1, ChartColor);
SetIndexStyle(1, DRAW_HISTOGRAM, STYLE_SOLID, 1, ChartColor);
SetIndexStyle(2, DRAW_HISTOGRAM, STYLE_SOLID, 1, Black);
SetIndexStyle(4, DRAW_ZIGZAG, STYLE_SOLID, 1, ChartColor);
SetIndexStyle(5, DRAW_ZIGZAG, STYLE_SOLID, 1, ChartColor);
SetIndexLabel(0, "High");
SetIndexLabel(1, "Low");
SetIndexLabel(2, "Shadow");
SetIndexLabel(4, "Open");
SetIndexLabel(5, "Close");
/*
if (ChartMode_Volume)
{
SetIndexBuffer(0, BufferVolume);
SetIndexStyle(0, DRAW_HISTOGRAM, STYLE_SOLID, 1, Color);
SetIndexLabel(0, "Volume");
}*/
SetIndexBuffer(3, BufferFuture);
SetIndexStyle(3, DRAW_SECTION, STYLE_SOLID, 1, ChartColor);
SetIndexLabel(3, "Close2");
FutureBufferShift= MathMin(Bars-1, PERIOD_D1*365/Period());
SetIndexShift(3, FutureBufferShift);
IndicatorName= "TesterEquity";
if (ChartMode_Profit) IndicatorName= "TesterProfit";
//if (ChartMode_Volume) IndicatorName= "TesterVolume";
//IndicatorName= IndicatorName+" "+GetTickCount();
IndicatorShortName(IndicatorName);
IndicatorDigits(2);
return(0);
TesterSetSpread(0); // ôóíêöèè èñïîëüçóåìûå äëÿ ýêñïîðòà â äðóãèå ñîâåòíèêè
TesterSetComission(0);
TesterSetComissionType(0);
TesterSetSwap(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
if (!ThisIndicator) return(0);
for (int i=0; i<ArraySize(LabelCaption); i++)
if (StringLen(LabelCaption[i])>0) ObjectDelete(LabelCaption[i]);
for (i=0; i<ArraySize(LabelResults); i++)
if (StringLen(LabelResults[i])>0) ObjectDelete(LabelResults[i]);
ObjectDelete(DrowdownMark[0]);
ObjectDelete(DrowdownMark[1]);
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
static bool firststart=true;
if (firststart)
{
IndicatorInit();
MySymbols_FillAllParameters();
firststart=false;
}
int hparent= GetParent(WindowHandle(Symbol(),Period()));
if (GetWindow(hparent,GW_HWNDFIRST) !=hparent || hparent==0) return(0); // òåêóùèé ãðàôèê íå ÿâëÿåòñÿ àêòèâíûì ãðàôèêîì
ThisIndicator=true;
Window= WindowFind(IndicatorName);
if (Window>=0)
{
for (int i=ArraySize(LabelCaption)-1; i>=0; i--)
LabelCaption[i]= IndicatorPrefix+Window+"LabelCaption"+i;
for (i=ArraySize(LabelResults)-1; i>=0; i--)
LabelResults[i]= IndicatorPrefix+Window+"LabelResult"+i;
}
static bool IsCounted=0;
if (IndicatorCounted()>0 && IsCounted==true) return(0);
static int countedtime=0;
if (TimeLocal()-countedtime <2) return(0); // ïåðåñ÷¸ò íå ÷àùå ÷åì ðàç â 2 ñåêóíäû
countedtime= TimeLocal();
//static bool initstart= true;
//if (UninitializeReason()==REASON_CHARTCHANGE && initstart) { Alert(IndicatorCounted()); initstart=false; IsCounted=true; return(0); }
double Equity[1000][6];
int equitybars= GetTesterEquity(Equity, ChartMode_Profit, 0);
DrawIndicatorBuffers(Equity, equitybars);
SetLevelValue(0, Equity[equitybars-1][4]);
SetLevelStyle(DRAW_LINE, 1, Gray);
IsCounted=true;
return(0);
}
//-----------------------------------------
int GetTesterEquity(double& Equity[][], bool mode_profit=false, int startpos=0)
{
Initialize(BufferOpen, EMPTY_VALUE);
Initialize(BufferClose, EMPTY_VALUE);
Initialize(BufferHigh, EMPTY_VALUE);
Initialize(BufferLow, EMPTY_VALUE);
Initialize(BufferShadow, EMPTY_VALUE);
Initialize(BufferFuture, EMPTY_VALUE);
double deposit=0;
if (!mode_profit) // && !ChartMode_Volume)
GetReportParameters(deposit);
string expert="";
string symbol="";
int period=0;
int model=0;
if (! GetTesterParameters(expert, symbol, period, model)) return(0);
ExpertName=expert;
string file= TerminalPath() +"\\Tester\\History\\" +symbol +period +"_" +model +".fxt";
double Trades[100][5];
int tradescount= GetTrades(Trades);
if (tradescount==0) return(0);
ArrayResize(Trades, tradescount);
double History[1000][5];
double symbolinfo[100];
string currencies[3];
//int ticks=GetTickCount();
int historysize= GetFxtHistory(file, History, symbolinfo, currencies, AddSkippedTicks);
//Print(GetTickCount()-ticks," ms");
if (historysize==0) return(0);
ArrayResize(History, historysize);
Print(symbol," fxt history loaded: ", historysize, " ticks (", NormalizeDouble(ArraySize(History)*8/1024.0, 1), " kb)");
double drowdown[2];
int drowdowntime[2];
currencies[2]= GetDepoCurrency();
int equitybars= CreateEquity(symbol, symbolinfo, currencies, deposit, History, Trades, Equity, startpos, drowdown, drowdowntime);
if (!ThisIndicator) return(equitybars);
ArrayResize(Equity, equitybars);
int AbsDrowdownTime= drowdowntime[0];
int RelDrowdownTime= drowdowntime[1];
if (AbsDrowdownTime>0)
{
int absdrowdownbar= ArrayBsearch(Equity, AbsDrowdownTime);
DrawText(DrowdownMark[0], AbsDrowdownTime, Equity[absdrowdownbar][2], "_____", Red, 4);
}
if (RelDrowdownTime>0)
{
int reldrowdownbar= ArrayBsearch(Equity, RelDrowdownTime);
DrawText(DrowdownMark[1], RelDrowdownTime, Equity[reldrowdownbar][2], "_____", Orange, 4);
}
string periodnames[]= { "M1", "M5", "M15", "M30", "H1", "H4", "D1", "W1" };
int periods[]= { 1, 5, 15, 30, 60, PERIOD_H4, PERIOD_D1, PERIOD_W1 };
int periodindex= ArrayBsearch(periods, period);
DrawLabel(LabelCaption[0], 5, 15, 0, expert, 8, "Arial", TextColor);
DrawLabel(LabelCaption[1], 5, 30, 0, symbol+", "+periodnames[periodindex], 7, "Arial", TextColor);
DrawLabel(LabelCaption[2], 5, 43, 0, ModelName[model], 7, "Arial", TextColor);
DrawLabel(LabelResults[0], 5, 5, 1, StringConcatenate("Profit: ",NormalizeDouble(Equity[equitybars-1][4]-deposit, 2)), 7, "Arial", TextColor);
DrawLabel(LabelResults[1], 5, 20, 1, StringConcatenate("MaxDD: ", NormalizeDouble(drowdown[0], 2)), 7, "Arial", TextColor);
if (SaveToFile)
{
StringReplace(FileName, "%expert%", expert);
StringReplace(FileName, "%symbol%", symbol);
StringReplace(FileName, "%period%", period);
int delimiter = StringGetChar(FileDelimiter,0);
if (delimiter==0) delimiter= '\t';
if (FileType_Binary) WriteEquityToBinaryFile(Equity, equitybars, FileName);
else WriteEquityToTextFile(Equity, equitybars, FileName, delimiter);
}
return(equitybars);
}
//-------------------------------------------
int CreateEquity(string symbol, double symbolinfo[], string currencies[], double deposit, double History[][], double& Trades[][],
double& Equity[][], int startpos, double &drowdown[2], int &drowdowntime[2]) //int& absdrowdowntime, int& reldrowdowntime)
{
double point = symbolinfo[MODE_POINT];
double ticksize = symbolinfo[MODE_TICKSIZE];
double tickvalue = symbolinfo[MODE_TICKVALUE];
int profitcalcmode = symbolinfo[MODE_PROFITCALCMODE];
double swaptype = symbolinfo[MODE_SWAPTYPE];
double swaplong = symbolinfo[MODE_SWAPLONG];
double swapshort = symbolinfo[MODE_SWAPSHORT];
int swap3day = symbolinfo[MODE_SWAP3DAY];
double comission = symbolinfo[MODE_COMISSION];
int comissiontype = symbolinfo[MODE_COMISSIONTYPE];
bool comissionperdeal = symbolinfo[MODE_COMISSIONPERDEAL];
//Alert(comissiontype);
string maincurrency= currencies[0];
string margincurrency= currencies[1];
string depocurrency= currencies[2];
string basecurrency= "";
string quotecurrency= maincurrency;
if (profitcalcmode==0) // Forex
{
basecurrency= maincurrency;
quotecurrency= StringSubstr(symbol,3,3);
}
if (profitcalcmode <2) // Forex èëè CFD
{
ticksize= symbolinfo[MODE_POINT];
tickvalue= symbolinfo[MODE_LOTSIZE] * ticksize; // ñòîèìîñòü òèêà â âàëþòå êîòèðîâàíèÿ
}
string CurrArray[4];
CurrArray[0]= basecurrency;
CurrArray[1]= quotecurrency;
CurrArray[2]= margincurrency;
CurrArray[3]= depocurrency;
int basecurr= ArrayStringSearch(CurrArray, basecurrency);
int margincurr= ArrayStringSearch(CurrArray, margincurrency);
int quotecurr= ArrayStringSearch(CurrArray, quotecurrency);
int depocurr= ArrayStringSearch(CurrArray, depocurrency);
double basecurrvalue = GetCurrencyPrice(basecurrency, depocurrency); // ñòîèìîñòü áàçîâîé âàëþòû â âàëþòå äåïîçèòà
double quotecurrvalue = GetCurrencyPrice(quotecurrency, depocurrency); // ñòîèìîñòü âàëþòû êîòèðîâàíèÿ â âàëþòå äåïîçèòà
double margincurrvalue = GetCurrencyPrice(margincurrency, depocurrency); // ñòîèìîñòü çàëîãîâîé âàëþòû â âàëþòå äåïîçèòà
if (ticksize==0) { Print("Íóëåâîé ðàçìåð òèêà!"); return(0); }
double pointvalue0= point / ticksize * tickvalue;
double pointvalue= pointvalue0;
if (basecurrency !=depocurrency && !RealTickValue) { tickvalue *= quotecurrvalue; pointvalue*=quotecurrvalue; }
//double basecurrvalue0= basecurrvalue;
//double margincurrvalue0= margincurrvalue;
int historysize= ArrayRange(History,0);
int tradescount= ArrayRange(Trades,0);
int myspread= EMPTY_VALUE;
string paramtxt="";
string checksymbols[2];
checksymbols[0]= symbol;
checksymbols[1]= "";
//Alert(swaplong," ",swapshort," ",swaptype);
for (int s=0; s<=1; s++)
{
int symindex= ArrayStringSearch(MySymbols, checksymbols[s], MySymbolsCount);
if (symindex<0) continue;
if (MySymbolsParam[symindex][_Spread] != EMPTY_VALUE) { myspread= MySymbolsParam[symindex][_Spread]; paramtxt=paramtxt+" MySpread: "+myspread+" pip"; }
if (MySymbolsParam[symindex][_Comission] != EMPTY_VALUE) { comission= MySymbolsParam[symindex][_Comission]; paramtxt=StringConcatenate(paramtxt," MyComission: ",comission); }
if (MySymbolsParam[symindex][_ComissionType] != EMPTY_VALUE) { comissiontype= MySymbolsParam[symindex][_ComissionType]; paramtxt=paramtxt+" MyComisType: "+comissiontype; }
if (MySymbolsParam[symindex][_Swap] != EMPTY_VALUE) { swaplong= MySymbolsParam[symindex][_Swap]; swapshort=-swaplong; paramtxt=StringConcatenate(paramtxt," MySwap: ",swaplong,"/",swapshort); }
}
double askshift=0;
if (myspread!=EMPTY_VALUE) askshift= (myspread - symbolinfo[MODE_SPREAD])* point;
if (askshift!=0 || ReverseTrades)
for (int t=0; t<tradescount; t++)
{
if (ReverseTrades)
{
Trades[t][1]= !Trades[t][1];
if (Trades[t][1]==OP_BUY) Trades[t][3]+= symbolinfo[MODE_SPREAD]* point;
else Trades[t][3]-= symbolinfo[MODE_SPREAD]* point;
}
if (Trades[t][1]==OP_BUY) Trades[t][3]+=askshift;
}
if (ReverseTrades) paramtxt= "ReversedTrades"+paramtxt;
if (paramtxt!="") paramtxt= " ("+StringTrimLeft(paramtxt)+")";
//Alert("point: ",point,"\n","tick: size ",ticksize," value ",tickvalue,"\n","Swap: type ",swaptype," long ",swaplong," short ",swapshort," 3day ",swap3day,"\n",
// "comission: ",comission," type ",comissiontype," deal ",comissiondeal);
int n = startpos-1;
double netposlots=0;
double tradeprice[2]={ 0, 0 };
double equity= deposit;
double typelots[2]= { 0, 0 };
int trade=0;
double swaps=0;
double comissions=0;
double sumlots=0;
double highequity= deposit;
double absdrowdown=0;
double reldrowdown=0;
ArrayInitialize(drowdowntime, 0);
int lasttime=0;
int lastminute=0;
//int ticks= GetTickCount();
double balance= deposit;
double spread= symbolinfo[MODE_SPREAD] * point;
//string txt="";
//Alert(ticksize," ",tickvalue);
double swappointvalue= -1;
double CrossPrices[];
int CrossPricesCount=0;
int CrossReverse=0;
string Cross="";
//int ticks= GetTickCount();
if (RealTickValue && quotecurrency !=depocurrency && basecurrency !=depocurrency)
for (CrossReverse=0; CrossReverse<=1; CrossReverse++)
{
Cross= quotecurrency+depocurrency;
if (CrossReverse>0) Cross= depocurrency+quotecurrency;
MarketInfo(Cross, MODE_TIME);
if (GetLastError()==4106) continue;
CrossPricesCount= GetHistoryPricesArray(Cross, History[0][0], History[historysize-1][0], CrossPrices, PERIOD_H1);
//Alert(CrossPricesCount," ",GetTickCount()-ticks," ms");
break;
}
int starthour= History[0][0] /60/PERIOD_H1;
//Alert(pointvalue0);
for (int i=0; i<historysize; i++)
{
int historytime= History[i][0];
double lots=0;
if (CrossPricesCount>0)
{
if (CrossReverse>0) pointvalue= pointvalue0 / CrossPrices[historytime/60/PERIOD_H1-starthour];
else pointvalue= pointvalue0 * CrossPrices[historytime/60/PERIOD_H1-starthour];
if (pointvalue==0) { Print("Null point value! tick: ", i," time: ",TimeToStr(historytime)); continue; }
}
for (int p=1; p<=4; p++)
{
bool newtrade=0;
double price= History[i][p]; // * ticksize;
double bid= price;
int time= historytime;
if (trade<tradescount)
if (Trades[trade][0] < historytime || (Trades[trade][0]==historytime && p==4))
{ newtrade=true; time= Trades[trade][0]; price= Trades[trade][3]; if (Trades[trade][1]==OP_BUY) bid= price-spread; }
if (netposlots==0 && !newtrade) continue;
double ask= bid+spread;
if (basecurr==depocurr) pointvalue= pointvalue0/price; //NormalizeDouble(-pointvalue0/price, 8);
if (swappointvalue < 0) swappointvalue= NormalizeDouble(pointvalue, 2);
if (RealTickValue) swappointvalue= pointvalue;
double floatprofitbuy= (bid-tradeprice[OP_BUY]) / point * pointvalue * typelots[OP_BUY];
double floatprofitsell= (tradeprice[OP_SELL]-ask) / point * pointvalue * typelots[OP_SELL];
equity= balance + floatprofitbuy + floatprofitsell; // / basecurrprice;
if (lasttime>0 && time>lasttime) if (typelots[OP_BUY]+typelots[OP_SELL] > 0)
for (int day= lasttime/60/PERIOD_D1; day< time/60/PERIOD_D1; day++)
{
int k=1;
int weekday= TimeDayOfWeek(day*PERIOD_D1*60);
if (swap3day>=0)
if (weekday==swap3day) k=3;
else if (weekday==5 || weekday==6) k=0; else
if (weekday==0 && (swap3day==5 || swap3day==6)) k=0;
double swapunit=0; //double swapunit0= -pointvalue0/MarketInfo("GBPUSD",MODE_ASK);//(price+MarketInfo(symbol,MODE_SPREAD)*point);
switch (swaptype)
{
case 0: swapunit= swappointvalue; break; // â ïèïñàõ //NormalizeDouble(pointvalue,2);
case 1: if (basecurr >= 0) if (RealTickValue) swapunit= price*pointvalue/pointvalue0; else swapunit= basecurrvalue; // // â îñíîâíîé âàëþòå ñèìâîëà (äëÿ ôîðåêñà - áàçîâàÿ âàëþòà, äëÿ CFD - âàëþòà êîòèðîâàíèÿ)
else swapunit= quotecurrvalue;
break;
case 3: if (margincurr==basecurr) margincurrvalue= price*pointvalue/pointvalue0;
swapunit= margincurrvalue; break; // â âàëþòå çàëîãîâûõ ñðåäñòâ
case 2: swapunit= price/point*swappointvalue/100/360; break; // â ïðîöåíòàõ
}
double swap= swaplong * swapunit * k * typelots[OP_BUY] + swapshort * swapunit * k * typelots[OP_SELL];
balance += swap;
equity += swap;
swaps += swap;
}
if (newtrade)
{
lots= Trades[trade][2];
sumlots+=lots;
int type= Trades[trade][1];
double netlots= lots;
if (type==OP_SELL) netlots*= -1;
if (Trades[trade][4]==true) // íîâûé îðäåð
{
double comissionunit=0;
switch (comissiontype)
{
case 0: if (basecurr >= 0) comissionunit= price*pointvalue/pointvalue0; // â äåíüãàõ (â áàçîâîé âàëþòå ôîðåêñ-ñèìâîëà ëèáî â âàëþòå êîòèðîâêè CFD)
else comissionunit= quotecurrvalue;
break;
case 1: comissionunit= pointvalue; break; // â ïèïñàõ
case 2: comissionunit= price/point*pointvalue/100; // â ïðîöåíòàõ
}
double comis= comission*comissionunit;
if (!comissionperdeal) comis *= lots;
balance -= comis;
equity -= comis + (spread/point)*pointvalue;
comissions += comis;
tradeprice[type]= (typelots[type]*tradeprice[type] + lots*price) / (typelots[type]+lots);
typelots[type]+=lots;
}
else // çàêðûòèå îðäåðà
{
typelots[!type] -= lots; //if (typelots[type]<0) { Alert("!!! ",typelots[type]," ",trade); break; } }
balance += NormalizeDouble( (tradeprice[!type]-price) / point * pointvalue * netlots, 8);
//Alert(trade,". ", NormalizeDouble( (tradeprice[!type]-price) / point * pointvalue * netlots, 8) );
}
netposlots += netlots;
trade++;
p--;
}
if (time/60 > lastminute) //lasttime/60)
if (lots!=0 || netposlots!=0)
{
n++;
if (n >= ArrayRange(Equity,0)) ArrayResize(Equity, n+10000);
lastminute= time/60;
Equity[n][0]= lastminute*60; Equity[n][1]=equity; Equity[n][2]=equity; Equity[n][3]=equity;
}
if (n>=startpos)
{
if (equity < Equity[n][2]) Equity[n][2]=equity; else //Equity[n][2]= MathMin(Equity[n][2], equity);
if (equity > Equity[n][3]) Equity[n][3]=equity; //Equity[n][3]= MathMax(Equity[n][3], equity);
Equity[n][4]= equity;
}
lasttime=time;
double currentdrowdown= highequity-equity;
if (currentdrowdown > absdrowdown) { absdrowdown= currentdrowdown; drowdowntime[0]= time; }
if (deposit>0) if (currentdrowdown/highequity > reldrowdown) { reldrowdown= currentdrowdown/highequity; drowdowntime[1]= time; }
if (equity > highequity) highequity= equity; //= MathMax(highvalue, equity);
}
}
n++;
int count= n-startpos;
balance= NormalizeDouble(balance, 2);
swaps= NormalizeDouble(swaps, 2);
absdrowdown= NormalizeDouble(absdrowdown, 2);
drowdown[0]= absdrowdown;
drowdown[1]= reldrowdown;
if (comissions>0) comissions *= -1;
Print(symbol," equity created: ",count," bars M1",", Profit: ",balance-deposit,", Drowdown: ",absdrowdown,", Swaps: ",swaps,", Comissions: ",comissions,", Lots: ",sumlots/2, paramtxt);//,", time: ",GetTickCount()-ticks," ms");//swapshort*swapunit*k);
//Print(reldrowdown," ",TimeToStr(reldrowdowntime));
return(count);
}
//--------------------------------------------------------------
bool DrawIndicatorBuffers(double Equity[][], int equitybars)
{
IndicatorInit();
int lastbar=-1;
for (int i=0; i<equitybars; i++)
{
int time= Equity[i][0];
if (time >= Time[0])
{
int bar= (Time[0]-time) / 60 / Period();
BufferFuture[bar+FutureBufferShift]= Equity[i][4];
if (bar<0) continue;
}
bar= iBarShift(NULL,0,time);
if (bar!=lastbar) BufferOpen[bar]= Equity[i][1];
if (BufferLow[bar]==EMPTY_VALUE) BufferLow[bar]= Equity[i][2];
else BufferLow[bar]= MathMin(BufferLow[bar], Equity[i][2]);
if (BufferHigh[bar]==EMPTY_VALUE) BufferHigh[bar]= Equity[i][3];
else BufferHigh[bar]= MathMax(BufferHigh[bar], Equity[i][3]);
//if (BufferLow[bar]==BufferHigh[bar]) BufferShadow[bar]=EMPTY_VALUE; else
if (BufferLow[bar]>0 && BufferLow[bar]!=EMPTY_VALUE) BufferShadow[bar]= BufferLow[bar]-0.005; else
if (BufferHigh[bar]<0 && BufferHigh[bar]!=EMPTY_VALUE) BufferShadow[bar]= BufferHigh[bar]+0.005; else BufferShadow[bar]=EMPTY_VALUE;
BufferClose[bar]= Equity[i][4];
//BufferVolume[bar]= Equity[i][5];
lastbar= bar;
}
}
//----------------------------------------------------------------------------------
int GetHistoryPricesArray(string symbol, int starttime, int endtime, double &prices[], int period)
{
int count= endtime/60/period - starttime/60/period + 1;
ArrayResize(prices, count);
ArrayInitialize(prices, 0);
int timeframes[]= { PERIOD_MN1, PERIOD_W1, PERIOD_D1, PERIOD_H4, PERIOD_H1, 30, 15, 5, 1 };
int tfcount= ArraySize(timeframes);
int firstminute=0;
int prevtime=0;
double prevprice=0;
int saved=0;
for (int t=0; t< tfcount; t++)
{
int tf= timeframes[t];
int timearray[];
int bars= ArrayCopySeries(timearray, MODE_TIME, symbol, tf);
if (bars<=0) continue;
int leftbar= ArrayBsearch(timearray, starttime, bars);
int rightbar= ArrayBsearch(timearray, endtime, bars);
if (timearray[leftbar] > starttime && timearray[leftbar+1]+tf*60-1 >= starttime) leftbar++;
if (timearray[rightbar] > endtime && rightbar < bars-1) rightbar++;
//Alert(tf," ",TimeToStr(timearray[rightbar]));
//2013.02.25 23:00
double openpricearray[];
double closepricearray[];
ArrayCopySeries(openpricearray, MODE_CLOSE, symbol, tf);
ArrayCopySeries(closepricearray, MODE_CLOSE, symbol, tf);
for (int b=rightbar; b<=leftbar; b++)
{
int minute= (timearray[b]-starttime)/60;
prices[ minute/period ] = openpricearray[b];
//if (tf<=period) continue;
prices[ (minute+tf)/period ] = closepricearray[b];
}
if (timearray[b] < starttime && timearray[b] > prevtime) { prevtime= timearray[b]; prevprice= openpricearray[b]; }
int firstpos= MathMin(firstpos, minute/period);
saved += leftbar-rightbar+1;
}
if (saved==0) return(0);
if (prevprice==0) prevprice= prices[firstpos];
for (int i=0; i< count; i++)
if (prices[i]==0) if (i>0) prices[i]= prices[i-1]; else prices[i]=prevprice;
//Alert(TimeToStr(starttime+(count-1)*period*60)," ",prices[count-1]," ",prevprice);
return(count);
}
//--------------------------------
double ReadDouble(int address)
{
double value[1];
memcpy(GetAddressOfDouble(value), address, 8);
return(value[0]);
}
/*
int ReadInt(int address)
{
int value[1];
memcpy(GetAddressOfInt(value), address, 4);
return(value[0]);
}
*/
//----------------------------------
string GetDepoCurrency()
{
string file= TerminalPath() + "\\Tester\\" + ExpertName + ".ini";
int hfile= fopen(file, "r");
if (hfile==0) return(0);
string buffer=" ";
string currency="";
while (fgets(buffer, 30, hfile)>0)
{
if (buffer=="</common>\n") break;
int pos= StringFind(buffer,"currency=",0);
if (pos<0) continue;
currency= StringSubstr(buffer,pos+9);
currency= StringTrimLeft(StringTrimRight(currency));
break;
}
fclose(hfile);
return(currency);
}
//--------------------------------------------------------
double GetCurrencyPrice(string maincurr, string quotecurr)
{
if (maincurr==quotecurr) return(1);
double price= MarketInfo(maincurr+quotecurr,MODE_BID);
if (GetLastError()!=4106) return(price);
price= MarketInfo(quotecurr+maincurr,MODE_BID);
if (price==0) return(0);
return(1/price);
}
//--------------------------------------------------------
int GetFxtHistory(string file, double &history[][], double &info[], string ¤cies[], bool allticks=0)
{
int hfile= fopen (file, "rb");
if (hfile==0) { Print("Íå íàéäåí ôàéë ",file); return(0); }
#define HEADSIZE 728
int header[200];
int headeraddr= GetAddressOfInt(header);
if (fread(headeraddr, HEADSIZE, 1, hfile) < 1) { Print("Íåäîñòàòî÷íî äàííûõ â ôàéëå ",file); fclose(hfile); return(0); }
int period= header[208/4];
if (ArraySize(info)>0) ArrayInitialize(info,0);
info[MODE_SPREAD]= header[252/4];
info[MODE_POINT]= ReadDouble(headeraddr+264);
info[MODE_LOTSIZE]= ReadDouble(headeraddr+296);
info[MODE_TICKVALUE]= ReadDouble(headeraddr+304);
info[MODE_TICKSIZE]= ReadDouble(headeraddr+312);
info[MODE_PROFITCALCMODE]= header[320/4]; // { PROFIT_CALC_FOREX, PROFIT_CALC_CFD, PROFIT_CALC_FUTURES }
int swapenable= header[324/4];
if (swapenable==true)
{
info[MODE_SWAPTYPE]= header[328/4];
info[MODE_SWAPLONG]= ReadDouble(headeraddr+336);
info[MODE_SWAPSHORT]= ReadDouble(headeraddr+344);
info[MODE_SWAP3DAY]= header[352/4];
}
info[MODE_COMISSION]= ReadDouble(headeraddr+424);
info[MODE_COMISSIONTYPE]= header[432/4];
info[MODE_COMISSIONPERDEAL]= header[436/4];
string buffer[]= { "____________" };
int bufaddr= GetAddressOfString(buffer);
memcpy(bufaddr, headeraddr+196, 12);
string symbol= buffer[0]+"";
memcpy(bufaddr, headeraddr+240, 12);
string currency= buffer[0]+"";
memcpy(bufaddr, headeraddr+408, 12);
string margincurrency= buffer[0]+"";
currencies[0]= currency;
currencies[1]= margincurrency;
//for (int t=380; t<640; t+=4) { memcpy(bufaddr, headeraddr+t, 12); Alert(t," ",buffer[0]); }
//for (int j=56; j<728; j+=4) if (ReadDouble(headeraddr+j)==0.001) Alert(j);
//string txt="";
//int stticks=GetTickCount();
double prices[4];
int priceaddr= GetAddressOfDouble(prices);
int readbuffer[1000][13];
int readbufferaddr= GetAddressOfInt(readbuffer); //int historyaddr= GetAddressOfDouble(history);
int n=0;
while(true)
{
int readcount= fread(readbufferaddr, 4*13, 1000, hfile);
if (readcount<=0) break;
for (int i=0; i<readcount; i++)
{
int bartime= readbuffer[i][0];
memcpy(priceaddr, readbufferaddr+4*13*i+4, 32); // öåíû OLHC
int ticktime= readbuffer[i][11];
int flag= readbuffer[i][12];
if (flag==0) if (!allticks || n==0) continue;
if (ticktime== history[n-1][0])
{
history[n-1][2]= MathMin(history[n-1][2], prices[1]);
history[n-1][3]= MathMax(history[n-1][3], prices[2]);
history[n-1][4]= prices[3];
continue;
}
if (n >= ArrayRange(history,0)) ArrayResize(history, n+50000); //historyaddr= GetAddressOfDouble(history); }
history[n][0]= ticktime;
history[n][1]= prices[0]; // memcpy(historyaddr + n*historyrange*8 +8, priceaddr, 32);
history[n][2]= prices[1];
history[n][3]= prices[2];
history[n][4]= prices[3];
n++;
}
}
fclose(hfile);
if (n==0) Print("Îòñóòñòâóåò èñòîðèÿ");
//Alert("history: ",GetTickCount()-stticks," ms");
return(n);
}
//-----------------------------------------------
bool GetReportParameters(double& deposit)
{
int hMT4= GetAncestor( WindowHandle(Symbol(),Period()), GA_ROOT );
int hTerminal= GetDlgItem(hMT4, 0xE81E);
int hTester= GetDlgItem(hTerminal, 0x53);
int hReportList= GetDlgItem(hTester, 0x81BD);
if (hReportList==0) return(0);
deposit= StrToDouble( GetListViewItemText(hReportList, 2, 1) );
return(true);
}
//------------------------------------------------------------------
int GetTesterParameters(string& expert, string& symbol, int& period, int& model)
{
int hMT4= GetAncestor( WindowHandle(Symbol(),Period()), GA_ROOT );
int hTerminal= GetDlgItem(hMT4, 0xE81E);
int hTester= GetDlgItem(hTerminal, 0x53);
int hDlg= GetDlgItem(hTester, 0x81BF);
if (hDlg==0) return(0);
int hSymbol= GetDlgItem(hDlg, 0x543);
int hPeriod= GetDlgItem(hDlg, 0x4CC);
int hModel= GetDlgItem(hDlg, 0xFBB);
static string buffer="___________________________________________________";
symbol="";
if (GetWindowTextA(hSymbol, buffer, 32)>0)
symbol= StringSubstr(buffer, 0, StringFind(buffer,","));
int periods[]= { 1, 5, 15, 30, 60, PERIOD_H4, PERIOD_D1, PERIOD_W1 };
string periodnames[]= { "M1", "M5", "M15", "M30", "H1", "H4", "Daily", "Weekly" };
period=0;
if (GetWindowTextA(hPeriod, buffer, 32)>0)
for (int i=0; i<ArraySize(periods); i++)
if (buffer==periodnames[i]) { period=periods[i]; break; }
model= SendMessageA(hModel, CB_GETCURSEL, 0, 0);
if (GetWindowTextA(hModel, buffer, 50)>0)
ModelName[model]= StringSubstr(buffer, 0, StringFind(buffer," ("));
int hExpert= GetDlgItem(hDlg, 0x468);
expert="";
if (GetWindowTextA(hExpert, buffer, 50)>0)
expert= StringSubstr(buffer, 0, StringFind(buffer, ","));
if (symbol=="" || period==0 || model==-1) return(0);
return(true);
}
//------------------------------------------------------
int GetTrades(double& trades[][])
{
int hMT4= GetAncestor( WindowHandle(Symbol(),Period()), GA_ROOT );
int hTerminal= GetDlgItem(hMT4, 0xE81E);
int hTester= GetDlgItem(hTerminal, 0x53);
int hList= GetDlgItem(hTester, 0x81BE);
if (hList==0) { Alert("Íå íàéäåíî îêíî ñïèñêà îðäåðîâ òåñòåðà"); return (0); }
int itemscount= SendMessageA(hList, LVM_GETITEMCOUNT, 0, 0);
string celltxt[10];
//string txt="";
int ordertypes[1000];
if (ArraySize(trades)>0) ArrayInitialize(trades,0);
int n=0;
for (int i=0; i<itemscount; i++)
{
for (int j=0; j<6; j++)
celltxt[j]= GetListViewItemText(hList, i, j);
int newtrade= -1;
bool neworder=0;
int ticket= StrToInteger(celltxt[3]);
if (ticket>=ArraySize(ordertypes)) ArrayResize(ordertypes,ticket+1000);
if (celltxt[2]=="buy") { ordertypes[ticket]= OP_BUY; newtrade= OP_BUY; neworder=true; }
if (celltxt[2]=="sell") { ordertypes[ticket]= OP_SELL; newtrade= OP_SELL; neworder=true; }
if (celltxt[2]=="close" || celltxt[2]=="close at stop" || celltxt[2]=="s/l" || celltxt[2]=="t/p")
if (ordertypes[ticket]==OP_BUY) newtrade= OP_SELL; else newtrade= OP_BUY;
if (newtrade<0) continue;
if (n >= ArrayRange(trades,0)) ArrayResize(trades, n+100);
int time= StrToTime(celltxt[1]);
double lots= StrToDouble(celltxt[4]);
double price= StrToDouble(celltxt[5]);
trades[n][0]= time;
trades[n][1]= newtrade;
trades[n][2]= lots;
trades[n][3]= price;
trades[n][4]= neworder;
//txt=StringConcatenate(txt,TimeToStr(trades[n][0]),"\t",trades[n][1],"\t",trades[n][2],"\t",trades[n][3],"\n");
n++;
}
//Alert(txt);
return(n);
}
//+------------------------------------------------------------------+
string GetListViewItemText(int hlistview, int item, int subitem=0)
{
static string textbuf[]= {"_________________________________________________________________"};
int textaddress= GetAddressOfString(textbuf);
if (textaddress==0) { Alert("textaddress=0"); return(0); }
int LVITEM[10];
LVITEM[0]= LVIF_TEXT; // Mask
LVITEM[1]= item; // Item
LVITEM[2]= subitem; // iSubItem
LVITEM[5]= textaddress;
LVITEM[6]= 32; //TextMask
int LVITEM_addr= GetAddressOfInt(LVITEM);
if (LVITEM_addr==0) { Alert("arrayaddress=0"); return(0); }
if (SendMessageA(hlistview, LVM_GETITEMTEXT, item, LVITEM_addr) > 0) return( textbuf[0]+"" );
return("");
}
//+------------------------------------------------------------------+
int GetAddressOfString(string str[], int index=0) // Ïîëó÷åíèå àäðåñà ìàññèâà ñòðîê
{
return( lstrcpyn(str[index],str[index],0) );
}
//---------------------------------
int GetAddressOfInt(int array[], int index=0) // Ïîëó÷åíèå àäðåñà ìàññèâà int
{
return( lstrcpynA(array,array,0)+index*4 );
}
//----------------------------------------------
int GetAddressOfDouble(double array[], int index=0) // Ïîëó÷åíèå àäðåñà ìàññèâà double
{
return( lstrcpynW(array,array,0)+index*8 );
}
//-----------------------------------------------------------------------------------------------
bool DrawLabel(string name, int x, int y, int corner, string text, int fontsize, string font, int clr)
{
if (name=="") return(0);
int wnd= ObjectFind(name);
if (wnd!=Window || ObjectType(name)!=OBJ_LABEL)
{ ObjectDelete(name); wnd=-1; }
if (wnd<0) if (!ObjectCreate(name,OBJ_LABEL,Window,0,0))
{
if (GetLastError()==4051) { Print("Wrong window"); } //WrongWindow=true;
return(0);
}
ObjectSet(name,OBJPROP_XDISTANCE,x);
ObjectSet(name,OBJPROP_YDISTANCE,y);
ObjectSetText(name,text,fontsize,font,clr);
ObjectSet(name,OBJPROP_CORNER,corner);
return(true);
}
//-----------------------------------------------------------------------------------
void DrawText(string object, int time, double price, string text, color clr=White, int fontsize=10, string font="Arial")
{
if (object=="") return(0);
int wnd= ObjectFind(object);
if (wnd!=Window || ObjectType(object)!=OBJ_TEXT)
{ ObjectDelete(object); wnd=-1; }
if (wnd<0) if (!ObjectCreate(object,OBJ_TEXT,Window,0,0))
{
if (GetLastError()==4051) { Print("Wrong window"); } //WrongWindow=true;
return;
}
ObjectMove(object,0,time,price);
ObjectSetText(object,text,fontsize,font,clr);
}
//----------------------------------------------------
bool Initialize(double array[], double value)
{
if (ArraySize(array)==0) return(0);
return( ArrayInitialize(array, value) );
}
//-------------------------------------------------------------------------
bool WriteEquityToTextFile(double Equity[][], int equitysize, string filename, int delimiter)
{
int hfile= FileOpen(filename, FILE_CSV|FILE_WRITE, delimiter);
if (hfile<0) { Print("Íå óäàëîñü îòêðûòü äëÿ çàïèñè ôàéë ",filename); return(0); }
for (int i=0; i<equitysize; i++)
{
if (NormalizeDouble(Equity[i][1]-Equity[i][2],8)==0 && NormalizeDouble(Equity[i][1]-Equity[i][3],8)==0 && NormalizeDouble(Equity[i][1]-Equity[i][4],8)==0)
FileWrite(hfile, TimeToStr(Equity[i][0]), NormalizeDouble(Equity[i][1],2));
else
FileWrite(hfile, TimeToStr(Equity[i][0]), NormalizeDouble(Equity[i][1],2), NormalizeDouble(Equity[i][2],2), NormalizeDouble(Equity[i][3],2), NormalizeDouble(Equity[i][4],2));
}
Print("Çàïèñàí ôàéë ",filename);
FileClose(hfile);
return(true);
}
//------------------------------------------------------------------------------
bool WriteEquityToBinaryFile(double Equity[][], int equitysize, string filename)
{
int hfile= FileOpen(filename, FILE_BIN|FILE_WRITE);
if (hfile<0) { Print("Íå óäàëîñü îòêðûòü äëÿ çàïèñè ôàéë ",filename); return(0); }
for (int i=0; i<equitysize; i++)
{
FileWriteInteger(hfile, Equity[i][0]);
FileWriteArray(hfile, Equity, i*ArrayRange(Equity,1), 4);
}
Print("Çàïèñàí ôàéë ",filename);
FileClose(hfile);
return(true);
}
//----------------------------------------------------------------------------
bool StringReplace(string &SourceString, string FindString, string NewString)
{
int pos= StringFind(SourceString, FindString);
if (pos<0) return(0);
string LeftSubstr= "";
if (pos>0) LeftSubstr= StringSubstr(SourceString, 0, pos);
SourceString= LeftSubstr + NewString + StringSubstr(SourceString, pos+StringLen(FindString));
return(true);
}
//-------------------------------------------------------------------------------
int ArrayStringSearch(string array[], string searchstring, int maxcount=0)
{
if (maxcount==0) maxcount= ArraySize(array);
for (int i=0; i<maxcount; i++) if (array[i]==searchstring) break;
if (i==maxcount) i=-1;
return(i);
}
//----------------------------------------------------------------------------
int GetArrayFromString(string &Array[], string String, string delimiter=" ")
{
int n=0;
int len=StringLen(String);
int delimlen= StringLen(delimiter);
int delimpos=0;
bool resize=0;
for (int startfindpos=0; startfindpos<len; startfindpos=delimpos+delimlen)
{
delimpos= StringFind(String, delimiter, startfindpos);
if (delimpos<0) delimpos=len;
if (delimpos==startfindpos) continue;
if (n>=ArraySize(Array)) { ArrayResize(Array, n+10); resize=true; }
Array[n]= StringTrimLeft(StringTrimRight(StringSubstr(String, startfindpos, delimpos-startfindpos)));
n++;
}
if (resize) ArrayResize(Array, n);
return(n);
}
//----------------------------------------------------------------------------
int MySymbols_FillAllParameters()
{
MySymbolsCount=0;
MySymbols_FillParam(_Spread, Spread);
MySymbols_FillParam(_Comission, Comission);
MySymbols_FillParam(_Swap, Swap);
}
//-------------------------------------------------------------
int MySymbols_FillParam(int paramindex, string checkstring)
{
if (checkstring=="") return(0);
int range1= ArrayRange(MySymbolsParam,1);
string StrArray[];
int partscount= GetArrayFromString(StrArray, checkstring, " ");
for (int p=0; p<partscount; p+=2)
{
if (p==partscount-1 && partscount>1) continue;
string symbol= StrArray[p];
if (partscount==1) { symbol=""; p--; }
int symindex= ArrayStringSearch(MySymbols, symbol, MySymbolsCount);
if (symindex<0)
{
symindex= MySymbolsCount; MySymbolsCount++; ArrayResize(MySymbols,MySymbolsCount); ArrayResize(MySymbolsParam,MySymbolsCount);
MySymbols[symindex]= symbol;
for (int j=0; j<range1; j++) MySymbolsParam[symindex][j]= EMPTY_VALUE;
}
MySymbolsParam[symindex][paramindex]= StrToDouble(StrArray[p+1]);
}
return(MySymbolsCount);
}
//----------------------------------------------
void TesterSetSpread(int value)
{
MySymbols_FillParam(_Spread, value+"");
}
//-----------------------------------------------
void TesterSetComission(double value)
{
MySymbols_FillParam(_Comission, value+"");
}
//----------------------------------------
void TesterSetComissionType(int value)
{
MySymbols_FillParam(_ComissionType, value+"");
}
//----------------------------------------------
void TesterSetSwap(bool value)
{
MySymbols_FillParam(_Swap, value+"");
}
/*
string txt="";
for (int i=0; i<7; i++)
txt=txt+addr[i]+"\n";
Alert(txt);
// óêàçàòåëè:
memcpy(bufaddr,0x01C0E8D4,12); //0012B110
return(buf[0]+"");
int hMT4= GetAncestor( WindowHandle(Symbol(),Period()), GA_ROOT );
int hTerminal= GetDlgItem(hMT4, 0xE81E);
int hTester= GetDlgItem(hTerminal, 0x53);
int hDlg= GetDlgItem(hTester, 0x81BF);
int hExpertProperties= GetDlgItem(hDlg, 0x401);
if (hExpertProperties==0) return(0);
//hMT4= GetAncestor(hMT4, GA_PARENT);
//Alert(hMT4);
//int lastpopup= GetLastActivePopup(hMT4);
//SendMessageA(hExpertProperties, BM_CLICK, 0, 0);
SendMessageTimeoutA(hExpertProperties, BM_CLICK, 0, 0, 0, 500, 0);
int ticks= GetTickCount();
//Alert(ExpertName);
//Sleep(50);
//if (0);
//while (GetTickCount()-ticks < 100) continue;
while (GetTickCount()-ticks < 1000)
{
int hwnd= FindWindowExA(0, 0, "#32770",ExpertName);//ExpertName);
if (hwnd>0)
if (GetAncestor(hwnd,GA_ROOTOWNER)==hMT4)
break;
hwnd=0;
}
if (hwnd==0) return("");
string null;
int hTesting= FindWindowExA(hwnd, 0, "#32770", null);
int hCurrency= GetDlgItem(hTesting, 0x42C);
string buffer= " ";
if (GetWindowTextA(hCurrency,buffer,12)>0)
return(buffer+"");
return("");
*/
Comments