Discussing the article: "Developing a multi-currency Expert Advisor (Part 1): Collaboration of several trading strategies"
class CStrategy : public CObject { protected: ulong m_magic; // Magic string m_symbol; // Символ (торговый инструмент) ENUM_TIMEFRAMES m_timeframe; // Период графика (таймфрейм) double m_fixedLot; // Размер открываемых позиций (фиксированный) public: // Конструктор CStrategy(ulong p_magic, string p_symbol, ENUM_TIMEFRAMES p_timeframe, double p_fixedLot); virtual int Init() = 0; // Инициализация стратегии - обработка событий OnInit virtual void Tick() = 0; // Основной метод - обработка событий OnTick };
Why do we need Init-method if there is a constructor?
For some reason, they immediately limited the TS class to one symbol and timeframe.
It seems to be more logical.
class SYSTEM { public: virtual void OnTick() {} };
Why do you need an Init method when you have a constructor?
For some reason they immediately limited the TS class to one symbol and timeframe.
I liked the author's approach. There is such a passage in the article:
Then the class will be abstract, as far as I understand.....
It will be. It is used in the descendant for some reason. If Deinit is not done (there is a destructor), it is logical not to do Init (there is a constructor).
//+------------------------------------------------------------------+ //| Конструктор | //+------------------------------------------------------------------+ CSimpleVolumeStrategy::CSimpleVolumeStrategy( ulong p_magic, string p_symbol, ENUM_TIMEFRAMES p_timeframe, double p_fixedLot, int p_signalPeriod, double p_signalDeviation, double p_signaAddlDeviation, int p_openDistance, double p_stopLevel, double p_takeLevel, int p_ordersExpiration, int p_maxCountOfOrders) : // Список инициализации CStrategy(p_magic, p_symbol, p_timeframe, p_fixedLot), // Вызов конструктора базового класса signalPeriod_(p_signalPeriod), signalDeviation_(p_signalDeviation), signaAddlDeviation_(p_signaAddlDeviation), openDistance_(p_openDistance), stopLevel_(p_stopLevel), takeLevel_(p_takeLevel), ordersExpiration_(p_ordersExpiration), maxCountOfOrders_(p_maxCountOfOrders) {} //+------------------------------------------------------------------+ //| Initialization function of the expert | //+------------------------------------------------------------------+ int CSimpleVolumeStrategy::Init() { // Загружаем индикатор для получения тиковых объемов iVolumesHandle = iVolumes(m_symbol, m_timeframe, VOLUME_TICK); // Устанавливаем размер массива-приемника тиковых объемов и нужную адресацию ArrayResize(volumes, signalPeriod_); ArraySetAsSeries(volumes, true); // Установим Magic Number для выставления ордеров через trade trade.SetExpertMagicNumber(m_magic); return(INIT_SUCCEEDED); }
And artificial strong narrowing of possible TCs is a strange solution.
You can also clearly see the cumbersomeness with input because of OOP. It would be good to remove it.
Init() has been left out for now because it is impossible to return a result from the constructor. But it is possible that we will never need to return something other than INIT_SUCCESS as a result of strategy initialisation. So it is quite possible that this method will be removed in the future.
The allocation of mandatory strategy properties in the form of symbol and timeframe is a deliberate limitation. By design, trading on several symbols will be done by working with many instances of this class's descendants, but each particular instance works with a single symbol. I have not yet come across any strategies that would be hindered by such a limitation. On the contrary, these parameters were found in every strategy considered, that's why it was decided to put them into the base class at once.
But in the future I plan to consider some multi-symbol strategies that cannot be divided into several independent single-symbol strategies (if any). I don't think that the presence of symbol and timeframe properties in the base class will greatly hinder the implementation of a child class in which several symbols and several timeframes will be used.
It won't interfere - 100%. It's just an unnecessary entity. OOP architecturally follows the principle from the general to the particular. You have made the general (base class) "private". Although all that is called there is CStrategy::Tick().
And I liked the author's approach. There is such a passage in the article:
Then the class will be abstract, as far as I understand.....
It is, it will be used only for obtaining child classes. You will not need to create objects of the base class CStrategy. But any object of the child class can be passed to the Expert Advisor object to be added to the CAdvisor::AddStrategy(CStrategy &strategy) method.
Init() has been left out for now because it is impossible to return a result from the constructor. But it is possible that we will never need to return something other than INIT_SUCCESS as a result of strategy initialisation. So, it is quite possible that this method will be removed in the future.
static int CStrategy::InitFlag = INIT_FAILED;
any child class object can be passed to the EA object to be added to the CAdvisor::AddStrategy(CStrategy &strategy) method.
It seems to be a compiler bug that it doesn't swear at this method signature when called like this.
expert.AddStrategy(new CSimpleVolumeStrategy( magic_ + 1, "EURGBP", PERIOD_H1, NormalizeDouble(0.34 * depoPart_, 2), 130, 0.9, 1.4, 231, 3750, 50, 600, 3)
It should be like this.
CAdvisor::AddStrategy(CStrategy* strategy)
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Check out the new article: Developing a multi-currency Expert Advisor (Part 1): Collaboration of several trading strategies.
There are quite a lot of different trading strategies. So, it might be useful to apply several strategies working in parallel to diversify risks and increase the stability of trading results. But if each strategy is implemented as a separate Expert Advisor (EA), then managing their work on one trading account becomes much more difficult. To solve this problem, it would be reasonable to implement the operation of different trading strategies within a single EA.
We need to decide what we want and what we have.
We have (or almost have):
We want:
We will use an object-oriented approach, MQL5 and a standard tester in MetaTrader 5.
The task at hand is quite large, so we will solve it step by step.
Author: Yuriy Bykov