Confluence Index Stoch+RSI+MACD

Indicators MetaTrader 5 Free

Multi-timeframe confluence oscillator combining Stochastic, RSI and MACD across 3 timeframes. Used to identify trend entries when all indicators align (score >50 bullish, <-50 bearish). Best used as a confirmation for trend-continuation setups, support/resistance reactions, and exhaustion conditions

Instead of normalizing the values, we are simply assigning a score. I can’t fully explain why, but in my personal use it is surprisingly effective, especially for detecting divergences. 

//+------------------------------------------------------------------+

//|                                        MultiConfluence_Index.mq5 |

//|                           Confluence Index Stoch+RSI+MACD    |

//+------------------------------------------------------------------+

#property copyright "Multi-Confluence Index"

#property version   "1.00"

#property indicator_separate_window

#property indicator_buffers 6

#property indicator_plots   4



// Ligne principale de l'indice

#property indicator_label1  "Confluence Index"

#property indicator_type1   DRAW_LINE

#property indicator_color1  clrDodgerBlue

#property indicator_width1  3



// Ligne zéro

#property indicator_label2  "Zero Line"

#property indicator_type2   DRAW_LINE

#property indicator_color2  clrGray

#property indicator_width2  1

#property indicator_style2  STYLE_DOT



// Zone bullish extrême

#property indicator_label3  "Zone Bullish"

#property indicator_type3   DRAW_FILLING

#property indicator_color3  clrDarkGreen



// Zone bearish extrême

#property indicator_label4  "Zone Bearish"

#property indicator_type4   DRAW_FILLING

#property indicator_color4  clrDarkRed



//+------------------------------------------------------------------+

//| Input parameters                                               |

//+------------------------------------------------------------------+

input group "=== TIMEFRAMES ==="

input ENUM_TIMEFRAMES TF1 = PERIOD_CURRENT;   // Timeframe 1 (Fast)

input ENUM_TIMEFRAMES TF2 = PERIOD_H1;        // Timeframe 2 (Medium)

input ENUM_TIMEFRAMES TF3 = PERIOD_H4;        // Timeframe 3 (Slow)



input group "=== PARAMETRES ==="

input int      Stoch_K        = 14;      // Stochastic K

input int      Stoch_D        = 3;       // Stochastic D

input int      Stoch_Slowing  = 3;       // Stochastic Slowing

input int      RSI_Period     = 14;      // RSI Period

input int      MACD_Fast      = 12;      // MACD EMA Fast

input int      MACD_Slow      = 26;      // MACD EMA Slow

input int      MACD_Signal    = 9;       // MACD Signal



//+------------------------------------------------------------------+

//| Buffers                                                            |

//+------------------------------------------------------------------+

double IndexBuffer[];

double ZeroBuffer[];

double BullishZoneTop[];

double BullishZoneBottom[];

double BearishZoneTop[];

double BearishZoneBottom[];



// Handles for indicators

int handle_stoch_tf1, handle_stoch_tf2, handle_stoch_tf3;

int handle_rsi_tf1, handle_rsi_tf2, handle_rsi_tf3;

int handle_macd_tf1, handle_macd_tf2, handle_macd_tf3;



//+------------------------------------------------------------------+

//| Initialization                                                     |

//+------------------------------------------------------------------+

int OnInit()

{

   // Buffers

   SetIndexBuffer(0, IndexBuffer, INDICATOR_DATA);

   SetIndexBuffer(1, ZeroBuffer, INDICATOR_DATA);

   SetIndexBuffer(2, BullishZoneTop, INDICATOR_DATA);

   SetIndexBuffer(3, BullishZoneBottom, INDICATOR_DATA);

   SetIndexBuffer(4, BearishZoneTop, INDICATOR_DATA);

   SetIndexBuffer(5, BearishZoneBottom, INDICATOR_DATA);

   

   // Configuration

   ArraySetAsSeries(IndexBuffer, true);

   ArraySetAsSeries(ZeroBuffer, true);

   ArraySetAsSeries(BullishZoneTop, true);

   ArraySetAsSeries(BullishZoneBottom, true);

   ArraySetAsSeries(BearishZoneTop, true);

   ArraySetAsSeries(BearishZoneBottom, true);

   

   // Ligne zéro

   ArrayInitialize(ZeroBuffer, 0.0);

   

   // Configuration of fill zones

   PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, 0);

   PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, 0);

   

   // Creation of handles - STOCHASTIC

   handle_stoch_tf1 = iStochastic(_Symbol, TF1, Stoch_K, Stoch_D, Stoch_Slowing, MODE_SMA, STO_LOWHIGH);

   handle_stoch_tf2 = iStochastic(_Symbol, TF2, Stoch_K, Stoch_D, Stoch_Slowing, MODE_SMA, STO_LOWHIGH);

   handle_stoch_tf3 = iStochastic(_Symbol, TF3, Stoch_K, Stoch_D, Stoch_Slowing, MODE_SMA, STO_LOWHIGH);

   

   // Creation of handles - RSI

   handle_rsi_tf1 = iRSI(_Symbol, TF1, RSI_Period, PRICE_CLOSE);

   handle_rsi_tf2 = iRSI(_Symbol, TF2, RSI_Period, PRICE_CLOSE);

   handle_rsi_tf3 = iRSI(_Symbol, TF3, RSI_Period, PRICE_CLOSE);

   

   // Creation of handles - MACD

   handle_macd_tf1 = iMACD(_Symbol, TF1, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE);

   handle_macd_tf2 = iMACD(_Symbol, TF2, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE);

   handle_macd_tf3 = iMACD(_Symbol, TF3, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE);

   

   // Verification of handles

   if(handle_stoch_tf1 == INVALID_HANDLE || handle_stoch_tf2 == INVALID_HANDLE || handle_stoch_tf3 == INVALID_HANDLE ||

      handle_rsi_tf1 == INVALID_HANDLE || handle_rsi_tf2 == INVALID_HANDLE || handle_rsi_tf3 == INVALID_HANDLE ||

      handle_macd_tf1 == INVALID_HANDLE || handle_macd_tf2 == INVALID_HANDLE || handle_macd_tf3 == INVALID_HANDLE)

   {

      Print("ERROR: Impossible to create handles");

      return(INIT_FAILED);

   }

   

   // Name and scale

   IndicatorSetString(INDICATOR_SHORTNAME, "Multi-Confluence Index");

   IndicatorSetInteger(INDICATOR_DIGITS, 1);

   IndicatorSetDouble(INDICATOR_MINIMUM, -100);

   IndicatorSetDouble(INDICATOR_MAXIMUM, 100);

   

   // Levels

   IndicatorSetInteger(INDICATOR_LEVELS, 3);

   IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, 0);

   IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, 50);

   IndicatorSetDouble(INDICATOR_LEVELVALUE, 2, -50);

   

   IndicatorSetInteger(INDICATOR_LEVELCOLOR, 0, clrGray);

   IndicatorSetInteger(INDICATOR_LEVELCOLOR, 1, clrGreen);

   IndicatorSetInteger(INDICATOR_LEVELCOLOR, 2, clrRed);

   

   IndicatorSetInteger(INDICATOR_LEVELSTYLE, 0, STYLE_SOLID);

   IndicatorSetInteger(INDICATOR_LEVELSTYLE, 1, STYLE_DOT);

   IndicatorSetInteger(INDICATOR_LEVELSTYLE, 2, STYLE_DOT);

   

   Print("Multi-Confluence Index initialized - TF:", EnumToString(TF1), "/", EnumToString(TF2), "/", EnumToString(TF3));

   return(INIT_SUCCEEDED);

}



//+------------------------------------------------------------------+

//| Deinitialization                                                  |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

   if(handle_stoch_tf1 != INVALID_HANDLE) IndicatorRelease(handle_stoch_tf1);

   if(handle_stoch_tf2 != INVALID_HANDLE) IndicatorRelease(handle_stoch_tf2);

   if(handle_stoch_tf3 != INVALID_HANDLE) IndicatorRelease(handle_stoch_tf3);

   if(handle_rsi_tf1 != INVALID_HANDLE) IndicatorRelease(handle_rsi_tf1);

   if(handle_rsi_tf2 != INVALID_HANDLE) IndicatorRelease(handle_rsi_tf2);

   if(handle_rsi_tf3 != INVALID_HANDLE) IndicatorRelease(handle_rsi_tf3);

   if(handle_macd_tf1 != INVALID_HANDLE) IndicatorRelease(handle_macd_tf1);

   if(handle_macd_tf2 != INVALID_HANDLE) IndicatorRelease(handle_macd_tf2);

   if(handle_macd_tf3 != INVALID_HANDLE) IndicatorRelease(handle_macd_tf3);

   

   Comment("");

}



//+------------------------------------------------------------------+

//| Main 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[])

{

   if(rates_total < 100)

      return(0);

   

   int limit = rates_total - prev_calculated;

   if(limit == 0) limit = 1;

   if(prev_calculated == 0) limit = rates_total - 100;

   

   // Arrays for data (as series to match buffer indexing)

   double stoch_k1[], stoch_d1[], stoch_k2[], stoch_d2[], stoch_k3[], stoch_d3[];

   double rsi1[], rsi2[], rsi3[];

   double macd_main1[], macd_sig1[], macd_main2[], macd_sig2[], macd_main3[], macd_sig3[];

   

   ArraySetAsSeries(stoch_k1, true);

   ArraySetAsSeries(stoch_d1, true);

   ArraySetAsSeries(stoch_k2, true);

   ArraySetAsSeries(stoch_d2, true);

   ArraySetAsSeries(stoch_k3, true);

   ArraySetAsSeries(stoch_d3, true);

   ArraySetAsSeries(rsi1, true);

   ArraySetAsSeries(rsi2, true);

   ArraySetAsSeries(rsi3, true);

   ArraySetAsSeries(macd_main1, true);

   ArraySetAsSeries(macd_sig1, true);

   ArraySetAsSeries(macd_main2, true);

   ArraySetAsSeries(macd_sig2, true);

   ArraySetAsSeries(macd_main3, true);

   ArraySetAsSeries(macd_sig3, true);

   

   // Copy of data - copy enough bars

   int bars_to_copy = limit + 50;

   

   int copied = 0;

   copied = CopyBuffer(handle_stoch_tf1, 0, 0, bars_to_copy, stoch_k1);

   if(copied <= 0) { Print("ERROR: Failed to copy stoch_k1, code:", GetLastError()); return(prev_calculated); }

   

   if(CopyBuffer(handle_stoch_tf1, 1, 0, bars_to_copy, stoch_d1) <= 0) { Print("ERROR: Failed to copy stoch_d1"); return(prev_calculated); }

   if(CopyBuffer(handle_stoch_tf2, 0, 0, bars_to_copy, stoch_k2) <= 0) { Print("ERROR: Failed to copy stoch_k2"); return(prev_calculated); }

   if(CopyBuffer(handle_stoch_tf2, 1, 0, bars_to_copy, stoch_d2) <= 0) { Print("ERROR: Failed to copy stoch_d2"); return(prev_calculated); }

   if(CopyBuffer(handle_stoch_tf3, 0, 0, bars_to_copy, stoch_k3) <= 0) { Print("ERROR: Failed to copy stoch_k3"); return(prev_calculated); }

   if(CopyBuffer(handle_stoch_tf3, 1, 0, bars_to_copy, stoch_d3) <= 0) { Print("ERROR: Failed to copy stoch_d3"); return(prev_calculated); }

   

   if(CopyBuffer(handle_rsi_tf1, 0, 0, bars_to_copy, rsi1) <= 0) { Print("ERROR: Failed to copy rsi1"); return(prev_calculated); }

   if(CopyBuffer(handle_rsi_tf2, 0, 0, bars_to_copy, rsi2) <= 0) { Print("ERROR: Failed to copy rsi2"); return(prev_calculated); }

   if(CopyBuffer(handle_rsi_tf3, 0, 0, bars_to_copy, rsi3) <= 0) { Print("ERROR: Failed to copy rsi3"); return(prev_calculated); }

   

   if(CopyBuffer(handle_macd_tf1, 0, 0, bars_to_copy, macd_main1) <= 0) { Print("ERROR: Failed to copy macd_main1"); return(prev_calculated); }

   if(CopyBuffer(handle_macd_tf1, 1, 0, bars_to_copy, macd_sig1) <= 0) { Print("ERROR: Failed to copy macd_sig1"); return(prev_calculated); }

   if(CopyBuffer(handle_macd_tf2, 0, 0, bars_to_copy, macd_main2) <= 0) { Print("ERROR: Failed to copy macd_main2"); return(prev_calculated); }

   if(CopyBuffer(handle_macd_tf2, 1, 0, bars_to_copy, macd_sig2) <= 0) { Print("ERROR: Failed to copy macd_sig2"); return(prev_calculated); }

   if(CopyBuffer(handle_macd_tf3, 0, 0, bars_to_copy, macd_main3) <= 0) { Print("ERROR: Failed to copy macd_main3"); return(prev_calculated); }

   if(CopyBuffer(handle_macd_tf3, 1, 0, bars_to_copy, macd_sig3) <= 0) { Print("ERROR: Failed to copy macd_sig3"); return(prev_calculated); }

   

   Print("DEBUG: Copied ", copied, " bars, limit=", limit, " rates_total=", rates_total);

   

   // Calcul of the index - now i=0 is most recent bar

   int calculated = 0;

   for(int i = 0; i < limit; i++)

   {

      // Security check for array access

      if(i >= ArraySize(stoch_k1) || i >= ArraySize(stoch_k2) || i >= ArraySize(stoch_k3))

      {

         Print("DEBUG: Skipping i=", i, " - stoch arrays too small");

         continue;

      }

      if(i >= ArraySize(rsi1) || i >= ArraySize(rsi2) || i >= ArraySize(rsi3))

      {

         Print("DEBUG: Skipping i=", i, " - rsi arrays too small");

         continue;

      }

      if(i >= ArraySize(macd_main1) || i >= ArraySize(macd_main2) || i >= ArraySize(macd_main3))

      {

         Print("DEBUG: Skipping i=", i, " - macd arrays too small");

         continue;

      }

      

      double score = 0.0;

      

      //=== STOCHASTIQUE ===

      // TF1

      if(stoch_k1[i] > stoch_d1[i])

         score += 11.0;

      else

         score -= 11.0;

      

      // TF2

      if(stoch_k2[i] > stoch_d2[i])

         score += 17.0;

      else

         score -= 17.0;

      

      // TF3

      if(stoch_k3[i] > stoch_d3[i])

         score += 17.0;

      else

         score -= 17.0;

      

      //=== RSI ===

      // TF1

      if(rsi1[i] > 50)

         score += 7.0;

      else

         score -= 7.0;

      

      // TF2

      if(rsi2[i] > 50)

         score += 11.0;

      else

         score -= 11.0;

      

      // TF3

      if(rsi3[i] > 50)

         score += 11.0;

      else

         score -= 11.0;

      

      //=== MACD ===

      // TF1

      if(macd_main1[i] > macd_sig1[i])

         score += 6.0;

      else

         score -= 6.0;

      

      // TF2

      if(macd_main2[i] > macd_sig2[i])

         score += 10.0;

      else

         score -= 10.0;

      

      // TF3

      if(macd_main3[i] > macd_sig3[i])

         score += 10.0;

      else

         score -= 10.0;

      

      // Stockage - i=0 is current bar

      IndexBuffer[i] = score;

      calculated++;

      

      if(i < 3)  // Debug pour les 3 premières barres

      {

         Print("DEBUG: Bar[", i, "] score=", score, " stoch1=", stoch_k1[i], " rsi1=", rsi1[i], " macd1=", macd_main1[i]);

      }

      

      // Colored zones

      if(score > 50)

      {

         BullishZoneTop[i] = 100;

         BullishZoneBottom[i] = 50;

      }

      else

      {

         BullishZoneTop[i] = EMPTY_VALUE;

         BullishZoneBottom[i] = EMPTY_VALUE;

      }

      

      if(score < -50)

      {

         BearishZoneTop[i] = -50;

         BearishZoneBottom[i] = -100;

      }

      else

      {

         BearishZoneTop[i] = EMPTY_VALUE;

         BearishZoneBottom[i] = EMPTY_VALUE;

      }

   }

   

   Print("DEBUG: Calculated ", calculated, " bars out of ", limit);

   

   // Debug info at first calculation

   if(prev_calculated == 0)

   {

      string info = StringFormat("Calculation completed | Current index: %.1f", IndexBuffer[0]);

      Print(info);

      Comment(info);

   }

   

   return(rates_total);

}

//+------------------------------------------------------------------+