Standard Library Experts and Indicators

 

Hello.

I have searched everywhere but except some samples I found on Metatrader I couldn't find any tutorials or something about implementing Indicators & Experts based on Standard Library.

To be exact, there is a way to create an indicator that inherits from the CIndicator class. Also, there is a way to create an expert that inherits from the CExpert class and can have trailing stop-loss via a class that inherits from CExpertTrailing and is being initialized by the InitTrailing method.

Apart from the samples, there is no tutorial I searched that explains the whole concept of how these work. 

For example, I want to create a Donchian channel indicator that I want to use it for trailing the stop-loss of a position. How would I implement it?

Should I first create the indicator like below:

//+------------------------------------------------------------------+
//| Donchian Channel Indicator                                      |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_color3 Green

// Input Parameters
input int Period = 20;  // Donchian period

// Buffers
double UpperBuffer[];
double LowerBuffer[];
double MiddleBuffer[];

//+------------------------------------------------------------------+
//| Initialization Function                                         |
//+------------------------------------------------------------------+
int OnInit()
{
    // Set buffers
    SetIndexBuffer(0, UpperBuffer);
    SetIndexBuffer(1, LowerBuffer);
    SetIndexBuffer(2, MiddleBuffer);
    
    IndicatorShortName("Donchian Channel (" + IntegerToString(Period) + ")");
    
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Indicator Calculation                                           |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &time[])
{
    // Validate enough bars for calculation
    if (rates_total < Period) return 0;

    int start = prev_calculated > 0 ? prev_calculated - 1 : Period;

    for (int i = start; i < rates_total; i++)
    {
        double highestHigh = high[i];
        double lowestLow = low[i];

        for (int j = 1; j < Period; j++)
        {
            if (i - j < 0) break;  // Ensure index doesn't go negative
            if (high[i - j] > highestHigh) highestHigh = high[i - j];
            if (low[i - j] < lowestLow) lowestLow = low[i - j];
        }

        UpperBuffer[i] = highestHigh;
        LowerBuffer[i] = lowestLow;
        MiddleBuffer[i] = (highestHigh + lowestLow) / 2;
    }

    return rates_total;
}

Then create a CDonchianChannel class and load the indicator there with iCustom (if I remember well) and do the rest of the trickery so that I can use it as a class or something? In that case, the above indicator code is not written with OOP in mind. Also, from the little things I understood looking at the documentation, it would be suggested to bypass the loading of the indicator with iCustom as it might be adding overhead... Information are currently quite mixed on my head and I am having struggles.

Am I missing something? Where can I find a good tutorial creating a custom indicator (not reusing a Metatrader one) that makes also use of the Standard Library way of doing it?


Thanks

 
ekalyvio:

Hello.

I have searched everywhere but except some samples I found on Metatrader I couldn't find any tutorials or something about implementing Indicators & Experts based on Standard Library.

To be exact, there is a way to create an indicator that inherits from the CIndicator class. Also, there is a way to create an expert that inherits from the CExpert class and can have trailing stop-loss via a class that inherits from CExpertTrailing and is being initialized by the InitTrailing method.

Apart from the samples, there is no tutorial I searched that explains the whole concept of how these work. 

For example, I want to create a Donchian channel indicator that I want to use it for trailing the stop-loss of a position. How would I implement it?

Should I first create the indicator like below:

Then create a CDonchianChannel class and load the indicator there with iCustom (if I remember well) and do the rest of the trickery so that I can use it as a class or something? In that case, the above indicator code is not written with OOP in mind. Also, from the little things I understood looking at the documentation, it would be suggested to bypass the loading of the indicator with iCustom as it might be adding overhead... Information are currently quite mixed on my head and I am having struggles.

Am I missing something? Where can I find a good tutorial creating a custom indicator (not reusing a Metatrader one) that makes also use of the Standard Library way of doing it?


Thanks

Hello

You then create a handle in your Expert Advisor.

You initialize the handle with the parameters of the indicator once for the symbol and you call it whenever you need it.

//handle for the indicator 
  int dcHandle=INVALID_HANDLE;
int OnInit()
  {
  dcHandle=INVALID_HANDLE;
  return(INIT_SUCCEEDED);
  }
void OnTick()
  {
  //if the indicator is loaded
    if(dcHandle!=INVALID_HANDLE){
    //get recent bar value
      double upper[];
      if(CopyBuffer(dcHandle,0,0,1,upper)==1){
        Comment("DC (upper) ("+DoubleToString(upper[0],_Digits)+")");
        }
    }
  //if the indicator is not loaded
    else{
    dcHandle=iCustom(_Symbol,_Period,"forumDonchianChannel.ex5",20);
    Comment("Loading indicator");
    }
  }
void OnDeinit(const int reason)
  {
  if(dcHandle!=INVALID_HANDLE){
    IndicatorRelease(dcHandle);
    }
  }

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 3


// Input Parameters
input int Period = 20;  // Donchian period

// Buffers
double UpperBuffer[];
double LowerBuffer[];
double MiddleBuffer[];

//+------------------------------------------------------------------+
//| Initialization Function                                         |
//+------------------------------------------------------------------+
int OnInit()
{
    // Set buffers
    SetIndexBuffer(0, UpperBuffer);
      PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);
      PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrDodgerBlue);
    SetIndexBuffer(1, LowerBuffer);
      PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE);
      PlotIndexSetInteger(1,PLOT_LINE_COLOR,clrCrimson);    
    SetIndexBuffer(2, MiddleBuffer);
      PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_LINE);
      PlotIndexSetInteger(2,PLOT_LINE_COLOR,clrCornsilk);    
    IndicatorSetString(INDICATOR_SHORTNAME,"Donchian Channel (" + IntegerToString(Period) + ")");
    
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Indicator Calculation                                           |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
  {
    // Validate enough bars for calculation
    if (rates_total < Period) return 0;

    int start = prev_calculated > 0 ? prev_calculated - 1 : Period;

    for (int i = start; i < rates_total; i++)
    {
        double highestHigh = high[i];
        double lowestLow = low[i];

        for (int j = 1; j < Period; j++)
        {
            if (i - j < 0) break;  // Ensure index doesn't go negative
            if (high[i - j] > highestHigh) highestHigh = high[i - j];
            if (low[i - j] < lowestLow) lowestLow = low[i - j];
        }

        UpperBuffer[i] = highestHigh;
        LowerBuffer[i] = lowestLow;
        MiddleBuffer[i] = (highestHigh + lowestLow) / 2;
    }

    return rates_total;
}