Hello MT5 programmers.
I've been putting together a multi-symbol EA and am sharing the part of the expert that may be of some interest to some of you.
Please note that I am no programmer and have only started using MT5 in the last 2 weeks, so the code is by no means elegant nor probably very efficient. If someone can improve upon it and share that, great.
The basis of the multi-symbol operation is as follows:
1. Upon initialisation, synchronise history of all required symbols (28 in my case) and download sufficient bars for each. I have used the work of Andrey Khatimlianskii to do this.
2. Look for a new bar in the current time frame and symbol (EURUSD, M1 in my case). This is based on the approach provided by Andrew R Young in his book in MT4 programming.
3. Wait for all symbols to open a new bar that matches the time stamp of the chart to which the EA is attached. This is the while loop commencing at line 415 in the EA.
4. When a new bar is open on all symbols, download Closing price history for each symbol, sufficient to run the EA.
This seems to work fine in "live" mode as well as when used as part of an Indicator. However there is a problem that I can not solve. When running in Strategy Tester, the CopyTime loop exits on Time Expiry (line 455) as it is unable to find a new bar for all 28 symbols. If anyone can suggest a fix for this, that would be great as well.
cheers
Jim
Hi Jim,
You're off to a good start for only two weeks. If you're investing time in learning MQL5 I would advise picking up a good c++ tutorial (there aren't many good modern-MQL tutorials) so you can get a good foundation in OOP.
One thing I want to point out that will kill your EA is the fact that you hard coded all your symbols, and as soon as you use a broker with appended symbols (eg. EURUSDi) your entire system will fail to work.
Here is an example of using OOP and the standard library to accomplish the task (and more) while reducing a lot of redundant code. Feel free to take this EA and set a break-point at the OnInit() and step through the code... it will help you learn by watching what's happening at every step. Good luck on your learning journey! :)
//+------------------------------------------------------------------+ //| MultiCurrency.mq5 | //| nicholishen | //| www.reddit.com/u/nicholishenFX | //+------------------------------------------------------------------+ #property copyright "nicholishen" #property link "www.reddit.com/u/nicholishenFX" #property version "1.00" #include <Trade\SymbolInfo.mqh> #include <Arrays\ArrayObj.mqh> class MySymbol : public CSymbolInfo { protected: ENUM_TIMEFRAMES m_period; MqlRates m_rates[]; datetime m_bartime; public: MySymbol(const string symbol,ENUM_TIMEFRAMES period):m_period(period) { m_name = symbol; ArraySetAsSeries(m_rates,true); } int BarsTotal() const { return ArraySize(m_rates);} bool RefreshRates() { datetime btime = (datetime)SeriesInfoInteger(m_name,m_period,SERIES_LASTBAR_DATE); if(m_bartime != btime || BarsTotal() < 300) { if(CopyRates(m_name,m_period,0,Bars(m_name,m_period),m_rates)<300) return false; m_bartime = btime; } return CSymbolInfo::RefreshRates(); } double Open (const int i) const { return m_rates[i].open; } double High (const int i) const { return m_rates[i].high; } double Low (const int i) const { return m_rates[i].low ; } double Close (const int i) const { return m_rates[i].close;} datetime Time (const int i) const { return m_rates[i].time; } }; class MySymbolCollection : public CArrayObj { public: MySymbol* operator[](const int index)const{return(MySymbol*)At(index);} bool Init(string &syms[]) { Clear(); for(int i=0;i<ArraySize(syms);i++) { for(int j=0;j<SymbolsTotal(false);j++) { if(StringFind(SymbolName(j,false),syms[i])>=0) { Add(new MySymbol(SymbolName(j,false),Period())); break; } } } EventSetTimer(1); return true; } bool RefreshRates() { bool res = true; for(int i=0;i<Total();i++) if(!this[i].RefreshRates()) res = false; return res; } }; string sym[]={ "AUDCAD","AUDCHF","AUDJPY","AUDNZD","AUDUSD","EURAUD","GBPAUD", "CADCHF","CADJPY","EURCAD","GBPCAD","NZDCAD","USDCAD","CHFJPY", "EURCHF","GBPCHF","NZDCHF","USDCHF","EURGBP","EURJPY","EURNZD", "EURUSD","GBPJPY","GBPNZD","GBPUSD","NZDJPY","USDJPY","NZDUSD"}; MySymbolCollection symbols; //+------------------------------------------------------------------+ int OnInit() { //--- symbols.Init(sym); symbols.RefreshRates(); //--- return(INIT_SUCCEEDED); } void OnTick() { //--- if(!symbols.RefreshRates()) { Print(__FUNCTION__+" Waiting for data"); return; } else { for(int i=0;i<symbols.Total();i++) Print("My Symbol is ",symbols[i].Name()," and I have copied ",symbols[i].BarsTotal()," bars to rates."); ExpertRemove(); } // --- stuff with symbol data.... } //+------------------------------------------------------------------+ void OnTimer() { symbols.RefreshRates(); EventKillTimer(); }
Hi Jim,
You're off to a good start for only two weeks. If you're investing time in learning MQL5 I would advise picking up a good c++ tutorial (there aren't many good modern-MQL tutorials) so you can get a good foundation in OOP.
One thing I want to point out that will kill your EA is the fact that you hard coded all your symbols, and as soon as you use a broker with appended symbols (eg. EURUSDi) your entire system will fail to work.
Here is an example of using OOP and the standard library to accomplish the task (and more) while using over 500 less lines of code. Feel free to take this EA and set a break-point at the OnInit() and step through the code... it will help you learn by watching what's happening at every step. Good luck on your learning journey! :)
Thanks for the advice nicholishen.
I'll study your code.
Hi Jim,
You're off to a good start for only two weeks. If you're investing time in learning MQL5 I would advise picking up a good c++ tutorial (there aren't many good modern-MQL tutorials) so you can get a good foundation in OOP.
One thing I want to point out that will kill your EA is the fact that you hard coded all your symbols, and as soon as you use a broker with appended symbols (eg. EURUSDi) your entire system will fail to work.
Here is an example of using OOP and the standard library to accomplish the task (and more) while using over 500 less lines of code. Feel free to take this EA and set a break-point at the OnInit() and step through the code... it will help you learn by watching what's happening at every step. Good luck on your learning journey! :)
Just to be clear (for newbies) there is absolutely no need to know or even use OOP with mql5. It's optional.
Thanks Alain. Reassuring comment.
By the way, have you any suggestions as to why the CopyTime loop works fine in live mode but not in strategy tester?
Thanks Alain. Reassuring comment.
By the way, have you any suggestions as to why the CopyTime loop works fine in live mode but not in strategy tester?
I'm not sure there's too much to be gained in an all or nothing refresh strategy... Why not just update each symbol as a new bar comes in for that symbol? Here is the example in the code I posted...
bool RefreshRates() { datetime btime = (datetime)SeriesInfoInteger(m_name,m_period,SERIES_LASTBAR_DATE); if(m_bartime != btime || BarsTotal() < 300) { if(CopyRates(m_name,m_period,0,Bars(m_name,m_period),m_rates)<300) return false; m_bartime = btime; } return CSymbolInfo::RefreshRates(); }
If you're generating signals down the line that are contingent upon all charts being on the same bar you would add a boolean method to check your symbol-collection to see if they are all on the same bar. In this example I add the following method to the MySymbolCollection class.
bool IsAllSameBarTime() { for(int i=0;i<Total()-1;i++) if(this[i].Time(0) != this[i+1].Time(0)) return false; return Total() >= 2; }
And then implemented into your EA as
if(symbols.IsAllSameBarTime()) { //do stuff }
Finally, while OOP is not "required", your development capabilities will be greatly hampered if you're not familiar with OOP while developing for MQL5 because you won't be able to work with the standard library, most 3rd party libraries, and/or alter any of the EAs generated by the wizard. It is a steeper learning curve, but one that will pay off when it comes to development time and your ability to implement complex strategies, like the one you're working on.
I'm not sure there's too much to be gained in an all or nothing refresh strategy... Why not just update each symbol as a new bar comes in for that symbol? Here is the example in the code I posted...
If you're generating signals down the line that are contingent upon all charts being on the same bar you would add a boolean method to check your symbol-collection to see if they are all on the same bar. In this example I add the following method to the MySymbolCollection class.
And then implemented into your EA as
Finally, while OOP is not "required", your development capabilities will be greatly hampered if you're not familiar with OOP while developing for MQL5 because you won't be able to work with the standard library, most 3rd party libraries, and/or alter any of the EAs generated by the wizard. It is a steeper learning curve, but one that will pay off when it comes to development time and your ability to implement complex strategies, like the one you're working on.
Thanks. So much more to think about!
![MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal](https://c.mql5.com/i/registerlandings/logo-2.png)
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hello MT5 programmers.
I've been putting together a multi-symbol EA and am sharing the part of the expert that may be of some interest to some of you.
Please note that I am no programmer and have only started using MT5 in the last 2 weeks, so the code is by no means elegant nor probably very efficient. If someone can improve upon it and share that, great.
The basis of the multi-symbol operation is as follows:
1. Upon initialisation, synchronise history of all required symbols (28 in my case) and download sufficient bars for each. I have used the work of Andrey Khatimlianskii to do this.
2. Look for a new bar in the current time frame and symbol (EURUSD, M1 in my case). This is based on the approach provided by Andrew R Young in his book in MT4 programming.
3. Wait for all symbols to open a new bar that matches the time stamp of the chart to which the EA is attached. This is the while loop commencing at line 415 in the EA.
4. When a new bar is open on all symbols, download Closing price history for each symbol, sufficient to run the EA.
This seems to work fine in "live" mode as well as when used as part of an Indicator. However there is a problem that I can not solve. When running in Strategy Tester, the CopyTime loop exits on Time Expiry (line 455) as it is unable to find a new bar for all 28 symbols. If anyone can suggest a fix for this, that would be great as well.
cheers
Jim