HELP! Custom Bullish/Bearish Pattern Indicator not working

 

Hi guys! I'm trying to code a simple indicator that identifies a pattern of 4 bullish/bearish candles in a particular order and whenever it finds one of the 3 patterns, it should set a buffer for buying/Selling at the Close price of the last candle, drawing arrows. But I can't make it work and I don't know why.

Can anyone help me with that, please?

Here's the code:

//+------------------------------------------------------------------+
//|                                                  |
//|                                                   Bruno Chimenti |
//|                                             --- > V3.0           |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Bruno Chimenti"
#property link      "https://www.mql5.com"
#property version   "3.00"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   2
//--- plot Compra
#property indicator_label1  "Compra"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrMediumBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Venda
#property indicator_label2  "Venda"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrFuchsia
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

//--- indicator buffers
double   BuyBuffer[];
double   SellBuffer[];

bool     tipo1Compra;
bool     tipo1Venda;
bool     tipo2Compra;
bool     tipo2Venda;
bool     tipo3Compra;
bool     tipo3Venda;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,BuyBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SellBuffer,INDICATOR_DATA);
 
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
   PlotIndexSetInteger(0,PLOT_ARROW,236);
   PlotIndexSetInteger(1,PLOT_ARROW,237);
   
   ArraySetAsSeries(BuyBuffer, true);
   ArraySetAsSeries(SellBuffer, true);
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration 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[])
    {
// ---- Main Loop
     
   for(int i=1; i<rates_total; i++)
 {
      tipo1Compra = (open[i-4]<close[i-4] && open[i-3]>close[i-3] && open[i-2]<close[i-2] && open[i-1]>close[i-1]);
      tipo1Venda  = (open[i-4]>close[i-4] && open[i-3]<close[i-3] && open[i-2]>close[i-2] && open[i-1]<close[i-1]);

      tipo2Compra = (open[i-4]>close[i-4] && open[i-3]<close[i-3] && open[i-2]<close[i-2] && open[i-1]>close[i-1]);
      tipo2Venda  = (open[i-4]<close[i-4] && open[i-3]>close[i-3] && open[i-2]>close[i-2] && open[i-1]<close[i-1]);

      tipo3Compra = (open[i-4]>close[i-4] && open[i-3]<close[i-3] && open[i-2]>close[i-2] && open[i-1]>close[i-1]);
      tipo3Venda  = (open[i-4]<close[i-4] && open[i-3]>close[i-3] && open[i-2]<close[i-2] && open[i-1]<close[i-1]);

      if ( tipo1Compra || tipo2Compra || tipo3Compra) 
      { 
      BuyBuffer[i] =  close[i-1]; 
      }
   
      if ( tipo1Venda || tipo2Venda || tipo3Venda) 
      { 
      SellBuffer[i] = close[i-1]; 
      }
}

   return(rates_total);
 }
//+------------------------------------------------------------------+
 
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 and sorry about that.
Since it's more of a price action indicator, I thought the term "technical" didn't fit here. My mistake.

Anyways...I'm not sure what's the problem with my code, it looks like it's pretty straightforward.
Maybe something wrong with the main  loop?

Still waiting for help :)

 
Bruno Chimenti #: Anyways...I'm not sure what's the problem with my code, it looks like it's pretty straightforward. Maybe something wrong with the main  loop? Still waiting for help :)
  1. You have not explained what you consider as "not working".
  2. You have set the Buy and Sell buffers as a "series", but you have not done the same for the OHLC buffers.
    Since this MQL5 and the default is "non-series", don't set the buffers as "series".
  3. You are starting the loop at "i = 1", but you are referencing the index "i - 4" which would be an invalid index of "-3".
  4. Also you are assigning values to the Buy and Sell buffers when one of the conditions are met, but don't assign any value when the conditions are NOT met.
    In other words, you should be assigning the value EMPTY_VALUE in those cases.
BuyBuffer[ i] = tipo1Compra || tipo2Compra || tipo3Compra ? close[i-1] : EMPTY_VALUE; 
SellBuffer[i] = tipo1Venda  || tipo2Venda  || tipo3Venda  ? close[i-1] : EMPTY_VALUE;
    These are just a few things I see at a quick glance. There may be more problems.
     
      for(int i=1; i<rates_total; i++)
     {
          tipo1Compra = (open[i-4]<close[i-4
    1. When i equals one, you try to access element minus three. Indicator crashes.
                How to do your lookbacks correctly #9#14 & #19 (2016)

    2. You haven't specified whether you are accessing your arrays as-series or non-series. Your buffers are set as-series.

      To define the indexing direction in the time[], open[], high[], low[], close[], tick_volume[], volume[] and spread[] arrays, call the ArrayGetAsSeries() function. In order not to depend on defaults, call the ArraySetAsSeries() function for the arrays to work with.
                Event Handling / OnCalculate - Reference on algorithmic/automated trading language for MetaTrader 5
     

    William Roeder #:

    1. When i equals one, you try to access element minus three. Indicator crashes.
                How to do your lookbacks correctly #9#14 & #19 (2016)

    2. You haven't specified whether you are accessing your arrays as-series or non-series. Your buffers are set as-series.

    Many thanks for both of your responses!

    I've  commented out the "buffer set as series" function and changed the main loop to prevent from crashing when there's not enough bars in the chart. And now it is working (it displays the Buy and Sell buffers at the right places on the chart).

    But i suspect that what i did was not the best solution though. This is how I wrote the loop:

      if(rates_total<5)
        {
         return(0);
        }
     
    for(int i=5; i<rates_total; i++)

    Again,it does work but i think it's far from optimal..

    Could you please help me with this loop to make it more efficient?

    thanks in advance

     
    Bruno Chimenti #: But i suspect that what i did was not the best solution though. This is how I wrote the loop: Again,it does work but i think it's far from optimal.. Could you please help me with this loop to make it more efficient?

    Make use of the parameter variable "prev_calculated" so that you don't recalculate everything on each call.

    Search for examples in the CodeBase with similar functionality to what you want to create, and study them.
      MQL5 Code Base
      MQL5 Code Base
      • www.mql5.com
      MQL5 Source Code Library for MetaTrader 5
       

      I see some potential issues in your code that might be causing it not to work as expected. Here are a few suggestions:

      1. Array Indexing: Ensure that your array indexing is within bounds to avoid accessing elements outside the array.

      2. Initialization: Initialize your boolean variables ( tipo1Compra , tipo1Venda , etc.) at the beginning of the OnCalculate function. This helps in preventing unexpected behavior.

      3. Plotting Arrows: Make sure that the conditions for plotting arrows are met. You are currently plotting arrows at every bar, but you might want to plot them only when a buy or sell condition occurs.

      4. Buffer Assignments: The assignment of values to BuyBuffer and SellBuffer should be conditional on whether a buy or sell condition is met. Ensure that you are assigning values only when the conditions are true.

      Here's an updated version of your OnCalculate function with these considerations:

      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[])
      {
          // Initialize boolean variables
          bool tipo1Compra, tipo1Venda, tipo2Compra, tipo2Venda, tipo3Compra, tipo3Venda;
      
          for (int i = 1; i < rates_total; i++)
          {
              // Your existing conditions for pattern detection
      
              if (tipo1Compra || tipo2Compra || tipo3Compra)
              {
                  BuyBuffer[i] = close[i - 1];
                  SellBuffer[i] = 0; // Reset SellBuffer to avoid conflicting signals
              }
      
              if (tipo1Venda || tipo2Venda || tipo3Venda)
              {
                  SellBuffer[i] = close[i - 1];
                  BuyBuffer[i] = 0; // Reset BuyBuffer to avoid conflicting signals
              }
          }
      
          return (rates_total);
      }
      

      This modification resets the opposite buffer whenever a buy or sell condition is met to avoid conflicting signals. Adjust this according to your strategy logic. Also, make sure to test this thoroughly in a safe environment before using it with real funds.

       

      Awesome! Thanks a lot for all the help 

      For anyone that might use this topic for educational purposes:
      Since I fixed the buffer array ordering and the main loop to avoid crashing when it returned [-3]  It's now totally functional.

      Now I'm just tweaking the main loop to make it more efficient computation-wise.

      Reason: