//+------------------------------------------------------------------+
//|                                                  Impulse_MT5.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1	100
#property indicator_level3	50
#property indicator_level2	0
#property indicator_levelcolor	clrSilver
#property indicator_levelwidth	0
#property indicator_levelstyle	2

#property indicator_buffers 6
#property indicator_plots   6
#property indicator_type1   DRAW_LINE
#property indicator_color1 clrMaroon
#property indicator_style1 2
#property indicator_type2   DRAW_LINE
#property indicator_color2 clrDarkGreen
#property indicator_style2 2
#property indicator_type3   DRAW_LINE
#property indicator_color3 clrNavy
#property indicator_style3 2
#property indicator_type4   DRAW_LINE
#property indicator_color4 clrOrange
#property indicator_width4 2
#property indicator_type5   DRAW_LINE
#property indicator_color5 clrRed
#property indicator_width5 6
#property indicator_type6   DRAW_LINE
#property indicator_color6 clrRed
#property indicator_width6 6


//+------------------------------------------------------------------+
input bool AlertON = false;
input ENUM_STO_PRICE StoPrice_field = STO_CLOSECLOSE; // Method of calculation
//+------------------------------------------------------------------+

//---- buffers
double SignalBuffer[];
double BUFFER_1[];
double BUFFER_2[];
double BUFFER_3[];
double data_a[];
double data_b[];
double data_c[];
double GREEN[];
double RED[];
int per1;
int per2;
int per3;
int n=3;

int indicator_handle_1 = INVALID_HANDLE;
int indicator_handle_2 = INVALID_HANDLE;
int indicator_handle_3 = INVALID_HANDLE;
string fontName = "Arial";
color fontColor = clrRed;
int fontSize = 8;

int shift;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {  
   ObjectCreate(0, "on", OBJ_LABEL, 1, 0, 0);
   ObjectSetInteger(0,"on", OBJPROP_CORNER, 0);
   ObjectSetInteger(0,"on", OBJPROP_XDISTANCE, 10);
   ObjectSetInteger(0,"on", OBJPROP_YDISTANCE, 15);
   ObjectSetInteger(0, "on", OBJPROP_FONTSIZE, fontSize);
   ObjectSetInteger(0, "on",OBJPROP_COLOR, fontColor);
   if (AlertON) ObjectSetString(0, "on",OBJPROP_TEXT,"Alert ON");
   else ObjectSetString(0, "on",OBJPROP_TEXT,"Alert OFF");

    SetIndexBuffer(0, BUFFER_1, INDICATOR_CALCULATIONS);
    SetIndexBuffer(1, BUFFER_2, INDICATOR_CALCULATIONS);
    SetIndexBuffer(2, BUFFER_3, INDICATOR_CALCULATIONS);
    SetIndexBuffer(3, SignalBuffer, INDICATOR_DATA);
    SetIndexBuffer(4, GREEN, INDICATOR_DATA);
    SetIndexBuffer(5, RED, INDICATOR_DATA);
    ArraySetAsSeries(BUFFER_1, true);
    ArraySetAsSeries(BUFFER_2, true);
    ArraySetAsSeries(BUFFER_3, true);
    ArraySetAsSeries(SignalBuffer, true);
    ArraySetAsSeries(GREEN, true);
    ArraySetAsSeries(RED, true);
    
   per1 = (int)Period();
   per2 = (int)per1+1;   
   if (per2==0) n=1;
   per3 = (int)per1+2;
   if (per3==0 && per2 != 0) n=2;  
   
     // Create handles for Stochastic indicators
    indicator_handle_1 = iStochastic(
        _Symbol,         // Symbol
        _Period,           // Timeframe
        per1,              // K-period
        45,                // D-period
        50,                // Slowing
        MODE_EMA,          // MA method
        StoPrice_field          // Applied to the main price
    );

    if (n > 1)
    {
        indicator_handle_2 = iStochastic(
            _Symbol,     // Symbol
            _Period,       // Timeframe
            per2,          // K-period
            50,            // D-period
            100,           // Slowing
            MODE_EMA,      // MA method
            StoPrice_field      // Applied to the main price
        );
    }

    if (n > 2)
    {
        indicator_handle_3 = iStochastic(
            _Symbol,     // Symbol
            _Period,       // Timeframe
            per3,          // K-period
            75,            // D-period
            50,            // Slowing
            MODE_EMA,      // MA method
            StoPrice_field      // Applied to the main price
        );
    }

    // Check if indicator handles are valid
    if (indicator_handle_1 == INVALID_HANDLE ||
        (n > 1 && indicator_handle_2 == INVALID_HANDLE) ||
        (n > 2 && indicator_handle_3 == INVALID_HANDLE))
    {
        Print("Failed to create handles for Stochastic indicators");
        return INIT_FAILED;
    } 
   
   PlotIndexSetString(0,PLOT_LABEL, string_per(per1));
   PlotIndexSetString(1,PLOT_LABEL, string_per(per2));
   PlotIndexSetString(2,PLOT_LABEL, string_per(per3));
   PlotIndexSetString(3,PLOT_LABEL, "Average");
                   
   IndicatorSetString(INDICATOR_SHORTNAME,"Stochastic 3("+string_per(per1)+""+string_per(per2)+""+string_per(per3)+")");
   return(INIT_SUCCEEDED);
  }


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 limit = rates_total - prev_calculated;

    // Initialize arrays with the appropriate size
    ArrayResize(BUFFER_1, rates_total);
    ArrayResize(BUFFER_2, rates_total);
    ArrayResize(BUFFER_3, rates_total);
    ArrayResize(SignalBuffer, rates_total);
    ArrayResize(GREEN, rates_total);
    ArrayResize(RED, rates_total);

    //ArraySetAsSeries(time, true);
    //ArraySetAsSeries(high, true);
    //ArraySetAsSeries(low, true);
    //ArraySetAsSeries(close, true);

    static int barShift_a = 0, barShift_b = 0, barShift_c = 0;

    for (int i = rates_total-1; i >= prev_calculated; i--)
    {
       ENUM_TIMEFRAMES period = Period();
       barShift_a = iBarShift(Symbol(), period, time[i]);
       
       period = (ENUM_TIMEFRAMES)(period + 1);
       barShift_b = iBarShift(Symbol(), period, time[i]);
       
       period = (ENUM_TIMEFRAMES)(period + 1);
       barShift_c = iBarShift(Symbol(), period, time[i]);
       
       
        if (!CopyBuffer(indicator_handle_1, 0, barShift_a, i, BUFFER_1))
        {
            Print("Failed to copy buffer for indicator 1");
            return 0;
        }

        if (!CopyBuffer(indicator_handle_2, 0, barShift_b, i, BUFFER_2))
        {
            Print("Failed to copy buffer for indicator 2");
            return 0;
        }

        if (!CopyBuffer(indicator_handle_3, 0, barShift_c, i, BUFFER_3))
        {
            Print("Failed to copy buffer for indicator 3");
            return 0;
        }      
       
        // Calculate SignalBuffer based on Stochastic values
        if (n == 3)
            SignalBuffer[i] = (BUFFER_1[i] + BUFFER_2[i] + BUFFER_3[i]) / n;
        else if (n == 2)
            SignalBuffer[i] = (BUFFER_1[i] + BUFFER_2[i]) / n;
        else if (n == 1)
            SignalBuffer[i] = BUFFER_1[i];

        // Update plot values based on SignalBuffer
        if (SignalBuffer[i] > 80)
        {
            GREEN[i] = SignalBuffer[i];
            if (AlertON && i < 2)
                Alert(Symbol() + " Stochastic 3 = " + DoubleToString(SignalBuffer[i], 2));
        }

        if (SignalBuffer[i] < 20)
        {
            RED[i] = SignalBuffer[i];
            if (AlertON && i < 2)
                Alert(Symbol() + " Stochastic 3 = " + DoubleToString(SignalBuffer[i], 2));
        }
    }

    return rates_total;
}



string string_per(int per)
{
   if (per <= (int)PERIOD_M1)  return(" M1  ");
   if (per <= (int)PERIOD_M5)  return(" M5  ");
   if (per <= (int)PERIOD_M15) return(" M15 ");
   if (per <= (int)PERIOD_M30) return(" M30 ");
   if (per <= (int)PERIOD_H1) return(" H1  ");
   if (per <= (int)PERIOD_H4) return(" H4  ");
   if (per <= (int)PERIOD_D1) return(" D1  ");
   if (per <= (int)PERIOD_W1) return(" W1  ");
   if (per <= (int)PERIOD_M1) return(" MN1 ");
   
   return("err");
}


void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, "on");
}