//+------------------------------------------------------------------+ //| 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 //========= ВНЕШНИЕ ПАРАМЕТРЫ =============================== 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; i0) ObjectDelete(LabelCaption[i]); for (i=0; i0) 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; t0) 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; i0) { 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 (trade0 && 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= 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=="\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= 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; i0) 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=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; i0) 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=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; p1) 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; j0) 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(""); */