indicator performance

 
I am relatively new to metatrader and have written the attached indicator(EMA_slope-v1.3.mq5).  It seems to be ok when running as an indicator, but the performance seems poor when running against a strategy.  Can someone give me some advice on how to improve the performance of this?  
Files:
 
Your topic has been moved to the section: Technical Indicators
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893
 

Thanks for moving it.

 
pbMoney:
I am relatively new to metatrader and have written the attached indicator(EMA_slope-v1.3.mq5).  It seems to be ok when running as an indicator, but the performance seems poor when running against a strategy.  Can someone give me some advice on how to improve the performance of this?  

I've added the source code here for ease.

//+------------------------------------------------------------------+
//| EMA Slope Histogram Indicator        |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots   6

// Define indicator buffers
double HistoBuffer[];
double HistoColorBuffer[];
double SellEntryBuffer[];
double SellExitBuffer[];
double BuyEntryBuffer[];
double BuyExitBuffer[];

// Input parameters
input int emaPeriod = 20;
input int changePeriod = 5;

// Handle for EMA
int emaHandle;

//+------------------------------------------------------------------+
//| Indicator Initialization                                         |
//+------------------------------------------------------------------+
int OnInit()
{
   // Create EMA handle
   emaHandle = iMA(_Symbol, 0, emaPeriod, 0, MODE_EMA, PRICE_CLOSE);

   // Set indicator buffers
   SetIndexBuffer(0, HistoBuffer);
   SetIndexBuffer(1, HistoColorBuffer);
   SetIndexBuffer(2, SellEntryBuffer);
   SetIndexBuffer(3, SellExitBuffer);
   SetIndexBuffer(4, BuyEntryBuffer);
   SetIndexBuffer(5, BuyExitBuffer);

   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_HISTOGRAM);
   PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 2); // Increase thickness
   PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_NONE); // Hide color buffer

   PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_ARROW); 
   PlotIndexSetInteger(2, PLOT_ARROW, 234);             
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, clrRed);     

   PlotIndexSetInteger(4, PLOT_DRAW_TYPE, DRAW_ARROW);  
   PlotIndexSetInteger(4, PLOT_ARROW, 233);             
   PlotIndexSetInteger(4, PLOT_LINE_COLOR, clrGreen);   

   PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_ARROW);
   PlotIndexSetInteger(3, PLOT_ARROW, 10060);           
   PlotIndexSetInteger(3, PLOT_LINE_COLOR, clrRed);     

   PlotIndexSetInteger(5, PLOT_DRAW_TYPE, DRAW_ARROW);  
   PlotIndexSetInteger(5, PLOT_ARROW, 10060);           
   PlotIndexSetInteger(5, PLOT_LINE_COLOR, clrGreen);   

   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Main Calculation Function                                        |
//+------------------------------------------------------------------+
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[])
{
   if (rates_total < emaPeriod + changePeriod) return 0;

   // Ensure buffer safety
   ArraySetAsSeries(HistoBuffer, false);
   ArraySetAsSeries(HistoColorBuffer, false);
   ArraySetAsSeries(SellEntryBuffer, false);
   ArraySetAsSeries(SellExitBuffer, false);
   ArraySetAsSeries(BuyEntryBuffer, false);
   ArraySetAsSeries(BuyExitBuffer, false);

   double emaValues[];
   if (CopyBuffer(emaHandle, 0, 0, rates_total, emaValues) <= 0) return 0;

   bool insideSellTrade = false;  // Track if histogram should be red

   for (int i = changePeriod; i < rates_total; i++)
   {
      if (i - changePeriod < 0) continue;

      double emaCurrent  = emaValues[i];                // Latest EMA value
      double emaPrevious = emaValues[i - changePeriod]; // EMA value `changePeriod` bars ago

      double histo = (emaCurrent - emaPrevious) / changePeriod;
      HistoBuffer[i] = histo;

      bool histoDownTrend         = (i > 0) && (histo < HistoBuffer[i - 1]);
      bool histoUpTrend           = (i > 0) && (histo > HistoBuffer[i - 1]);
      bool histoDownTrendPrevious = (i > 1) && (HistoBuffer[i - 1] < HistoBuffer[i - 2]);
      bool histoUpTrendPrevious   = (i > 1) && (HistoBuffer[i - 1] > HistoBuffer[i - 2]);

      bool sellEntryTransition = histoUpTrendPrevious && histoDownTrend;
      bool sellExitTransition  = histoDownTrendPrevious && histoUpTrend;
      bool buyEntryTransition  = histoDownTrendPrevious && histoUpTrend;
      bool buyExitTransition   = histoUpTrendPrevious && histoDownTrend;

      double offset = 0.2;

      SellEntryBuffer[i] = (sellEntryTransition) ? ((histo < 0) ? histo - offset : histo + offset) : EMPTY_VALUE;
      if (sellEntryTransition) insideSellTrade = true;  // Activate red histogram

      SellExitBuffer[i]  = (sellExitTransition)  ? ((histo < 0) ? histo - offset : histo + offset) : EMPTY_VALUE;
      if (sellExitTransition) insideSellTrade = false; // Deactivate red histogram

      BuyEntryBuffer[i]  = (buyEntryTransition)  ? ((histo < 0) ? histo - offset : histo + offset) : EMPTY_VALUE;

      BuyExitBuffer[i]   = (buyExitTransition)   ? ((histo < 0) ? histo - offset : histo + offset) : EMPTY_VALUE;

      HistoColorBuffer[i] = insideSellTrade ? clrRed : clrBlue;
   }

   return rates_total;
}
 
pbMoney #:

I've added the source code here for ease.

IMHO, EMA code should not be so intricate. I recommend using a standard MA or EMA indicator, and coding the EA to evaluate the values of its bar positions in the EA's trading conditions. This will eliminate the need for entry and exit "signals," and the EA will simply send orders instead. This is how I do it, and there are no efficiency issues.

 

1. Don't copy rates_total into copybuffer

2. Don't start the loop at a value which is far away from rates_total (when you can instead use prev_calculated)

Learn from this example:

Code Base

Portable Moving Average

Conor Mcnamara, 2025.02.03 14:35

Calculate a moving average in one function call. Code that can easily be transported between different projects.