Multicurrency EA. What to use: OnTimer, OnChartEvent, OnTick, OnFakeindicator? - page 2

 
William Roeder #:

So do not trade multiple currencies in one EA.

  1. You can't use any {MT4: predefined variables, MT5: predefined variables,}

  2. A multi-asset EA runs in one thread so that one asset blocks all the others, while each EA for a single asset runs in its own thread,

  3. Must poll (not OnTick, unless you use specific indicators)
              The Implementation of a Multi-currency Mode in MetaTrader 5 - MQL5 Articles (2011)

  4. and usually other problems, e.g. A problem with iBarShift - MQL4 programming forum - Page 2 (2016)

  5. You must handle History {MT4:4066/4073 errors: Download history in MQL4 EA - MQL4 programming forum, MT5: Timeseries and Indicators Access /  Data Access - Reference on algorithmic/automated trading language for MetaTrader 5.}

  6. Code it to trade the chart pair only. Look at the others if you must. Don't assume that Time[i] == iTime(otherPair, TF, i) always use iBarShift.

Then put it on other charts to trade the other pairs. Done.

The thing is that there are several instances in which the actual strategy is the use of different pairs. For instance, arbitrage,  hedging, equity optimization by running uncorrelated pairs, etc. Anyway, the multi-currency functionality of MQL5 is in my opinion (among other things) what makes Metatrader such as great tool. It is just a  petty that it has so many critical nuances.
 
Camilo Mora:

There are tons of articles and blogs about the many issues with multicurrency EAs. And remarkably little clarity over the best practice. Let me summarize some of the problems I have encountered:

For the longest of times, I have used ISpy in combination with OnChartEvent for multicurrency EAs, until recently when I encounter that the results I was getting from a farm of agents were different between simulations. That was a pain to debug, and came to discover that the problem is that when many pairs are loaded, this overruns the EA with events, and it actually bypasses/ never runs some events. That was a crazy finding, as basically as a way to avoid overload, the EA bypasses commands, this is a major concern over this solution specially at critical times like news events. 

A solution was OnTimer, another deceiving tool when using strategy tester, it turns out that on strategy tester on Timer is set by the tick data you set in the main chart. Results on OnTimer were very unreliable when running the EA optimization on agents from a farm. I was not able to figure out why agents set different OnTimers, but the same multicurrency ea produces exactly the same result in a local machine but varying results when run in agents.

Then came the use of OnTick (using as very liquid pair as the base chart, like BTCUSD), and implementing an internal OnNewBar (to check all pairs every minute) to then loop over all pairs. This reduced considerably the use of resources, but remarkably the results were different than if I use the ISpy (reliably but heavy and error prone when many tick arrive simultaneously). 

In theory, all we need during back-test and live trading is a reliable timer that we can use to check at specific time intervals the rates of pairs to trade. That brought me to this idea of creating a heartbeat currency pair. A fake pair that has 1 tick per minute, and this is used as the base of the ea. Basically it will reliably check every certain amount of time the data in pairs over a loop. What people think of this idea. Any other suggestions on how to generate reproducible results from optimizations in multicurrency EAs, while considering the effects of backtesting with agents?

I use the iSpy method but not with the same code presented in the article (https://www.mql5.com/en/articles/234) my version tracks M1 bars and only sends a tick at M1 bar opens so when I backtest with 1 min OHLC the results are same in live. There is probably better ways to track M1 bars and if anyone wants to suggest a better method I'm sure I'd switch to it. But this code for now solves my problems of getting different results in multisymbol backtests when selecting different symbols thru the strategy tester and I haven't had anything weird happen in live with it. Other than that wiring it to a EA is the same as the article but you should do your own error/sync checking for the chart event, symbol, and copyrates again. 
//+------------------------------------------------------------------+
//|                                                       iSpyM1.mq5 |
//|                                            Copyright 2010, Lizar |
//|                                               lizar-2010@mail.ru |
//+------------------------------------------------------------------+

#property indicator_chart_window
#property indicator_plots 0

input long   chart_id=0;         // 0 = current chart
input ushort custom_event_id=0;  // base id

static datetime last_closed_m1 = 0;

int OnInit(){
   // Set current M1 bar as closed so we don't immediately fire a chart event
   MqlRates r[1];
   if(CopyRates(_Symbol, PERIOD_M1, 1, 1, r)==1)
      last_closed_m1 = r[0].time;
   return(INIT_SUCCEEDED);
}

// Note: No heavy checking of the CopyRates is done because if its not ready on this tick then you probably couldn't have reacted on that tick anyway. 
//       OnCalculate will fire at the next available tick anyways and since its already symbol specific in your EA all you have to do is check 
//       if its the correct symbol in OnChartEvent. It could probably get stuck or something but you should use copyrates again in your EA to check and 
//       make sure it aligns. 

// Note: There are probably better ways to do this but idk

int OnCalculate (const int rates_total,
                 const int prev_calculated,
                 const int begin,
                 const double& price[])
{

   MqlRates r[1];
   if(CopyRates(_Symbol, PERIOD_M1, 1, 1, r)!=1)
      return(prev_calculated);                 // not ready yet wait for next tick

   if(last_closed_m1==0) {                     
      last_closed_m1 = r[0].time;              
      return(rates_total);
   }

   if(r[0].time != last_closed_m1) {           // a new M1 bar has CLOSED
      EventChartCustom(chart_id, ushort(custom_event_id + 1),
                       (long)PERIOD_M1, r[0].close, _Symbol);
      last_closed_m1 = r[0].time;
   }
   return(rates_total);
}
The Implementation of a Multi-currency Mode in MetaTrader 5
The Implementation of a Multi-currency Mode in MetaTrader 5
  • 2011.02.18
  • www.mql5.com
For a long time multi-currency analysis and multi-currency trading has been of interest to people. The opportunity to implement a full fledged multi-currency regime became possible only with the public release of MetaTrader 5 and the MQL5 programming language. In this article we propose a way to analyze and process all incoming ticks for several symbols. As an illustration, let's consider a multi-currency RSI indicator of the USDx dollar index.
 
Csquared #:
I use the iSpy method but not with the same code presented in the article (https://www.mql5.com/en/articles/234) my version tracks M1 bars and only sends a tick at M1 bar opens so when I backtest with 1 min OHLC the results are same in live. There is probably better ways to track M1 bars and if anyone wants to suggest a better method I'm sure I'd switch to it. But this code for now solves my problems of getting different results in multisymbol backtests when selecting different symbols thru the strategy tester and I haven't had anything weird happen in live with it. Other than that wiring it to a EA is the same as the article but you should do your own error/sync checking for the chart event, symbol, and copyrates again. 
With how much symbols are using this system (live) ?
 
Alain Verleyen #:
With how much symbols are using this system (live) ?
I've never gone above 12 but thats because I don't want to trade every single symbol. 
 
Csquared #:
I've never gone above 12 but thats because I don't want to trade every single symbol. 

Thanks.

Using this solution (also only an event for new M1 bar), I had reliability issue with EventChartCustom(). On some (weaker) computers, from time to time, it was "stuck" for several seconds. The results was the solution was not reliable enough for my use cases. I was using 28 symbols.

 
Alain Verleyen #:

Thanks.

Using this solution (also only an event for new M1 bar), I had reliability issue with EventChartCustom(). On some (weaker) computers, from time to time, it was "stuck" for several seconds. The results was the solution was not reliable enough for my use cases.

I would post code for an example EA that uses this but I cannot for the life of me get the news filter to work in the tester thru the save script -> read to EA method because daylight savings time always causes the event timestamps to be wrong somehow. (I will probably make a thread later today about it)

Also you cannot use the iSpyM1 indicator with open prices only mode because of how the M1 bar tracking is done. There is probably a way to do it but I don't plan on using open prices only when I can use 1 min ohlc 

 
Csquared #:
I would post code for an example EA that uses this but I cannot for the life of me get the news filter to work in the tester thru the save script -> read to EA method because daylight savings time always causes the event timestamps to be wrong somehow. (I will probably make a thread later today about it)
Without getting too far off-topic, Calendar events are stamped with TimeTradeServer() which the Tester doesn't use.
 
Ryan L Johnson #:
Without getting too far off-topic, Calendar events are stamped with TimeTradeServer() which the Tester doesn't use.
yeah and its definitely causing me issues lol. If I solve it in the next day or so I'll post it here
 
Alain Verleyen #:

Thanks.

Using this solution (also only an event for new M1 bar), I had reliability issue with EventChartCustom(). On some (weaker) computers, from time to time, it was "stuck" for several seconds. The results was the solution was not reliable enough for my use cases. I was using 28 symbols.

Also are you sure it was "stuck" because for me I thought the symbols were getting stuck too but it turns out the symbols just weren't receiving ticks all at the same time. Especially on exotic pairs they wouldn't have a new m1 open tick until almost ten seconds after major pairs did and you can visually confirm this by looking at the tick volume in the data window or with print messages.
 
Csquared #:
Also are you sure it was "stuck" because for me I thought the symbols were getting stuck too but it turns out the symbols just weren't receiving ticks all at the same time. Especially on exotic pairs they wouldn't have a new m1 open tick until almost ten seconds after major pairs did and you can visually confirm this by looking at the tick volume in the data window or with print messages.

Sure I am sure 😉

I am not saying there was just no event (tick), but that the EventChartCustom() call was taking a lot of time to execute and return instead of being "instantaneous". I will check again and provide some data about it when I will have some spare time. For sure it depends of the computer resources.