﻿//+------------------------------------------------------------------+
//|                                                    BB_HL_Cpp.mq5 |
//|                                      Copyright 2026, Your Name   |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright   "Copyright 2026"
#property link        ""
#property version     "1.00"
#property indicator_chart_window

// Définition des 3 buffers graphiques demandés par le script (Upper, Lower, MA)
#property indicator_buffers 3
#property indicator_plots   3

// Propriétés visuelles des tracés
#property indicator_label1  "Upper Band"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrPurple
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "Lower Band"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrPurple
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

#property indicator_label3  "MA Buffer"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrPurple
#property indicator_style3  STYLE_DOT
#property indicator_width3  1

//--- Paramètres d'entrée (Inputs automatiques)
input int      InpPeriod   = 200;  // Période (Period)
input int      InpBarsBack = 500;  // Nombre de bougies en arrière à calculer
input double   InpNDev     = 2.0;  // Multiplicateur d'écart-type (nDev)

//--- Buffers globaux de l'indicateur
double upperbandbuffer[];
double lowerbandbuffer[];
double mabuffer[];

//--- Buffers internes de calcul (non tracés sur le graphique)
double extmapbuffer2[];
double devsbuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   // Liaison des buffers graphiques
   SetIndexBuffer(0, upperbandbuffer, INDICATOR_DATA);
   SetIndexBuffer(1, lowerbandbuffer, INDICATOR_DATA);
   SetIndexBuffer(2, mabuffer,        INDICATOR_DATA);

   // Indiquer à MQL5 de ne pas tracer les premières valeurs vides
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpPeriod);
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, InpPeriod);
   PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, InpPeriod);

   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[])
{
   // Vérification du nombre de barres disponibles requis pour la période
   if(rates_total < InpPeriod + 1)
      return(0);

   // Synchronisation de la taille des buffers internes calculés manuellement
   if(ArrayResize(extmapbuffer2, rates_total) < 0 || ArrayResize(devsbuffer, rates_total) < 0)
      return(0);

   // Détermination de la limite stricte selon le paramètre InpBarsBack
   int limit = rates_total - prev_calculated;
   if(limit > InpBarsBack)
      limit = InpBarsBack;
      
   if(prev_calculated > 0)
      limit++; // Recalcul dynamique de la bougie en cours

   int start_index = rates_total - limit;
   if(start_index < InpPeriod) 
      start_index = InpPeriod; // Sécurité de décalage initial

   // ====================================================================
   // ÉTAPE 1 : Calcul de la Moyenne Mobile Glissante Rapide (Style FSMA)
   // ====================================================================
   // On effectue le calcul sur l'ensemble de la zone requise
   double sum = 0;
   
   // Initialisation de la première somme glissante
   int first_calc_pos = start_index - InpPeriod + 1;
   if(first_calc_pos < 0) first_calc_pos = 0;

   for(int k = 0; k < InpPeriod; k++)
   {
      sum += (high[first_calc_pos + k] + low[first_calc_pos + k]) / 2.0;
   }
   extmapbuffer2[first_calc_pos + InpPeriod - 1] = sum / InpPeriod;

   // Application de la fenêtre glissante rapide (Équivalent du While p>=0)
   for(int i = first_calc_pos + InpPeriod; i < rates_total; i++)
   {
      sum = sum + ((high[i] + low[i]) / 2.0) - ((high[i - InpPeriod] + low[i - InpPeriod]) / 2.0);
      extmapbuffer2[i] = sum / InpPeriod;
   }

   // ====================================================================
   // ÉTAPE 2 : Remplissage des écarts (DevsBuffer)
   // ====================================================================
   for(int i = start_index; i < rates_total; i++)
   {
      double ma = extmapbuffer2[i];
      double d1 = high[i] - ma;
      d1 = d1 * d1;
      double d2 = low[i] - ma;
      d2 = d2 * d2;

      mabuffer[i] = ma;    
      devsbuffer[i] = (d1 > d2) ? d1 : d2; // d1>=d2 prend d1, sinon prend d2
   }

   // ====================================================================
   // ÉTAPE 3 : Calcul de l'écart-type final et des Bandes
   // ====================================================================
   for(int i = start_index; i < rates_total; i++)
   {
      // Protection pour le calcul arrière de l'écart-type glissant
      if(i < InpPeriod - 1) continue;

      double d1_sum = 0;
      // Somme glissante des déviations maximales stockées sur la période
      for(int j = 0; j < InpPeriod; j++)
      {
         d1_sum += devsbuffer[i - j];
      }
      
      double d1_avg = d1_sum / InpPeriod;
      double d2 = InpNDev * MathSqrt(d1_avg);
      double ma = mabuffer[i];

      upperbandbuffer[i] = ma + d2;
      lowerbandbuffer[i] = ma - d2;
   }

   return(rates_total);
}
//+------------------------------------------------------------------+