Download MetaTrader 5

Features of Custom Indicators Creation

18 August 2005, 17:27
MetaQuotes Software Corp.
2
5 726

Creation of Custom Indicators in the MetaTrader trading system has a number of features.

  • For the program to be considered a Custom Indicator, it must fall under one of two definitions:

    #property  indicator_chart_window      // an indicator is drawn in the main chart window

    or

    #property  indicator_separate_window   // an indicator is drawn in a separate window
  • To set the scale of a separate indicator window, the following definitions are used:

    #property  indicator_minimum Min_Value
    #property  indicator_maximum Max_Value

    where "Min_Value" and "Max_Value" are corresponding values. For example, these values must be 0 and 100 respectively for custom indicator RSI.

  • The number of indicator arrays necessary for drawing an indicator must be defined as follows:

    #property  indicator_buffers N

    where N can take on values from 1 to 8.

  • The color of lines in an indicator is set by the following definitions:

    #property  indicator_color1  Silver
    #property  indicator_color2  Red
    ...
    #property  indicator_colorN  <SomeColor>

    where N is the number of indicator arrays defined by "#define indicator_buffer".

  • There are functions allowing to control the process of indicator calculation and visualization. Custom Indicator of Ishimoku Kinko Hyo is used here to illustrate it:

    //+------------------------------------------------------------------+
    //|                                                     Ichimoku.mq4 |
    //|                      Copyright © 2004, MetaQuotes Software Corp. |
    //|                                       http://www.metaquotes.net/ |
    //+------------------------------------------------------------------+
    #property copyright "Copyright © 2004, MetaQuotes Software Corp."
    #property link      "http://www.metaquotes.net/"
     
    #property indicator_chart_window
    #property indicator_buffers 7
    #property indicator_color1 Red
    #property indicator_color2 Blue
    #property indicator_color3 SandyBrown
    #property indicator_color4 Thistle
    #property indicator_color5 Lime
    #property indicator_color6 SandyBrown
    #property indicator_color7 Thistle
    //---- input parameters
    extern int Tenkan=9;
    extern int Kijun=26;
    extern int Senkou=52;
    //---- indicator buffers
    double Tenkan_Buffer[];
    double Kijun_Buffer[];
    double SpanA_Buffer[];
    double SpanB_Buffer[];
    double Chinkou_Buffer[];
    double SpanA2_Buffer[];
    double SpanB2_Buffer[];
    //---- span_a drawing begin
    int a_begin;
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int init()
      {
    //----
       SetIndexStyle(0,DRAW_LINE);
       SetIndexBuffer(0,Tenkan_Buffer);
       SetIndexDrawBegin(0,Tenkan-1);
       SetIndexLabel(0,"Tenkan Sen");
    //----
       SetIndexStyle(1,DRAW_LINE);
       SetIndexBuffer(1,Kijun_Buffer);
       SetIndexDrawBegin(1,Kijun-1);
       SetIndexLabel(1,"Kijun Sen");
    //----
       a_begin=Kijun; if(a_begin&lt;Tenkan) a_begin=Tenkan;
       SetIndexStyle(2,DRAW_HISTOGRAM,STYLE_DOT);
       SetIndexBuffer(2,SpanA_Buffer);
       SetIndexDrawBegin(2,Kijun+a_begin-1);
       SetIndexShift(2,Kijun);
       SetIndexLabel(2,NULL);
       SetIndexStyle(5,DRAW_LINE,STYLE_DOT);
       SetIndexBuffer(5,SpanA2_Buffer);
       SetIndexDrawBegin(5,Kijun+a_begin-1);
       SetIndexShift(5,Kijun);
       SetIndexLabel(5,"Senkou Span A");
    //----
       SetIndexStyle(3,DRAW_HISTOGRAM,STYLE_DOT);
       SetIndexBuffer(3,SpanB_Buffer);
       SetIndexDrawBegin(3,Kijun+Senkou-1);
       SetIndexShift(3,Kijun);
       SetIndexLabel(3,NULL);
       SetIndexStyle(6,DRAW_LINE,STYLE_DOT);
       SetIndexBuffer(6,SpanB2_Buffer);
       SetIndexDrawBegin(6,Kijun+Senkou-1);
       SetIndexShift(6,Kijun);
       SetIndexLabel(6,"Senkou Span B");
    //----
       SetIndexStyle(4,DRAW_LINE);
       SetIndexBuffer(4,Chinkou_Buffer);
       SetIndexShift(4,-Kijun);
       SetIndexLabel(4,"Chinkou Span");
    //----
       return(0);
      }
    //+------------------------------------------------------------------+
    //| Ichimoku Kinko Hyo                                               |
    //+------------------------------------------------------------------+
    int start()
      {
       int    i,k;
       int    counted_bars=IndicatorCounted();
       double high,low,price;
    //----
       if(Bars&lt;=Tenkan || Bars&lt;=Kijun || Bars&lt;=Senkou) return(0);
    //---- initial zero
       if(counted_bars&lt;1)
         {
          for(i=1;i&lt;=Tenkan;i++)    Tenkan_Buffer[Bars-i]=0;
          for(i=1;i&lt;=Kijun;i++)     Kijun_Buffer[Bars-i]=0;
          for(i=1;i&lt;=a_begin;i++) { SpanA_Buffer[Bars-i]=0; SpanA2_Buffer[Bars-i]=0; }
          for(i=1;i&lt;=Senkou;i++)  { SpanB_Buffer[Bars-i]=0; SpanB2_Buffer[Bars-i]=0; }
         }
    //---- Tenkan Sen
       i=Bars-Tenkan;
       if(counted_bars>Tenkan) i=Bars-counted_bars-1;
       while(i>=0)
         {
          high=High[i]; low=Low[i]; k=i-1+Tenkan;
          while(k>=i)
            {
             price=High[k];
             if(high&lt;price) high=price;
             price=Low[k];
             if(low>price)  low=price;
             k--;
            }
          Tenkan_Buffer[i]=(high+low)/2;
          i--;
         }
    //---- Kijun Sen
       i=Bars-Kijun;
       if(counted_bars>Kijun) i=Bars-counted_bars-1;
       while(i>=0)
         {
          high=High[i]; low=Low[i]; k=i-1+Kijun;
          while(k>=i)
            {
             price=High[k];
             if(high<price) high=price;
             price=Low[k];
             if(low>price)  low=price;
             k--;
            }
          Kijun_Buffer[i]=(high+low)/2;
          i--;
         }
    //---- Senkou Span A
       i=Bars-a_begin+1;
       if(counted_bars>a_begin-1) i=Bars-counted_bars-1;
       while(i>=0)
         {
          price=(Kijun_Buffer[i]+Tenkan_Buffer[i])/2;
          SpanA_Buffer[i]=price;
          SpanA2_Buffer[i]=price;
          i--;
         }
    //---- Senkou Span B
       i=Bars-Senkou;
       if(counted_bars>Senkou) i=Bars-counted_bars-1;
       while(i>=0)
         {
          high=High[i]; low=Low[i]; k=i-1+Senkou;
          while(k>=i)
            {
             price=High[k];
             if(high&lt;price) high=price;
             price=Low[k];
             if(low>price)  low=price;
             k--;
            }
          price=(high+low)/2;
          SpanB_Buffer[i]=price;
          SpanB2_Buffer[i]=price;
          i--;
         }
    //---- Chinkou Span
       i=Bars-1;
       if(counted_bars>1) i=Bars-counted_bars-1;
       while(i>=0) { Chinkou_Buffer[i]=Close[i]; i--; }
    //----
       return(0);
      }
    //+------------------------------------------------------------------+
  • "SetIndexStyle" function controls drawing parameters of an indicator array. The drawing mode of DRAW_LINE assumes that lines between values defined in a corresponding indicator array are drawn. The drawing mode of DRAW_HISTOGRAM having been applied to the main window indicator has its special features, as well. A histogram is drawn between corresponding values of two index arrays: an even one (here: SpanA_Buffer) and an odd one (here: SpanB_Buffer). At that, the color of the index array is used the value of which is higher.

  • "SetIndexDrawBegin" function specifies which element significant data of indicator array start at.

  • "SetIndexBuffer" function allows to declare any one-dimensional array of the "double" type as an index array. At that, the system will manage index arrays. It is for this reason that is not required to specify these arrays.

    //---- indicator buffers
    double Tenkan_Buffer[];
    double Kijun_Buffer[];
    double SpanA_Buffer[];
    double SpanB_Buffer[];
    double Chinkou_Buffer[];
    double SpanA2_Buffer[];
    double SpanB2_Buffer[];

    The ArrayResize function cannot be applied to indicator arrays, either, as it is useless. It is useless, as well, to apply the ArrayInitialize function to indicator arrays, especially as 'init' function, when indicator arrays have not been allocated yet. Indicator arrays are initialized automatically during memory allocation and reallocation. EMPTY_VALUE, or the value specified by SetIndexEmptyValue function, are used as initializing values. "Empty" values are not displayed.

  • The "SetIndexLabel" function sets the name to be displayed in tool tips and in data window along with the corresponding value (the "ValueN" is set by default, where N is the number of the index array). If NULL is transferred instead of a name, the corresponding value will be displayed neither in tool tips, nor in the data window. In the given case, clouds are hatched using a histogram and limited by a line. At that, the values of corresponding "line" and "histogram" arrays are the same, and it is possible to show only one of them.

  • The "IndicatorCounted" function allows to organize an economic calculation of an indicator. This function returns the amount of bars by the moment of the preceding launch of the indicator, i.e., the amount of bars having already been calculated (potentially, if there were no errors or early termination during the preceding launch) which do not need any recalculation. At reinitialization of the custom indicator or significant updating of history data, this amount will be automatically reset to 0.

  • Let us discuss one more example. The custom indicator named Accelerator/Decelerator Oscillator:

    //+------------------------------------------------------------------+
    //|                                                  Accelerator.mq4 |
    //|                      Copyright © 2005, MetaQuotes Software Corp. |
    //|                                       http://www.metaquotes.net/ |
    //+------------------------------------------------------------------+
    #property  copyright "Copyright © 2005, MetaQuotes Software Corp."
    #property  link      "http://www.metaquotes.net/"
    //---- indicator settings
    #property  indicator_separate_window
    #property  indicator_buffers 3
    #property  indicator_color1  Black
    #property  indicator_color2  Green
    #property  indicator_color3  Red
    //---- indicator buffers
    double     ExtBuffer0[];
    double     ExtBuffer1[];
    double     ExtBuffer2[];
    double     ExtBuffer3[];
    double     ExtBuffer4[];
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int init()
      {
    //---- 2 additional buffers are used for counting.
       IndicatorBuffers(5);
    //---- drawing settings
       SetIndexStyle(0,DRAW_NONE);
       SetIndexStyle(1,DRAW_HISTOGRAM);
       SetIndexStyle(2,DRAW_HISTOGRAM);
       IndicatorDigits(Digits+2);
       SetIndexDrawBegin(0,38);
       SetIndexDrawBegin(1,38);
       SetIndexDrawBegin(2,38);
    //---- 4 indicator buffers mapping
       SetIndexBuffer(0,ExtBuffer0);
       SetIndexBuffer(1,ExtBuffer1);
       SetIndexBuffer(2,ExtBuffer2);
       SetIndexBuffer(3,ExtBuffer3);
       SetIndexBuffer(4,ExtBuffer4);
    //---- name for DataWindow and indicator subwindow label
       IndicatorShortName("AC");
       SetIndexLabel(1,NULL);
       SetIndexLabel(2,NULL);
    //---- initialization done
       return(0);
      }
    //+------------------------------------------------------------------+
    //| Accelerator/Decelerator Oscillator                               |
    //+------------------------------------------------------------------+
    int start()
      {
       int    limit;
       int    counted_bars=IndicatorCounted();
       double prev,current;
    //---- last counted bar will be recounted
       if(counted_bars>0) counted_bars--;
       limit=Bars-counted_bars;
    //---- macd counted in the 1-st additional buffer
       for(int i=0; i&lt;limit; i++)
          ExtBuffer3[i]=iMA(NULL,0,5,0,MODE_SMA,PRICE_MEDIAN,i)-
                        iMA(NULL,0,34,0,MODE_SMA,PRICE_MEDIAN,i);
    //---- signal line counted in the 2-nd additional buffer
       for(i=0; i<limit; i++)
          ExtBuffer4[i]=iMAOnArray(ExtBuffer3,Bars,5,0,MODE_SMA,i);
    //---- dispatch values between 2 buffers
       bool up=true;
       for(i=limit-1; i>=0; i--)
         {
          current=ExtBuffer3[i]-ExtBuffer4[i];
          prev=ExtBuffer3[i+1]-ExtBuffer4[i+1];
          if(current>prev) up=true;
          if(current&lt;prev) up=false;
          if(!up)
            {
             ExtBuffer2[i]=current;
             ExtBuffer1[i]=0.0;
            }
          else
            {
             ExtBuffer1[i]=current;
             ExtBuffer2[i]=0.0;
            }
           ExtBuffer0[i]=current;
         }
    //---- done
       return(0);
      }
    //+------------------------------------------------------------------+
  • The "IndicatorBuffers" function specifies the amount of buffers to be used in indicator claculation. Generally, this function is called if more index arrays are used than it is necessary for drawing an indicator. At that, the system manages additional arrays.

  • The "SetIndexDigits" function manages the precision of information output. In this case, when the difference between two moving averages as well as the further difference between the result and the signal line is calculated, the standard precision of within 4 characters after point is obviously insufficient.

  • The "SetIndexDrawBegin" function determines the significant starting element of the indicator array. In our example, the signal line is calculated as simple moving average of another simple moving average. This is why the first 38 values of the indicator are considered as empty ones and are not to be drawn.

  • The "IndicatorShortName" function sets a so-called short name of the indicator to be displayed in the upper left corner of the indicator window and in "DataWindow". If the short name has not been set up, the custom indicator name will be used as the former one. In the given example, there is no need to use the SetIndexLabel function, because only one value is output. So, the name of the indicator is enough for output of a single value.

  • The "SetIndexStyle" function manages drawing parameters of an indicator array. The drawing mode of DRAW_NONE means that the line does not need to be drawn. The matter is that histogram of the indicator presented must be colored in 2 different colors. Data from ExtBuffer0 are allocated in two other arrays, ExtBuffer1 and ExtBuffer2. In order not to output doubling data in tool tips or in data window, the SetIndexLabel function having NULL parameter is used. The drawing mode of DRAW_HISTOGRAM being applied to the indicator of a separate window allows to draw histogram between zero value and the value of a corresponding array (compare with drawing of a histogram in the main window described above).

  • Input parameters used for calculation by custom indicators and functions must be defined as "extern" and may be of any type.

  • If input parameters have not been set the corresponding custom indicator will be called in the simplest format.

    double current_AC = iCustom( NULL, 0, "Accelerator", 0, 0 );

    The transfer of the first two values "NULL" and "0" means that the current chart will be used. The name of the corresponding file (without extension of mq4) is used as custom indicator name. If the last but one parameter is 0, it means that we are interested in the data from the very first indicator array. The last parameter being 0 means that we are interested in the value of the last element (i.e., the most recent, current value) of indicator array requested.

  • Parameters are transferred in the function of custom indicator calculation in the order they have been described. For example, custom indicator named "Ichimoku" and having parameters of (9,26,52) will be called as follows:

    iCustom( NULL, 0, "Ichimoku", 9, 26, 52, 0, shift );

    Strictly speaking, custom indicator parameters do not need to be necessarily transferred to the function. If no one extern variable is defined in the program, it is useless to trasnfer parameters. Or, if necessary, initial values can be used that are used in description of parameters. For example, the same custom indicator without parameters will be called as follows:

    iCustom( NULL, 0, "Ichimoku", 0, shift );

    This means that the values will be used that initialize variables "Tenkan", "Kijun", "Senkou", i.e., 9, 26, and 52. However, if one custom indicator having different sets of parameters is called in one Expert Advisor, default settings are highly not recommended to be used.

It must be noted that the surplus of custom indicators as well as incorrectly written ones can decelerate the work of client terminal significantly!

Warning: All rights for these materials are reserved by MetaQuotes Software Corp. Complete or partial reproduction is prohibited.

Translated from Russian by MetaQuotes Software Corp.
Original article: https://www.mql5.com/ru/articles/1497

Last comments | Go to discussion (2)
DeveloperMQL
DeveloperMQL | 11 Feb 2010 at 08:20
for more detail you can read about custom indicator instructions
molanis
molanis | 22 Feb 2010 at 17:53

For a fast start try a custom indicator builder. It's a graphical environment to create Custom Indicators. No coding is required. No need to know/learn how to program in MQL.

Read more about it here: http://www.molanis.com/products/molanis-technical-indicator-builder/custom-indicator-design

You can download it here: http://www.molanis.com/products/molanis-technical-indicator-builder/forex-technical-indicator-builder-download


Features and Benefits

  • Create Custom Indicators without writing any code.
  • Fast development time. Test your trading ideas in minutes.
  • No programming skills or MQL knowledge are required.
  • Leading Edge Code Generation creates all the code for MetaTrader.
  • Keep your trading and indicator ideas to yourself. No need to share your knowledge with programmers.
  • Gives you access to Molanis Online Community, Molanis Forum and free custom indicators for MT4.
  • Free trial!
Step on New Rails: Custom Indicators in MQL5 Step on New Rails: Custom Indicators in MQL5

I will not list all of the new possibilities and features of the new terminal and language. They are numerous, and some novelties are worth the discussion in a separate article. Also there is no code here, written with object-oriented programming, it is a too serous topic to be simply mentioned in a context as additional advantages for developers. In this article we will consider the indicators, their structure, drawing, types and their programming details, as compared to MQL4. I hope that this article will be useful both for beginners and experienced developers, maybe some of them will find something new.

Here Comes the New MetaTrader 5 and MQL5 Here Comes the New MetaTrader 5 and MQL5

This is just a brief review of MetaTrader 5. I can't describe all the system's new features for such a short time period - the testing started on 2009.09.09. This is a symbolical date, and I am sure it will be a lucky number. A few days have passed since I got the beta version of the MetaTrader 5 terminal and MQL5. I haven't managed to try all its features, but I am already impressed.

Using text files for storing input parameters of Expert Advisors, indicators and scripts Using text files for storing input parameters of Expert Advisors, indicators and scripts

The article describes the application of text files for storing dynamic objects, arrays and other variables used as properties of Expert Advisors, indicators and scripts. The files serve as a convenient addition to the functionality of standard tools offered by MQL languages.

How to create an indicator of non-standard charts for MetaTrader Market How to create an indicator of non-standard charts for MetaTrader Market

Through offline charts, programming in MQL4, and reasonable willingness, you can get a variety of chart types: "Point & Figure", "Renko", "Kagi", "Range bars", equivolume charts, etc. In this article, we will show how this can be achieved without using DLL, and therefore such "two-for-one" indicators can be published and purchased from the Market.