//+------------------------------------------------------------------+
//|                                      BB_WPR_ATR_Offset.mq5       |
//|                          WPR centered + ATR applied on BB bands  |
//+------------------------------------------------------------------+
#property copyright "IonOne 2026"
#property link "http://forex-station.com"
#property version "1.0"

#property indicator_chart_window
#property indicator_buffers 8
#property indicator_plots   5

//--- plot settings
#property indicator_label1  "BB Upper"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "BB Middle"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrOrange
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

#property indicator_label3  "BB Lower"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrDodgerBlue
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1

#property indicator_label4  "BB Uppper WPR"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrOrange
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1

#property indicator_label5  "BB Lower WPR"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrOrange
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1

//--- inputs
input group "---- Main Periods ----" 
input int                InpBBPeriod     = 20;          // Bollinger MA Period
input int                InpStdDevPeriod = 20;          // Standard Deviation Period
input int                InpWPRPeriod    = 14;          // WPR Period
input int                InpATRPeriod    = 14;          // ATR Period

input group "---- Main Settings ----"
input double             InpBBDeviation  = 2.0;         // Bollinger Deviation
input ENUM_MA_METHOD     InpBBMethod     = MODE_SMA;    // Bollinger MA Method
input ENUM_APPLIED_PRICE InpBBPrice      = PRICE_CLOSE; // Bollinger Applied Price
input double             WPRAmount       = 0.15;      


   
//--- indicator buffers
double ExtUpperBuffer[];
double ExtMiddleBuffer[];
double ExtLowerBuffer[];
double ExtUpperBufferWPR[];
double ExtLowerBufferWPR[];

//--- handles
int handleMA  = INVALID_HANDLE;
int handleWPR = INVALID_HANDLE;
int handleATR = INVALID_HANDLE;

//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, ExtUpperBuffer,  INDICATOR_DATA);
   SetIndexBuffer(1, ExtMiddleBuffer, INDICATOR_DATA);
   SetIndexBuffer(2, ExtLowerBuffer,  INDICATOR_DATA);
   SetIndexBuffer(3, ExtUpperBufferWPR,  INDICATOR_DATA);
   SetIndexBuffer(4, ExtLowerBufferWPR,  INDICATOR_DATA);
   
   
   

   handleMA  = iMA(_Symbol, _Period, InpBBPeriod, 0, InpBBMethod, InpBBPrice);
   handleWPR = iWPR(_Symbol, _Period, InpWPRPeriod);
   handleATR = iATR(_Symbol, _Period, InpATRPeriod);

   if(handleMA == INVALID_HANDLE || handleWPR == INVALID_HANDLE || handleATR == INVALID_HANDLE)
   {
      Print("Failed to create indicator handles. Error = ", GetLastError());
      return(INIT_FAILED);
   }

   IndicatorSetString(INDICATOR_SHORTNAME, "BB + WPR*ATR Offset");
   
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   if(handleMA  != INVALID_HANDLE) IndicatorRelease(handleMA);
   if(handleWPR != INVALID_HANDLE) IndicatorRelease(handleWPR);
   if(handleATR != INVALID_HANDLE) IndicatorRelease(handleATR);
}

//+------------------------------------------------------------------+
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[])
{
   int minBars = MathMax(InpBBPeriod, MathMax(InpStdDevPeriod, MathMax(InpWPRPeriod, InpATRPeriod)));
   if(rates_total < minBars) return(0);

   //--- temporary arrays
   double ma[], wpr[], atr[];
   ArrayResize(ma,  rates_total);
   ArrayResize(wpr, rates_total);
   ArrayResize(atr, rates_total);

   if(CopyBuffer(handleMA,  0, 0, rates_total, ma)  <= 0) return(0);
   if(CopyBuffer(handleWPR, 0, 0, rates_total, wpr) <= 0) return(0);
   if(CopyBuffer(handleATR, 0, 0, rates_total, atr) <= 0) return(0);

   //--- applied price array for StdDev calculation
   double price[];
   ArrayResize(price, rates_total);
   
   switch(InpBBPrice)
   {
      case PRICE_CLOSE:    ArrayCopy(price, close); break;
      case PRICE_OPEN:     ArrayCopy(price, open);  break;
      case PRICE_HIGH:     ArrayCopy(price, high);  break;
      case PRICE_LOW:      ArrayCopy(price, low);   break;
      case PRICE_MEDIAN:   for(int i=0; i<rates_total; i++) price[i] = (high[i]+low[i])/2.0; break;
      case PRICE_TYPICAL:  for(int i=0; i<rates_total; i++) price[i] = (high[i]+low[i]+close[i])/3.0; break;
      case PRICE_WEIGHTED: for(int i=0; i<rates_total; i++) price[i] = (high[i]+low[i]+close[i]+close[i])/4.0; break;
      default:             ArrayCopy(price, close);
   }

   int start = MathMax(prev_calculated - 1, minBars);
   if(start < 0) start = 0;

   for(int i = start; i < rates_total; i++)
   {
      //--- calculate Standard Deviation with independent period
      double sum = 0.0;
      for(int j = 0; j < InpStdDevPeriod; j++)
      {
         double diff = price[i - j] - ma[i];
         sum += diff * diff;
      }
      double stdDev = MathSqrt(sum / InpStdDevPeriod);

      //--- classic Bollinger
      double upper  = ma[i] + InpBBDeviation * stdDev;
      double middle = ma[i];
      double lower  = ma[i] - InpBBDeviation * stdDev;
 
      //--- final lines
      ExtUpperBuffer[i]  = upper;
      ExtMiddleBuffer[i] = middle;
      ExtLowerBuffer[i]  = lower;
      
      //--- WPR centered around 0 and scaled by ATR
      double wprCentered = wpr[i] + 50.0;
      double offset      = wprCentered * atr[i];
      
      ExtUpperBufferWPR[i]  = upper  - WPRAmount * offset / 10.0;
      ExtLowerBufferWPR[i]  = lower  + WPRAmount * offset / 10.0;
   }

   return(rates_total);
}
//+------------------------------------------------------------------+