Adapting EA robots to trading on custom renko charts in MetaTrader 5

29 May 2018, 15:38
Stanislav Korotky
4
6 089

Many trading strategies are based on well known and popular renko charts. MetaTrader 5 does not provide renko out of the box, so traders need to utilize the platform's MQL API. The simpliest solution would be a renko indicator. Unfortunately, a trading strategy does normally include some other indicators running on top of quotes, and it's not so easy to apply them to the renko indicator. As you may know, one indicator can be applied to a data produced by another indicator only if it's a single array. But we know numerous cases when an indicator is calculated on a group of arrays. For example, Parabolic SAR or Stochastic require both high and low price series. If someone would like to apply them to a renko indicator (which is most likely built as 4 buffers with DRAW_CANDLES style), then [s]he would require to rework the entire thing.

Of course, it would be great if all the indicators could be used on renko "as is", without any modifications. This can be done if renko is a chart indeed. But is this possible? The answer is yes.

MetaTrader 5 gives you means to create custom symbols (financial instruments) from user interface and MQL programs. They are based on arbitrary data (quotes) you provide, and then can be easily shown in standard MetaTrader 5 charts. This feature allows us to generate renko quotes and renko charts for any real symbol (instrument, ticker) available at your broker server. The only nuance we should note - the custom symbol must have a different name. For example, we can build renko for EURUSD and name it EURUSDr or EURUSD_renko, or whatever else, but not EURUSD or any other existing symbol name.

In my previous blog post I introduced a ready-made non-trading EA which generates custom renko charts for you.

As a result, a user can open the renko chart, and apply standard or 3-d party indicators to it as usual.

But wait - what about EAs? After all, MetaTrader implies automatic trading with EAs according to your strategy. So, will EAs run on the custom renko chart?

Well, technically - yes, but actually - no. You can place a EA on the renko chart but it'll do nothing. This is because EAs can work with custom symbols in the tester only. When it comes to real trading, it turns out that custom symbols do not belong to your broker server, so EAs can not issue trade requests. The fact that the renko is generated from a real symbol does not help. We need somehow adapt our EA if we want it to trade on the renko chart.

Stricktly speaking, we need to replace current work symbol (custom renko name) to underlying real symbol name in all MQL API calls related to trading. We need to change EA code for this, because MetaQuotes does not provide any alternative approaches internally. In 2017 I filed a suggestion to the service desk, which could eliminate the need of the workaround and excessive efforts. I proposed to introduce a special property for a custom symbol, which contains a name of a real symbol, used to generate the custom. Of course, this property should be optional and can be empty. One can call it "origin". In case the "origin" is filled in, any MQL calls for trading functions from EAs (which reference current custom symbol) should be transparently updated to the original symbol. Actually, every symbol already has a property SYMBOL_BASIS, which could play a role of "origin" for custom symbols. If my proposition would be accepted, no one would have the need to alter his/her EA code in order to use it on a custom chart. Yet the suggestion was declined. And this is why we need to discuss the matter in details in this blog post.

Before we continue, let us choose a simple specific example of EA, which we will adapt for renko charts. One of the simpliest strategies used on renko is two moving averages (MA) crossing.

The following screenshot illustrates the idea of the trading strategy. When fast (red) MA crosses slow (blue) MA in up or down direction, open buy or sell respectively.

2 MAs crossing on custom renko chart in MetaTrader 5

2 MAs crossing on custom renko chart in MetaTrader 5

We could code it from scratch, but MetaTrader 5 provides MQL Wizard, based on standard MQL library, supplied with every copy of the product. The library is far from ideal, and I'd not recommend it for real work, but it's bound to the Wizard, and this is crucial for many traders who are not programmers. So, if you have a code generated by the Wizard, you'll know how to prepare it for renko. And if your code does not use the library, it's either something simplier or more sophisticated, so you'll find appropriate changes better than I.

Surprisingly, the library does not contain a signal for 2 MAs crossing. I'd thought this is a commonplace and a must. Yet it's missing, and we need to implement such signal class ourselves. An example of such a class is attached below in the file Signal2MACross.mqh. I think the code is self-explaining. It starts with a special comment section which describes the signal and makes it "importable" into MetaEditor:

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signals of 2 MAs crosses                                   |
//| Type=SignalAdvanced                                              |
//| Name=2MA Cross                                                   |
//| ShortName=2MACross                                               |
//| Class=Signal2MACross                                             |
//| Page=signal_2mac                                                 |
//| Parameter=SlowPeriod,int,11,Slow MA period                       |
//| Parameter=FastPeriod,int,7,Fast Ma period                        |
//| Parameter=MAMethod,ENUM_MA_METHOD,MODE_LWMA,Method of averaging  |
//| Parameter=MAPrice,ENUM_APPLIED_PRICE,PRICE_OPEN,Price type       |
//| Parameter=Shift,int,0,Shift                                      |
//+------------------------------------------------------------------+
// wizard description end

Name of the class should correspond to the actual MQL class, which will follow. The signal uses 5 parameters, all are usual for MAs: 2 periods (fast and slow), as well as averaging method, price type and shift.

The class is derived from CExpertSignal as it should, and contains 2 instances of indicator objects CiMA, variables with work parameters values, methods used to set work parameters (their names should correspond to the names in the special comment above), and several reserved methods - actually overriden virtual methods from the parent class - which are called by the core to initialize indicators, verify settings, and detect trade signals for buys and sells.

class Signal2MACross : public CExpertSignal
{
  protected:
    CiMA              m_maSlow;         // object-indicator
    CiMA              m_maFast;         // object-indicator
    
    // adjustable parameters
    int               m_slow;
    int               m_fast;
    ENUM_MA_METHOD    m_method;
    ENUM_APPLIED_PRICE m_type;
    int               m_shift;
    
    // "weights" of market models (0-100)
    int               m_pattern_0;      // model 0 "fast MA crosses slow MA"

  public:
                      Signal2MACross(void);
                     ~Signal2MACross(void);
                     
    // parameters setters
    void              SlowPeriod(int value) { m_slow = value; }
    void              FastPeriod(int value) { m_fast = value; }
    void              MAMethod(ENUM_MA_METHOD value) { m_method = value; }
    void              MAPrice(ENUM_APPLIED_PRICE value) { m_type = value; }
    void              Shift(int value) { m_shift = value; }
    
    // adjusting "weights" of market models
    void              Pattern_0(int value) { m_pattern_0 = value; }
    
    // verification of settings
    virtual bool      ValidationSettings(void);
    
    // creating the indicator and timeseries
    virtual bool      InitIndicators(CIndicators *indicators);
    
    // checking if the market models are formed
    virtual int       LongCondition(void);
    virtual int       ShortCondition(void);

  protected:
    // initialization of the indicators
    bool              InitMAs(CIndicators *indicators);
    
    // getting data
    double            FastMA(int ind) { return(m_maFast.Main(ind)); }
    double            SlowMA(int ind) { return(m_maSlow.Main(ind)); }
};

The signal class provides the only trading model: when fast MA crosses slow MA - a request is issued to buy (if crossed up) or sell (if crossed down). So the weight of this pattern is assumed as 100.

Signal2MACross::Signal2MACross(void) : m_slow(11), m_fast(7), m_method(MODE_LWMA), m_type(PRICE_OPEN), m_shift(0), m_pattern_0(100)
{
}

The conditions for opening trades are detected in the following 2 methods (the coded conditions are not actually MAs crossing, but checkup which one is above of another, but this way it's a bit simplier):

int Signal2MACross::LongCondition(void)
{
  int result = 0;
  int idx = StartIndex();
  
  if(FastMA(idx) > SlowMA(idx))
  {
    result = m_pattern_0;
  }
  return(result);
}

int Signal2MACross::ShortCondition(void)
{
  int result = 0;
  int idx = StartIndex();

  if(FastMA(idx) < SlowMA(idx))
  {
    result = m_pattern_0;
  }
  return(result);
}

The function StartIndex here is inherited from the parent class. You can find the complete code in the attached file. You may use MetaEditor's built-in command "Go To Definition" for examining all identificators in the code and find out their inheritance from base classes hierarchy.

You should place the file Signal2MACross.mqh into MQL5/Include/Expert/Signal/MySignals folder, then restart MetaEditor (if it was running) in order to hook up the new signal into MQL Wizard.

Now we can generate EA based on our signal. Choose File | New to run MQL Wizard. In the Wizard choose:

Expert Adviser (generate);
Give a name for EA, for example Experts\Examples\MA2Cross;
Add our "Signals of 2 MAs crosses";
Leave Trailing stop not used;
Leave Trading with fixed volume;


And voila - you'll get the source code of EA, something like this (code style is refined):

#include <Expert\Expert.mqh>
#include <Expert\Signal\MySignals\Signal2MACross.mqh>
#include <Expert\Trailing\TrailingNone.mqh>
#include <Expert\Money\MoneyFixedLot.mqh>

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
// inputs for expert
input string             Expert_Title              = "MA2Cross";  // Document name
ulong                    Expert_MagicNumber        = 7623;
bool                     Expert_EveryTick          = false;
// inputs for main signal
input int                Signal_ThresholdOpen      = 10;          // Signal threshold value to open [0...100]
input int                Signal_ThresholdClose     = 10;          // Signal threshold value to close [0...100]
input double             Signal_PriceLevel         = 0.0;         // Price level to execute a deal
input double             Signal_StopLevel          = 0.0;         // Stop Loss level (in points)
input double             Signal_TakeLevel          = 0.0;         // Take Profit level (in points)
input int                Signal_Expiration         = 0;           // Expiration of pending orders (in bars)
input int                Signal_2MACross_SlowPeriod = 11;         // 2MA Cross(11,7,MODE_LWMA,...) Slow MA period
input int                Signal_2MACross_FastPeriod = 7;          // 2MA Cross(11,7,MODE_LWMA,...) Fast Ma period
input ENUM_MA_METHOD     Signal_2MACross_MAMethod  = MODE_LWMA;   // 2MA Cross(11,7,MODE_LWMA,...) Method of averaging
input ENUM_APPLIED_PRICE Signal_2MACross_MAPrice   = PRICE_OPEN;  // 2MA Cross(11,7,MODE_LWMA,...) Price type
input int                Signal_2MACross_Shift     = 0;           // 2MA Cross(11,7,MODE_LWMA,...) Shift
input double             Signal_2MACross_Weight    = 1.0;         // 2MA Cross(11,7,MODE_LWMA,...) Weight [0...1.0]
// inputs for money
input double             Money_FixLot_Percent      = 10.0;        // Percent
input double             Money_FixLot_Lots         = 0.1;         // Fixed volume

//+------------------------------------------------------------------+
//| Global expert object                                             |
//+------------------------------------------------------------------+
CExpert ExtExpert;

//+------------------------------------------------------------------+
//| Initialization function of the expert                            |
//+------------------------------------------------------------------+
int OnInit()
{
  // Initializing expert
  if(!ExtExpert.Init(Symbol(), Period(), Expert_EveryTick, Expert_MagicNumber))
  {
    printf(__FUNCTION__ + ": error initializing expert");
    ExtExpert.Deinit();
    return(INIT_FAILED);
  }
  // Creating signal
  CExpertSignal *signal = new CExpertSignal;
  if(signal == NULL)
  {
    printf(__FUNCTION__ + ": error creating signal");
    ExtExpert.Deinit();
    return(INIT_FAILED);
  }
  
  ExtExpert.InitSignal(signal);
  signal.ThresholdOpen(Signal_ThresholdOpen);
  signal.ThresholdClose(Signal_ThresholdClose);
  signal.PriceLevel(Signal_PriceLevel);
  signal.StopLevel(Signal_StopLevel);
  signal.TakeLevel(Signal_TakeLevel);
  signal.Expiration(Signal_Expiration);
  
  // Creating filter Signal2MACross
  Signal2MACross *filter0 = new Signal2MACross;
  if(filter0 == NULL)
  {
    printf(__FUNCTION__ + ": error creating filter0");
    ExtExpert.Deinit();
    return(INIT_FAILED);
  }
  signal.AddFilter(filter0);
  
  // Set filter parameters
  filter0.SlowPeriod(Signal_2MACross_SlowPeriod);
  filter0.FastPeriod(Signal_2MACross_FastPeriod);
  filter0.MAMethod(Signal_2MACross_MAMethod);
  filter0.MAPrice(Signal_2MACross_MAPrice);
  filter0.Shift(Signal_2MACross_Shift);
  filter0.Weight(Signal_2MACross_Weight);

  ...
  
  // Check all trading objects parameters
  if(!ExtExpert.ValidationSettings())
  {
    ExtExpert.Deinit();
    return(INIT_FAILED);
  }
  
  // Tuning of all necessary indicators
  if(!ExtExpert.InitIndicators())
  {
    printf(__FUNCTION__ + ": error initializing indicators");
    ExtExpert.Deinit();
    return(INIT_FAILED);
  }

  return(INIT_SUCCEEDED);
}

...

The complete example file MA2Cross-step0.mq5 is attached below (the suffix 0 denotes initial evolution stage in the code edition process).

Before we proceed, let's discuss some nuances of renko. Every renko box does not exist until it's completely formed by price movement. When the rightmost box is just created, the next box position - even its open price - is not yet known, because there can be 2 opposite directions for future movement. This means that close price is the only distinctive price type for renko. This is why we change default value for Signal_2MACross_MAPrice parameter to PRICE_CLOSE. You can play with other price types on your own, but I'm sure the essense of renko is in eliminating price fluctuations, which is done through respecting the box granularity, and hence other price types are evil.

Also note that 0-th renko bar is always incomplete box (in many cases it's not even a box), so we need to change Signal_2MACross_Shift parameter from default 0 to value 1.

At last, let's make Expert_EveryTick a published input parameter and set it to true. This way we make sure that our EA can correctly process multicurrency and multitimeframe situations, which will be used later.

As semantics of fast and slow periods implies, fast period should always be smaller than slow, so we add the following line in OnInit in order to drop useless optimization passes in future:

if(Signal_2MACross_SlowPeriod <= Signal_2MACross_FastPeriod) return INIT_PARAMETERS_INCORRECT;

The example file is attached below as MA2Cross-step1.mq5.

Now all is ready to compile EA, run it in the tester, and even optimize.

For this publication I have generated custom renko symbols with box size 100 points (5 digits) for EURUSD, and done this twice using 2 different hosting timeframes - H1 and M1. As a result, I have 2 custom symbols: EURUSD_H1_r100 and EURUSD_M1_r100 respectively.

Remeber that we need to select our custom symbol in the tester, and choose timeframe M1, since renko is always generated in this most accurate timeframe.

I used fast and slow MA periods for optimization on 2018 and got a bunch of profitable results, one of which are periods 9 and 12.

Here is how this EA trades on 2017-2018 with these settings for both EURUSD_H1_r100 and EURUSD_M1_r100:

Tester result for 2 MAs crossing strategy on custom renko built from EURUSD H1

Tester result for 2 MAs crossing strategy on custom renko built from EURUSD H1

Tester result for 2 MAs crossing strategy on custom renko built from EURUSD M1

Tester result for 2 MAs crossing strategy on custom renko built from EURUSD M1

The results are slightly different, because the accuracy of renko generated from higher timeframe (H1) is lower than that generated from lower timeframe (M1). The reason why you would like to use a higher timeframe is efficiency (it's calculated faster) and deeper history. Indeed with a given number of bars in a chart, say, 10000 bars of H1 will cover 60 times deeper history of quotes than 10000 bars of M1. On the other hand, for higher precision (when it's important) it's recommended to use as low timeframe as possible for running RenkoCharts generator. M1 is the best.

You may notice that history quality is 0% in both reports. This is because our custom symbols do not contain ticks. The utility robot RenkoCharts emulates ticks only online - for triggering OnTick event in EAs which are attached to the renko charts, but the ticks are not generated on the history.

Strictly speaking, we can't build proper ticks there in principle, because of contradiction between renko box structure and ticks timing. Historical ticks can not be used, cause they do not fit into renko boxes, and specially crafted ticks can not be used, cause they will differ from actual price movements.

What we have done so far is a verification that EA can trade and can be optimized on the custom renko symbol. But trading is currently limited to the tester. In order to make this EA capable of trading online we need to add something in its code.

First, let's add new input variable:

input string             WorkSymbol = "";

It will contain a name of a real symbol available from broker. It will be used in trade requests. In our test case it should be EURUSD.

At first glance, what we should do is to change the expert object initialization like this:

if(!ExtExpert.Init(WorkSymbol, Period(), Expert_EveryTick, Expert_MagicNumber))

Unfortunately, this won't work, because the method Init checks if the passed symbol name is equal to Symbol() and if it's not - returns an error and stops EA. Moreover, even without this limitation there is another problem: Init method invokes other initialization methods inside itself, including InitSignal method, which prepares signals to work with the same symbol. In our case the symbol used for signals should differ from the symbol for trading.

A possible workaround can comprise 2 steps.

1. Leave initialization of the expert object as is (with Symbol() reference), but add 1 line below:

if(WorkSymbol != "") ExtExpert.Symbol(WorkSymbol);

This will change the expert's symbol in deferred manner and will enable trading on a symbol other than Symbol(). But since it also affects the symbol of signals, which we need to preserve pointing to the custom renko symbol, there is the need of the 2-nd step.

2. In order to separate signal symbol from work symbol of the expert object we subclass CExpert class in the following manner:

class CustomExpert : public CExpert
{
  CSymbolInfo mySymbol; // auxiliary member
  
  public:
  CustomExpert() : CExpert()
  {
  }
  
  bool InitSignal(CExpertSignal *signal) override
  {
    if(m_signal != NULL) delete m_signal;
   
    if(signal == NULL)
    {
      if((m_signal = new CExpertSignal) == NULL) return(false);
    }
    else
    {
      m_signal = signal;
    }

    mySymbol.Name(Symbol()); // new line
    if(!m_signal.Init(&mySymbol, Period(), m_adjusted_point)) return(false); // changed line
    m_signal.EveryTick(m_every_tick);
    m_signal.Magic(m_magic);
    return(true);
  }
};

Just a side note on OOP. It's against good coding style to hardcode global Symbol() and Period() in the class, but we do it as a quick and dirty hack. The better approach would be to define constructor with custom symbol and timeframe parameters, store them in member variables and then access only those variables inside the method.

The only overriden method is InitSignal. Its code is almost completely taken from the parent class, but it specifies Symbol() explicitly, where it was initilized through member variable m_symbol like this (in Expert.mqh):

if(!m_signal.Init(GetPointer(m_symbol), m_period, m_adjusted_point)) return(false);

m_symbol here contains the work symbol of the expert, which we'd like to decouple from signals, so replacing the line does the job.

Of course, we should now instantiate the expert object of our own class:

//+------------------------------------------------------------------+
//| Global expert object                                             |
//+------------------------------------------------------------------+
CustomExpert ExtExpert; // was CExpert ExtExpert;

The resulting file MA2Cross-step2.mq5 is attached below. If WorkSymbol is left empty, the new version works exactly the same as the previous one, trading custom symbol. But we're after new possibility.

Now we can set WorkSymbol to EURUSD and run EA in the tester to see what happens. It does indeed trade EURUSD despite renko symbol selected in the tester. Here is 2 reports, again for EURUSD_H1_r100 and EURUSD_M1_r100.

Tester result for 2 MAs crossing strategy on custom renko built from H1 with trading on underlying symbol EURUSD

Tester result for 2 MAs crossing strategy on custom renko built from H1 with trading on underlying symbol EURUSD

Tester result for 2 MAs crossing strategy on custom renko built from M1 with trading on underlying symbol EURUSD

Tester result for 2 MAs crossing strategy on custom renko built from M1 with trading on underlying symbol EURUSD

You may notice that H1 report looks like the holy grail. To understand why this is so, let's dig into the renko building process.

Every renko box has its open time initialized at the moment when previous box was closed. Every renko box is actually M1 bar. Its close time does not correspond to the time when the box was actually closed. This is a general limitation of M1 chart used for renko, yet we are compelled to use M1 as the lesser available timeframe. Also remember that in MetaTrader's charts, bars can not differ in duration.

Hence, most of renko boxes have close time earlier than corresponding moments when they were completed on real time axis. In other words, renko box can disclose the future to EA algorithm. Main question is how much this "earlier" time is, or how far in the future the robot can see. The answer depends from the timeframe used for renko generation. When it's M1, EA can cheat only within 1 minute, which is usually not so much (scalpers are out of consideration here). But when it's H1, EA can see up to an extra 1 hour - the larger the box size the larger probability of bias.

For example, if renko box size is 100 points, and there is a H1 bar with range of 300 points at 12:00, then RenkoCharts on H1 generates 3 boxes with times 12:00, 12:01, 12:02. If you look at this H1 bar in more detail, say on the timeframe M15, you will most likely see that the whole movement is distributed inside 1 hour differently: 100 points in 12:00, 100 points in 12:15, 0 (flat) in 12:30 and 100 points in 12:45. Then generation of the renko from M15 would give renko boxes at times 12:00, 12:15, 12:45, which are closer to reality.

You may ask, why renko boxes from a single bar have open times with 1 minute step, and why not to distribute them evenly on entire duration of the bar. This was initially done for correct processing of fast price movements - in such cases we need to place renko boxes as close to each other as possible. In new version of RenkoCharts this is improved via speculation on how many boxes forthcoming bar can create, so boxes are placed with larger time step inbetween.  Anyway, when we want higher quality, we can use M1 as generative timeframe.

Since the renko from a larger timeframe, such as H1, can run ahead of reality, it throws predictive trading signals. When looking at the chart with signals (trades), you can clearly see how H1-based renko performs more early and hence more beneficial entries than M1-based.

Trades according to 2 MAs crossing signals from custom renko generated from H1 (renko not shown)

Trades according to 2 MAs crossing signals from custom renko generated from H1 (renko not shown)

Trades according to 2 MAs crossing signals from custom renko generated from M1 (renko not shown)

Trades according to 2 MAs crossing signals from custom renko generated from M1 (renko not shown)

Don't be mistaken by the pictures: although they are regular charts for better understanding, the trades are initiated by MAs from renko.

Also you can grasp the problem better by comparing trades from reports.

Table of trades according to 2 MAs crossing signals from custom renko generated from H1

Table of trades according to 2 MAs crossing signals from custom renko generated from H1

Table of trades according to 2 MAs crossing signals from custom renko generated from M1

Table of trades according to 2 MAs crossing signals from custom renko generated from M1

So, when a signal from 2 MAs is formed on a renko box, EA issues a trade request with real symbol and timing, which is usually near the latest bar on generative timeframe. This is why the trades in H1-based table are aligned to 1 hour or near it.

On M1-based renko the problem is faint, so testing and optimization results should be adequate.

You may ask, why not to use ticks to generate renko? Does this help? Actually, no, because MetaTrader 5 does not allow for time difference between bars smaller than 1 minute, so even if we could calculate renko from historical ticks, we could not align them with more precision than 1 minute. Besides, processing of ticks would be much more resource consuming. Currently, generation of renko on M1 for several years takes several minutes, but with ticks (which can be thousands in a minute) it would be most likely hours.

Nevertheless, is it possible to eliminate the problem or make it less noticable?

Yes, it is - by turning all up side down. Every renko box (M1 bar) should be marked by (placed at) its close time, not open. The close time is perfect for testing on history (no peeping into the future). But this introduces another problem in online mode: what to show on renko chart before box is actually closed? Indeed, from the moment when previous box is formed and until a new one will be fully completed (when we finally know its close price and time), we can't start a new bar, because otherwise it will have open time other than (and probably much earlier than) close time. This would lead to very strange "renko" with variable bar duration. But we know, this is not possible in MetaTrader, and moreover, this would spoil all the effect of renko, which is intended for eliminating time from bar series.

So, with the closing time used for renko bar placement, renko generator can form boxes discontinuously only: every next bar will first appear only when fully completed, and before this moment there will be no ticks on renko chart (!), because otherwise MetaTrader would create new bar itself from the ticks (this is how it works). In other words, this mode is somewhat similar to "open prices" mode of the tester, but it's "close prices" and online! In this mode we get only 1 tick per box, when the box appears on the chart, and this happens only when the box is formed completely. Probably this is not a problem in case of renko, because renko implies thinking in boxes, and waiting for new box completion provides noice reduction, which is the main feature of renko.

This mode is supported in the upcoming version of RenkoCharts, and enabled by special boolean input CloseTimeMode.

Before this moment we placed EA on custom renko chart and traded a different real symbol. Actually we can do other way round: place EA on the real chart (and trade its symbol in natural way), but generate signals for it with indicators calculated on custom renko. This is the point where we employ the fact that our EA is configured for trading by ticks: every next renko box can be formed on any tick, inside a bar on regular chart.

The source code requires little changes for this. Let's duplicate existing MA2Cross.mq5 (from the latest step) under a new name - MA2Cross2.mq5 - and edit it. Remove WorkSymbol input and add 2 other instead:

input string             SignalSymbol = "";
input ENUM_TIMEFRAMES    SignalTimeframe = PERIOD_CURRENT;

SignalSymbol and SignalTimeframe are for custom symbol and custom timeframe, on which indicators to run.

In the CustomExpert class change 2 lines with signal initialization:

mySymbol.Name(SignalSymbol != "" ? SignalSymbol : Symbol());
if(!m_signal.Init(&mySymbol, SignalTimeframe, m_adjusted_point)) return(false);

Now we can test new EA with the previous settings, but this time we run the test on EURUSD (timeframe can vary, but M1 is easier to analyze), and set SignalSymbol to one of custom renko symbol. SignalTimeframe should be always 1, because renko charts are M1.

Here is 2 reports obtained during tests with SignalSymbol EURUSD_H1_r100 and EURUSD_M1_r100.

Tester report for 2 MAs crossing EA, running on EURUSD chart with indicator signals coming from H1 renko

Tester report for 2 MAs crossing EA, running on EURUSD chart with indicator signals coming from H1 renko

Tester report for 2 MAs crossing EA, running on EURUSD chart with indicator signals coming from M1 renko

Tester report for 2 MAs crossing EA, running on EURUSD chart with indicator signals coming from M1 renko

Also you may want to look at and compare the tables of deals for both cases.

Table of deals, 2 MAs crossing EA with indicators on custom renko built from H1

Table of deals, 2 MAs crossing EA with indicators on custom renko built from H1

Table of deals, 2 MAs crossing EA with indicators on custom renko built from M1

Table of deals, 2 MAs crossing EA with indicators on custom renko built from M1

Comparison of deals of the two EAs - previous MA2Cross, which runs on renko symbol and trades on regular, and latest MA2Cross2, which runs on regular symbol and receives signals from renko, - shows that trades are performed almost at the same time: differences are 1 second maximum. Nevertheless, during these seconds price changes, and thus we get similar but not identical results. Which one is more precise? I'd suggest that less profitable variant with MA2Cross2 is closer to reality. Anyway, any of the two approaches makes it possible to estimate and optimize trading strategies on renko, and then trade online.

Some things can be improved for higher accuracy, but this is a matter of further work and publications.

Stay tuned.




Share it with friends: