Equal volume and range charts in MetaTrader 5

3 July 2018, 00:26
Stanislav Korotky
21
2 798

In equivolume (equal volume) charts horizontal axis comprises not specific timestamps, but an ordered sequence of bars, each of which contains the same volume. Neither MetaTrader 4 nor MetaTrader 5 provides equivolume charts out of the box.

For MetaTrader 4 it's possible to generate such charts as offline charts. This method is described in the article Equivolume Charting Revised.

For MetaTrader 5 we can implement the same algorithm using custom symbols. For the simplicity we can just take the expert adviser from the article and adapt it to the new MT5 features. Here is my quick and dirty implementation.

Lets start from the file EqualVolumeBars.mq4 attached below just for reference, and alter it step by step. This version was slightly improved in comparison to the original, but this is not important here.

For proper compilation, change 'extern' keyword to 'input' everywhere. Instead of StartYear and StartMonth inputs we'll use the single one - StartDate (don't use too distant dates in past while processing real ticks - this may take quite some time and space on your disk). The input CustomPeriod defines custom period of offline chart in MetaTrader 4, which is not applicable in MetaTrader 5, so remove it.

First, we should note that the volumes in MT4 are tick volumes, that is actually counters of ticks per bar. The main idea of the legacy version is to process M1 bars (with their tick volumes) or external csv-file with real ticks, count incoming ticks, and form every new equivolume bar as soon as predefined number of ticks is collected. The equivolume bars are outputted to a history file (with hst-extension), which can be opened in MetaTrader 4 as an offline chart. Range bars are formed similarly with the only difference that every new bar is outputted when price moves up or down to predefined number of points. The type of resulting chart is determined by the input WorkMode. The enumeration mode used in the input WorkMode can be potentially extended to support real volumes available in MetaTrader 5 (in stock exchange instruments), but lets leave it for future work.

The input parameter FromM1 controls if EA processes M1 bars (true, by default) or external ticks (false).

For MetaTrader 5 all the code related to reading and writing files is of no use and should be eliminated. Instead, we will read real ticks history and write equal volume bars into special custom symbol.

Custom symbols can be easily created and managed by the library Symbol. I use its slightly modified version attached below as Symbol2.mqh. In the EA code the library is plugged in as include: 

#include <Symbol2.mqh>

Then when necessary we can create a custom symbol based on current work symbol _Symbol of the chart as follows:

const SYMBOL Symb(symbolName);
Symb.CloneProperties(_Symbol);

where symbolName is a string with our custom symbol name.

Then when new equal volume bar is created or changed, the original code calls function WriteToFile. New implementation of this function for MetaTrader 5 should utilize built-in function CustomRatesUpdate, something like this:

void WriteToFile(datetime t, double o, double l, double h, double c, long v)
{
  MqlRates r[1];

  r[0].time = t;
  r[0].open = o;
  r[0].low = l;
  r[0].high = h;
  r[0].close = c;
  r[0].tick_volume = v;
  r[0].spread = 0;
  r[0].real_volume = 0;

  CustomRatesUpdate(symbolName, r);
}

Surprisingly, the cycle through M1 bars of work symbol can be left almost intact. That is, adaptation of WriteToFile is sufficient for the mode FromM1=true to work in its new reincarnation. The only nuance which can be improved - the function RefreshWindow. In MetaTrader 4 it sends Windows message to emulate new tick in offline charts. In MetaTrader 5 we should reinvent this function using CustomTicksAdd, something like this:

void RefreshWindow(const datetime t)
{
  MqlTick ta[1];
  SymbolInfoTick(_Symbol, ta[0]);
  ta[0].time = t;
  ta[0].time_msc = ta[0].time * 1000;
  if(CustomTicksAdd(symbolName, ta) == -1)
  {
    Print("Not ticked:", GetLastError(), " ", (long) ta[0].time);
    ArrayPrint(ta);
  }
  // remove the temporary tick
  CustomTicksDelete(symbolName, ta[0].time_msc, LONG_MAX);
}

Since we generate ticks only for the puspose of triggering OnTick event in EAs placed on our custom charts, we remove ticks just after their addition (though this is not obligatory, I used to do this primarily because I encounter errors for unexplainable reasons from time to time, while adding ticks to the tick base, so it's safer to have the tick base empty when it's not required, at least at the current stage of MT5).

Another mode - FromM1=false - is a bit harder one. Here we need to read real tick history using built-in function CopyTicks. All the related stuff is packed into the functions TicksBufferFilled, TicksBufferRead, which use an array of ticks:

MqlTick array[];

The ticks are requested by fragments of TICKS_ARRAY ticks, defined as: 

#define TICKS_ARRAY 10000

You may change the value as you wish. I don't include the functions' code here, it's very straighforward and can be found in the complete source code. 

On every start EA cleans up current history of the custom symbols, if it's already exist, using the function Reset. This mimics the original code writing hst-file from very beginning. If you need, you can implement a continuation logic to keep already processed history and figure out how to proceed from in-between state.

We're almost done.

The new code uses time series functions such as iTime, iOpen, iClose, etc. These functions were introduced in MetaTrader 5 starting from build 1860. If you use older build you need to use analogous functions implemented in MQL. I'm attaching the file mt4_dataseries.mqh as one of possible solutions.

You can easily find other minor changes by contextual comparison of the original file EqualVolumeBars.mq4 and the resulting EqualVolumeBars.mq5, which is also attached below.

Let us look how new EA works. Here is the work symbol chart EURUSD M1, where EA is placed:

EqualVolumeBars EA running on EURUSD M1 chart in MetaTrader 5

EqualVolumeBars EA running on EURUSD M1 chart in MetaTrader 5

And here is the generated equivolume chart with 100 ticks per bar.

Equal volumes chart with 100 ticks per bar, generated by EqualVolumeBars EA in MetaTrader 5

Equal volumes chart with 100 ticks per bar, generated by EqualVolumeBars EA in MetaTrader 5 

Please note that volumes are the same on all bars (except for the last bar which continues counting ticks). Also note that actual timestamps of bars are fictious. Nevertheless, since we generate ticks for the custom symbol, you may place your own EA on the equivolume chart and it'll receive OnTick events with latest known price and potentially can trade on originating EURUSD symbol. Of course, you may place indicators, objects and other stuff on the equal volume charts as well.