//+------------------------------------------------------------------+
//|                                        DailyFibFanReverse.mq4   |
//|                           Copyright 2025, YourName               |
//|                   https://www.yoursite.com                       |
//+------------------------------------------------------------------+
#property copyright "2025, YourName"
#property link      "https://www.yoursite.com"
#property version   "1.50"
#property strict
#property indicator_chart_window
#property indicator_buffers 0

//--- user inputs
input int      DaysToShow       = 5;           // Number of days (including today) to display
input double   FanLengthInPips  = 100.0;       // Vertical distance (in pips) for the largest fib level
input int      FanLevelsCount   = 5;           // How many fib levels to draw (max 5)
input double   FibRatio1        = 3.4;       // First Fibonacci ratio
input double   FibRatio2        = 6.2;       // Second Fibonacci ratio
input double   FibRatio3        = 8.9;         // Third Fibonacci ratio
input double   FibRatio4        = 12.1;       // Fourth Fibonacci ratio
input double   FibRatio5        = 16.2;       // Fifth Fibonacci ratio
input color    ZeroLineColor    = clrWhite;
input color    FanLineColor     = clrYellow;
input ENUM_LINE_STYLE ZeroLineStyle = STYLE_SOLID;
input ENUM_LINE_STYLE FanLineStyle  = STYLE_DOT;
input int      ZeroLineWidth    = 1;
input int      FanLineWidth     = 1;

//--- internal
double FibRatios[5];
int    LastDrawnDay = -1;

//+------------------------------------------------------------------+
//| Indicator initialization                                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   // populate ratios array
   FibRatios[0] = FibRatio1;
   FibRatios[1] = FibRatio2;
   FibRatios[2] = FibRatio3;
   FibRatios[3] = FibRatio4;
   FibRatios[4] = FibRatio5;
   
   DrawAllFans();
   EventSetTimer(60); // check once a minute for new day
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Indicator deinitialization                                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   EventKillTimer();
   DeleteAllFanObjects();
  }

//+------------------------------------------------------------------+
//| Required stub for a custom indicator                             |
//+------------------------------------------------------------------+
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[])
  {
   return(rates_total);
  }

//+------------------------------------------------------------------+
//| Timer handler: redraw if day has rolled over                     |
//+------------------------------------------------------------------+
void OnTimer()
  {
   int today = TimeDay(iTime(_Symbol, PERIOD_D1, 0));
   if(today != LastDrawnDay)
     {
      DeleteAllFanObjects();
      DrawAllFans();
     }
  }

//+------------------------------------------------------------------+
//| Draw reversed fans for the last N days                           |
//+------------------------------------------------------------------+
void DrawAllFans()
  {
   LastDrawnDay = TimeDay(iTime(_Symbol, PERIOD_D1, 0));
   double pipValue = Point * ((int)MarketInfo(_Symbol, MODE_POINT)==1 ? 1 : 10);
   double maxDelta = FanLengthInPips * pipValue;
   int    levels   = MathMin(FanLevelsCount, 5);
   
   for(int idx = 0; idx < DaysToShow; idx++)
     {
      datetime dayStart = iTime(_Symbol, PERIOD_D1, idx);
      datetime dayEnd   = dayStart + PeriodSeconds(PERIOD_D1);
      double   openP    = iOpen(_Symbol, PERIOD_D1, idx);
      string   dateStr  = TimeToString(dayStart, TIME_DATE);  // e.g. "2025.04.09"
      
      // zero line at day end back to day start
      string zeroName = "RDFZ_Zero_" + dateStr;
      ObjectCreate(0, zeroName, OBJ_TREND, 0, dayEnd, openP, dayStart, openP);
      ObjectSetInteger(0, zeroName, OBJPROP_COLOR,     ZeroLineColor);
      ObjectSetInteger(0, zeroName, OBJPROP_STYLE,     ZeroLineStyle);
      ObjectSetInteger(0, zeroName, OBJPROP_WIDTH,     ZeroLineWidth);
      ObjectSetInteger(0, zeroName, OBJPROP_RAY_RIGHT, false);
      ObjectSetInteger(0, zeroName, OBJPROP_RAY_LEFT,  false);
      
      // reversed fan arms
      for(int i=0; i<levels; i++)
        {
         double ratio = FibRatios[i];
         double delta = maxDelta * ratio;
         int    ratioPct = int(ratio * 1000);  // e.g. 236, 382, 500, 618, 786
         
         // up (backwards)
         string upName = StringFormat("RDFF_Up_%s_%d", dateStr, ratioPct);
         ObjectCreate(0, upName, OBJ_TREND, 0, dayEnd, openP, dayStart, openP + delta);
         ObjectSetInteger(0, upName, OBJPROP_COLOR,     FanLineColor);
         ObjectSetInteger(0, upName, OBJPROP_STYLE,     FanLineStyle);
         ObjectSetInteger(0, upName, OBJPROP_WIDTH,     FanLineWidth);
         ObjectSetInteger(0, upName, OBJPROP_RAY_RIGHT, false);
         ObjectSetInteger(0, upName, OBJPROP_RAY_LEFT,  false);
         
         // down (backwards)
         string dnName = StringFormat("RDFF_Dn_%s_%d", dateStr, ratioPct);
         ObjectCreate(0, dnName, OBJ_TREND, 0, dayEnd, openP, dayStart, openP - delta);
         ObjectSetInteger(0, dnName, OBJPROP_COLOR,     FanLineColor);
         ObjectSetInteger(0, dnName, OBJPROP_STYLE,     FanLineStyle);
         ObjectSetInteger(0, dnName, OBJPROP_WIDTH,     FanLineWidth);
         ObjectSetInteger(0, dnName, OBJPROP_RAY_RIGHT, false);
         ObjectSetInteger(0, dnName, OBJPROP_RAY_LEFT,  false);
        }
     }
  }

//+------------------------------------------------------------------+
//| Delete any object with our prefixes                              |
//+------------------------------------------------------------------+
void DeleteAllFanObjects()
  {
   string prefixes[] = { "RDFZ_Zero_", "RDFF_Up_", "RDFF_Dn_" };
   int total = ObjectsTotal();
   for(int i=total-1; i>=0; i--)
     {
      string name = ObjectName(i);
      for(int p=0; p<ArraySize(prefixes); p++)
        {
         if(StringFind(name, prefixes[p]) == 0)
           {
            ObjectDelete(0, name);
            break;
           }
        }
     }
  }
//+------------------------------------------------------------------+
