//+------------------------------------------------------------------+
//|                                A! Trade SpeedoMETER_FIXED.mq4 |
//+------------------------------------------------------------------+
#property copyright "THIS IS FREE INDICATOR AND NOT FOR SELL (FIXED by AI analysis)"
#property link      "https://forex-station.com/"

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 DodgerBlue
#property indicator_color2 Red 
#property indicator_width1 5
#property indicator_width2 5

//+------------------------------------------------------------------+
//| User Inputs                                                      |
//+------------------------------------------------------------------+
extern double Signal_Distance_Pips = 5.0; // Distance of the dot from the High/Low of the candle (in Pips).
extern bool   Alerts = TRUE;

//---- Range Calculation Inputs ----
// Note: These inputs are restored from the original but DO NOT affect the signal placement.
// Signal placement is controlled by 'Signal_Distance_Pips' above.
extern string _AvgRange_Settings = "---- (Unused) Range Calculation ----"; // Visual Separator
extern bool Use_AvgRange_Div_10  = true;
extern bool Use_Fixed_14_Points  = true;
extern bool Use_Fixed_6_Points   = true;

//---- Bollinger Bands Filter Inputs ----
extern string _BB_Filter_Settings = "---- Bollinger Bands Filter ----"; // Visual Separator
extern bool   Filter_By_BollingerBands = true; // Set to TRUE to only show signals outside the BB
extern int    BB_Period                 = 20;
extern double BB_Deviation              = 2.0;
extern int    BB_AppliedPrice           = PRICE_CLOSE;


//--- Indicator Buffers
double CrossUp[];
double CrossDown[];

//--- Global Variables
bool upalert=false, downalert=false;
double _Pip;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   SetIndexStyle(0, DRAW_ARROW, EMPTY, 5);
   SetIndexArrow(0, 159);
   SetIndexBuffer(0, CrossUp);
   SetIndexLabel(0,"Up Signal");

   SetIndexStyle(1, DRAW_ARROW, EMPTY, 5);
   SetIndexArrow(1, 159);
   SetIndexBuffer(1, CrossDown);
   SetIndexLabel(1,"Down Signal");
   
   //---- Automatically calculate the Pip size for the current symbol ----
   if(Digits==3 || Digits==5)
     _Pip=Point*10;
   else
     _Pip=Point;
     
   IndicatorShortName("SpeedoMETER (Fixed)");
   
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   Comment(""); 
   return(0);
}
  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start() 
{
   int limit;
   int counted_bars=IndicatorCounted();
   
   if(counted_bars < 0) return(-1);
   if(counted_bars > 0) counted_bars--;

   limit = Bars - counted_bars;

   // Start loop from the most recent bar backwards
   for(int i = limit; i >= 0; i--) 
   {
      // To avoid Array out of range error, ensure we have enough bars for calculation
      if (i > Bars - 20) continue;
      
      int k;
      int lastSignal;
      bool drawSignal;
      
      // RESTORED: This calculation block is from the original code.
      // Its result ('Range') is not used anywhere else in the indicator logic.
      double Range, AvgRange;
      if(Use_Fixed_14_Points)
      {
         Range = 14 * Point; // Use fixed 14 points
      }
      else if(Use_Fixed_6_Points)
      {
         Range = 6 * Point;  // Use fixed 6 points
      }
      else // This is the default if the others are false (or if Use_AvgRange_Div_10 is explicitly true)
      {
         AvgRange=0;
         for (int counter=i ;counter<=i+12;counter++)
         {
            AvgRange=AvgRange+MathAbs(High[counter]-Low[counter]);
         }
         Range=AvgRange/10;
      }
      // END of restored block
      
      double SOT[11]; // Array to hold Speed of Tape values for current and past 10 bars
      
      for(int j=0; j<=10; j++)
      {
         double p_j = Close[i+j] - Open[i+j];
         double v_j = Volume[i+j];
         if (v_j < 1) v_j = 1; // Avoid division by zero
         SOT[j] = (p_j / v_j) * 10000;
      }

      double SOTAV10 = 0;
      for(k=1; k<=10; k++)
      {
         SOTAV10 += SOT[k];
      }
      SOTAV10 = SOTAV10 / 10.0;

      double SOTAV2 = SOTAV10 * 2.0;

      bool isUpSignal = false;
      bool isDownSignal = false;

      if ((SOT[0] > SOTAV2) && (Close[i+1] < Open[i+1]) && (Close[i] < Open[i+1])) {
          isUpSignal = true;
      }
      
      if ((SOT[0] > SOTAV2) && (Close[i+1] > Open[i+1]) && (Close[i] > Open[i])) {
          isDownSignal = true;
      }
      
      CrossUp[i] = EMPTY_VALUE;
      CrossDown[i] = EMPTY_VALUE;

      if(isUpSignal)
      {
         lastSignal = 0; 
         for(k=i+1; k<Bars; k++)
         {
            if(CrossUp[k] != EMPTY_VALUE) { lastSignal = 1; break; }
            if(CrossDown[k] != EMPTY_VALUE) { lastSignal = 2; break; }
         }
         
         if(lastSignal != 1)
         {
            drawSignal = !Filter_By_BollingerBands || (Filter_By_BollingerBands && Low[i] < iBands(NULL, 0, BB_Period, BB_Deviation, 0, BB_AppliedPrice, MODE_LOWER, i));

            if(drawSignal)
            {
               CrossUp[i] = Low[i] - (Signal_Distance_Pips * _Pip);
               if(i <= 1 && Alerts && !upalert)
               {
                  Alert (Symbol()," ",Period()," M Price UP ");
                  upalert=true;
                  downalert=false;
               }
            }
         }
      }

      if(isDownSignal)
      {
         lastSignal = 0;
         for(k=i+1; k<Bars; k++)
         {
            if(CrossUp[k] != EMPTY_VALUE) { lastSignal = 1; break; }
            if(CrossDown[k] != EMPTY_VALUE) { lastSignal = 2; break; }
         }
         
         if(lastSignal != 2)
         {
            drawSignal = !Filter_By_BollingerBands || (Filter_By_BollingerBands && High[i] > iBands(NULL, 0, BB_Period, BB_Deviation, 0, BB_AppliedPrice, MODE_UPPER, i));
            
            if(drawSignal)
            {
               CrossDown[i] = High[i] + (Signal_Distance_Pips * _Pip);
               if(i <= 1 && Alerts && !downalert)
               {
                  Alert (Symbol()," ",Period()," M  Price DOWN ");
                  downalert=true;
                  upalert=false;
               }
            }
         }
      }
   }
   return(0);
}