//+------------------------------------------------------------------+
//|                                     WeeklyPriceLevelsWithADR.mq4 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025"
#property link      ""
#property version   "1.00"
#ifdef __MQL4__
#property strict
#endif 
#ifdef __MQL5__
#property indicator_plots 0
#endif 
#property indicator_chart_window

// Input Parameters for Historical Data
input int           HistoricalDays   = 10;            // Number of Historical Weeks

// ADR Parameters
input bool          Use_ADR          = true;          // Use AWR?
input int           ADR_Period       = 14;            // Average Weekly Range Period

// Percentage Mode Parameters
input bool          UsePercents      = false;         // Apply Prices by Percentage
input double        FirstLevelPct    = 25;            // First Level Percent
input double        SecondLevelPct   = 50;            // Second Level Percent
input double        ThirdLevelPct    = 75;            // Third Level Percent
input double        FourthLevelPct   = 100;           // Fourth Level Percent

// Input Parameters for Open Line
input color         OpenLineColor    = clrYellow;     // Open Line Color
input ENUM_LINE_STYLE OpenLineStyle  = STYLE_SOLID;   // Open Line Style
input int           OpenLineWidth    = 1;             // Open Line Width
input int           OpenPriceOffset  = 0;             // Offset from Open price (in points)

// Input Parameters for Upper Levels
input color         UpperLevelsColor = clrLime;       // Upper Levels Color
input ENUM_LINE_STYLE UpperLevelsStyle = STYLE_DOT;   // Upper Levels Style
input int           UpperLevelsWidth = 1;             // Upper Levels Width

// Input Parameters for Lower Levels
input color         LowerLevelsColor = clrRed;        // Lower Levels Color
input ENUM_LINE_STYLE LowerLevelsStyle = STYLE_DOT;   // Lower Levels Style
input int           LowerLevelsWidth = 1;             // Lower Levels Width

// Level Distances (in points) - used when Use_ADR = false and UsePercents = false
input int           Level1Distance   = 100;           // Level 1 Distance (in points)
input int           Level2Distance   = 200;           // Level 2 Distance (in points)
input int           Level3Distance   = 300;           // Level 3 Distance (in points)
input int           Level4Distance   = 400;           // Level 4 Distance (in points)
input int           Level5Distance   = 500;           // Level 5 Distance (in points)
input int           Level6Distance   = 600;           // Level 6 Distance (in points)

// Global Variables
string indicatorName = "WeeklyPriceLevels";
double point;

//+------------------------------------------------------------------+
//| Calculate Average Daily Range starting from specified day          |
//+------------------------------------------------------------------+
double CalculateADR(int startDay, int period)
{
    double adr = 0;
    for(int i = 0; i < period; i++)  // Start from 0 to count the proper number of days
    {
        int currentDay = startDay + i + 1;  // Add 1 to skip current day, then add i for lookback
        double high = iHigh(NULL, PERIOD_W1, currentDay);
        double low = iLow(NULL, PERIOD_W1, currentDay);
        adr += (high - low) / _Point;
    }
    return adr / period;
}

//+------------------------------------------------------------------+
//| Get array of level distances based on current settings             |
//+------------------------------------------------------------------+
void GetLevelDistances(double &distances[], int currentDay, double &currentADR)
{
    if(Use_ADR)
    {
        currentADR = CalculateADR(currentDay, ADR_Period);
        
        if(UsePercents)
        {
            // Use only 4 levels with percentage calculations
            ArrayResize(distances, 4);
            distances[0] = currentADR * FirstLevelPct / 100.0;
            distances[1] = currentADR * SecondLevelPct / 100.0;
            distances[2] = currentADR * ThirdLevelPct / 100.0;
            distances[3] = currentADR * FourthLevelPct / 100.0;
        }
        else
        {
            // Using full ADR for 6 levels
            ArrayResize(distances, 6);
            for(int i = 0; i < 6; i++)
            {
                distances[i] = (i + 1) * currentADR / 6.0;
            }
        }
    }
    else
    {
        currentADR = 0;
        if(UsePercents)
        {
            // Use fixed distances but only 4 levels
            ArrayResize(distances, 4);
            distances[0] = Level1Distance;
            distances[1] = Level2Distance;
            distances[2] = Level3Distance;
            distances[3] = Level4Distance;
        }
        else
        {
            // Use all 6 fixed distances
            ArrayResize(distances, 6);
            distances[0] = Level1Distance;
            distances[1] = Level2Distance;
            distances[2] = Level3Distance;
            distances[3] = Level4Distance;
            distances[4] = Level5Distance;
            distances[5] = Level6Distance;
        }
    }
}

//+------------------------------------------------------------------+
//| Custom indicator initialization function                           |
//+------------------------------------------------------------------+
int OnInit()
{
    point = _Point;
    if(HistoricalDays <= 0)
    {
        Print("Number of Historical Weeks must be positive");
        return(INIT_PARAMETERS_INCORRECT);
    }
    
    if(ADR_Period <= 0)
    {
        Print("AWR Period must be positive");
        return(INIT_PARAMETERS_INCORRECT);
    }
    
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    ObjectsDeleteAll(0, indicatorName);
    ChartRedraw(0);
}

//+------------------------------------------------------------------+
//| 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[])
{    
    if(_Period>PERIOD_W1)
     return rates_total;
     
    // Process each historical day
    for(int day = 0; day < HistoricalDays; day++)
    {
        // Get level distances for this specific day
        double levelDistances[];
        double currentADR;
        GetLevelDistances(levelDistances, day, currentADR);
        
        // Get daily open price
        double openPrice = iOpen(NULL, PERIOD_W1, day);
        
        // Calculate time boundaries for this day
        datetime dayStart = iTime(NULL, PERIOD_W1, day);
        datetime dayEnd = dayStart + PeriodSeconds(PERIOD_W1);
        
        // Create ADR text for the line with new format
        string adrText = Use_ADR ? StringFormat("AWR(%d) %d", ADR_Period, (int)currentADR) : "";
        
        // Draw Open line with ADR text
        string openLineName = indicatorName + "OpenLine" + IntegerToString(day);
        CreateLine(openLineName, openPrice + OpenPriceOffset * point, dayStart, dayEnd,
                  OpenLineColor, OpenLineStyle, OpenLineWidth, adrText);
        
        // Draw upper levels
        for(int i = 0; i < ArraySize(levelDistances); i++)
        {
            string upperLineName = indicatorName + "UpperLevel" + IntegerToString(day) + "_" + IntegerToString(i+1);
            double upperPrice = openPrice + (OpenPriceOffset + levelDistances[i]) * point;
            
            // Create percentage text only if UsePercents is true
            string percentText = "";
            if(UsePercents)
            {
                switch(i)
                {
                    case 0: percentText = StringFormat("+%g%%", FirstLevelPct); break;
                    case 1: percentText = StringFormat("+%g%%", SecondLevelPct); break;
                    case 2: percentText = StringFormat("+%g%%", ThirdLevelPct); break;
                    case 3: percentText = StringFormat("+%g%%", FourthLevelPct); break;
                }
            }
            
            CreateLine(upperLineName, upperPrice, dayStart, dayEnd,
                      UpperLevelsColor, UpperLevelsStyle, UpperLevelsWidth, percentText);
        }
        
        // Draw lower levels
        for(int i = 0; i < ArraySize(levelDistances); i++)
        {
            string lowerLineName = indicatorName + "LowerLevel" + IntegerToString(day) + "_" + IntegerToString(i+1);
            double lowerPrice = openPrice + (OpenPriceOffset - levelDistances[i]) * point;
            
            // Create percentage text only if UsePercents is true
            string percentText = "";
            if(UsePercents)
            {
                switch(i)
                {
                    case 0: percentText = StringFormat("-%g%%", FirstLevelPct); break;
                    case 1: percentText = StringFormat("-%g%%", SecondLevelPct); break;
                    case 2: percentText = StringFormat("-%g%%", ThirdLevelPct); break;
                    case 3: percentText = StringFormat("-%g%%", FourthLevelPct); break;
                }
            }
            
            CreateLine(lowerLineName, lowerPrice, dayStart, dayEnd,
                      LowerLevelsColor, LowerLevelsStyle, LowerLevelsWidth, percentText);
        }
    }
    ChartRedraw(0);
    
    return(rates_total);
}

//+------------------------------------------------------------------+
//| Creates or updates a horizontal line with specified parameters     |
//+------------------------------------------------------------------+
void CreateLine(string name, double price, datetime timeStart, datetime timeEnd,
                color lineColor, ENUM_LINE_STYLE lineStyle, int lineWidth, string text)
{
    if(ObjectFind(0, name) < 0)
        ObjectCreate(0, name, OBJ_TREND, 0, 0, 0, 0, 0);
        
#ifdef __MQL5__
    ObjectSetString(0, name, OBJPROP_NAME, name);
    ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor);
    ObjectSetInteger(0, name, OBJPROP_STYLE, lineStyle);
    ObjectSetInteger(0, name, OBJPROP_WIDTH, lineWidth);
    ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, false);
    ObjectSetInteger(0, name, OBJPROP_BACK, true);
    ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
    ObjectSetInteger(0, name, OBJPROP_SELECTED, false);
    ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
    ObjectSetInteger(0, name, OBJPROP_TIME, 0, timeStart);
    ObjectSetInteger(0, name, OBJPROP_TIME, 1, timeEnd);
    ObjectSetDouble(0, name, OBJPROP_PRICE, 0, price);
    ObjectSetDouble(0, name, OBJPROP_PRICE, 1, price);
    if(StringLen(text) > 0)
        ObjectSetString(0, name, OBJPROP_TEXT, text);
#else
    ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor);
    ObjectSetInteger(0, name, OBJPROP_STYLE, lineStyle);
    ObjectSetInteger(0, name, OBJPROP_WIDTH, lineWidth);
    ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, false);
    ObjectSetInteger(0, name, OBJPROP_BACK, true);
    ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
    ObjectSetInteger(0, name, OBJPROP_SELECTED, false);
    ObjectSetInteger(0, name, OBJPROP_TIME1, timeStart);
    ObjectSetInteger(0, name, OBJPROP_TIME2, timeEnd);
    ObjectSetDouble(0, name, OBJPROP_PRICE1, price);
    ObjectSetDouble(0, name, OBJPROP_PRICE2, price);
    if(StringLen(text) > 0)
        ObjectSetString(0, name, OBJPROP_TEXT, text);
#endif
}