vdemydiuk / mtapi

MetaTrader API (terminal bridge)
http://mtapi4.net/
MIT License
524 stars 283 forks source link

BackTesting #252

Open arteny opened 3 years ago

arteny commented 3 years ago

I want to clarify the available functionality of BackTesting (MtApi5). As I could check, these options are absent for MtApi5 if compare with MQL experts:

If I am wrong here or you have some other details, please share them with us.

And what I found is really missing for backtesting is there is no event in MtApi5 that says that backtesting is finishing. https://www.mql5.com/ru/docs/event_handlers/ontesterdeinit As a result Client.GetHistory.. methods returns "No connection" exception after auto-disconnecting. Also is it possible to add the following method? https://www.mql5.com/en/docs/common/testerstatistics

KptKuck commented 3 years ago

I know the problem. At the beginning I tried to add a new event OnDeinit. Which is sent in the function deinit(). But it was not satisfying.

Now I use the following workaround.

In the Trading APP I calculate the maximum time in minutes of the backtest.

Set a SafeEnd = maxtime-10min I check this value in each bar So you can definitely 10 minutes before the end of the backtest do everything you need (GetHistory..etc).

Here some code as help(MatLab)

Generate dates:

% Generate Tester Dates TesterDates.d1 = datetime('2018.01.01','InputFormat','yyyy.MM.dd' ); TesterDates.d2 = datetime('2019.01.01','InputFormat','yyyy.MM.dd' );

TesterDates.Mon = dateseries(TesterDates.d1,TesterDates.d2,'Interval','weekly','Day','Mon');
TesterDates.Tue = dateseries(TesterDates.d1,TesterDates.d2,'Interval','weekly','Day','Tue');
TesterDates.Wed = dateseries(TesterDates.d1,TesterDates.d2,'Interval','weekly','Day','Wed'); TesterDates.Thu = dateseries(TesterDates.d1,TesterDates.d2,'Interval','weekly','Day','Thu'); TesterDates.Fri = dateseries(TesterDates.d1,TesterDates.d2,'Interval','weekly','Day','Fri');

TesterDates.day(1) = length(TesterDates.Mon); TesterDates.day(2) = length(TesterDates.Tue); TesterDates.day(3) = length(TesterDates.Wed); TesterDates.day(4) = length(TesterDates.Thu); TesterDates.day(5) = length(TesterDates.Fri);

TesterDates.maxweeks = max(TesterDates.day); TesterDates.Dates = strings(TesterDates.maxweeks,5);

TesterDates.Dates(1:TesterDates.day(1),1) = TesterDates.Mon; TesterDates.Dates(1:TesterDates.day(2),2) = TesterDates.Tue; TesterDates.Dates(1:TesterDates.day(3),3) = TesterDates.Wed; TesterDates.Dates(1:TesterDates.day(4),4) = TesterDates.Thu; TesterDates.Dates(1:TesterDates.day(5),5) = TesterDates.Fri;

fromdate = datetime(TesterDates.preselected(k,1),'InputFormat','MM/dd/yyyy');
todate = datetime(TesterDates.preselected(k,2),'InputFormat','MM/dd/yyyy');

cLoggerP1.info(sprintf('Loop: %d of %d',k,K),1); cLoggerP1.info(sprintf('StartDate: %s ',char(fromdate)),1); cLoggerP1.info(sprintf('EndDate: %s',char(todate)),1);

safeend_dt = todate;

if (day(todate,'dayofweek') == 6) safeend_dt = safeend_dt - minutes(65);
safeend = System.DateTime.Parse(datestr(safeend_dt));

else safeend_dt = safeend_dt - minutes(10);
safeend = System.DateTime.Parse(datestr(safeend_dt)); end

function [ok] = updateTesterPreEnd(self,sdtTesterPreEndDate)

          cApiResult = self.cMtApi5.cCommon.TimeCurrent();

          if cApiResult.isSuccess()
              self.sdtTimeCurrent = cApiResult.sDateTime;
          end

          if self.sdtTimeCurrent > sdtTesterPreEndDate
             self.bTesterPreEnd = true;
          end

        end