﻿
//+----+
//|                    XU EFFECT v3.11     |
//|         ULTRA-OPTIMIZED EDITION - ALL FIXES APPLIED              |
//|         TERNARY EVOLUTION EDITION - PRODUCTION READY             |
//|         + INLINE TERNARY LIBRARY                    |
//|         + TERNARY CONFIDENCE LAYER                    |
//|         + SEMA BIAS INTEGRATION                    |
//|         + HUD FOREGROUND PRIORITY                    |
//|         + RSI TERNARY COMPONENT (O(1) OPTIMIZED)                 |
//|         + EXPONENTIAL ARRAY GROWTH                    |
//|         + OBJECT CACHING SYSTEM                    |
//|         + RAII HANDLE MANAGEMENT                    |
//|         + TERNARY LOOKUP OPTIMIZATION                    |
//|                    |
//|  v3.11 CHANGES:                    |
//|  - UX FIX: Changed MaxCalcBars warning to informational message   |
//|    * Now prints INFO instead of WARNING when bars < MaxCalcBars   |
//|    * Clarifies this is normal behavior, not a problem             |
//|    * Indicator handles limited history gracefully in OnCalculate  |
//|                    |
//|  v3.10 CHANGES:                    |
//|  - REMOVED: Account Protection Layer module                       |
//|  - REMOVED: Crimson ΔVol Lockout module                          |
//|  - PRESERVED: All v3.09 bug fixes and optimizations              |
//|  - PRESERVED: Delta volatility monitoring (without lockout)      |
//|                    |
//|  MODULES REMOVED IN v3.10:                    |
//|  1. Account Protection Layer:                    |
//|     - AccountProtection struct                    |
//|     - InitializeAccountProtection()                    |
//|     - UpdateAccountProtection()                    |
//|     - IsAccountLockedOut()                    |
//|     - GetAccountProtectionStatus()                    |
//|     - GetAccountProtectionColor()                    |
//|     - All related input parameters                    |
//|                    |
//|  2. Crimson ΔVol Lockout:                    |
//|     - CheckCrimsonLockout()                    |
//|     - AreSignalsSuppressed()                    |
//|     - GetCrimsonStatusText()                    |
//|     - CrimsonLockoutActive/TriggerTime/CooldownBars              |
//|     - All related input parameters                    |
//|                    |
//|  v3.09 FIXES PRESERVED:                    |
//|  - FIXED: Configuration constants contradiction (INITIAL vs MAX) |
//|  - FIXED: RAII handle recovery MA parameter storage bug          |
//|  - FIXED: RSI running sum calculation edge cases                 |
//|  - FIXED: Ternary lookup bounds validation                       |
//|  - FIXED: Yesterday ATR true range calculation                   |
//|  - FIXED: CopyBuffer series indexing consistency                 |
//|  - FIXED: VWAPTrendState array bounds safety                     |
//|  - FIXED: CalculateNewSize static variable disconnect            |
//|  - FIXED: CObjectCache exponential growth                        |
//|  - FIXED: Overextension value clamping                           |
//|  - FIXED: Input validation for ATR periods                       |
//|  - FIXED: Centralized version constant                           |
//|  - PRESERVED: All v3.08 optimizations                            |
//+----+
#property copyright "XU EFFECT v3.11 - Simplified Edition"
#property link      "https://xu-systems.com"
#property version   "3.11"
#property indicator_chart_window
#property indicator_buffers 18
#property indicator_plots   6

// --- VERSION CONSTANT (v3.09 fix: centralized version string) ---
#define XU_VERSION "3.11"

// --- PLOTS ---
#property indicator_label1  "Daily VWAP"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrGold
#property indicator_style1  STYLE_DASH
#property indicator_width1  2
#property indicator_label2  "Sniper Candles"
#property indicator_type2   DRAW_COLOR_CANDLES
#property indicator_color2  clrDimGray, clrDodgerBlue, clrDeepPink
#property indicator_label3  "VWAP Upper Band"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrDarkGray
#property indicator_style3  STYLE_DASH
#property indicator_width3  1
#property indicator_label4  "VWAP Lower Band"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrDarkGray
#property indicator_style4  STYLE_DASH
#property indicator_width4  1
#property indicator_label5  "Dev Band 2.0 Upper"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrDarkGray
#property indicator_style5  STYLE_DASH
#property indicator_width5  1
#property indicator_label6  "Dev Band 2.0 Lower"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrDarkGray
#property indicator_style6  STYLE_DASH
#property indicator_width6  1

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: CONFIGURATION CONSTANTS                 |
//|                                                                  |
//+------------------------------------------------------------------+
struct XUConfig {
   static const int    INITIAL_ARRAY_SIZE;
   static const int    MAX_ARRAY_SIZE;
   static const int    MAX_GROWTH_STEP;
   static const double GROWTH_FACTOR;
   static const int    HANDLE_CHECK_INTERVAL_SEC;
   static const int    HANDLE_RECOVERY_INTERVAL_SEC;
   static const int    HUD_THROTTLE_MS;
   static const int    MAX_HUD_UPDATES_PER_SEC;
   static const int    BUFFER_BARS_REQUIRED;
   static const int    DEFAULT_MAX_CALC_BARS;
   static const double VWAP_MIN_VOLUME;
   static const double VIRGIN_THRESHOLD;
   static const double KING_THRESHOLD;
   static const double TYRANT_THRESHOLD;
   static const double EXT_HUD_SCALE;
   static const double OVR_HUD_SCALE;
   static const double DELTA_COMPRESSION;
   static const double DELTA_EXHAUSTED;
   static const double DELTA_EQUILIBRIUM;
   static const double DELTA_RUNNING;
   static const double MEMORY_BREAKOUT;
   static const double MEMORY_FALSE_BREAK;
   static const double RELATIVE_EPSILON;
   static const double EXT_DIVISOR;
   static const double MAX_OVEREXTENSION;
   static const int    CACHE_GROWTH_FACTOR;
};

const int    XUConfig::INITIAL_ARRAY_SIZE         = 10000;
const int    XUConfig::MAX_ARRAY_SIZE             = 100000;
const int    XUConfig::MAX_GROWTH_STEP            = 10000;
const double XUConfig::GROWTH_FACTOR              = 1.5;
const int    XUConfig::HANDLE_CHECK_INTERVAL_SEC  = 3600;
const int    XUConfig::HANDLE_RECOVERY_INTERVAL_SEC = 300;
const int    XUConfig::HUD_THROTTLE_MS            = 100;
const int    XUConfig::MAX_HUD_UPDATES_PER_SEC    = 10;
const int    XUConfig::BUFFER_BARS_REQUIRED       = 3;
const int    XUConfig::DEFAULT_MAX_CALC_BARS      = 5000;
const double XUConfig::VWAP_MIN_VOLUME           = 1e-10;
const double XUConfig::VIRGIN_THRESHOLD          = 50.0;
const double XUConfig::KING_THRESHOLD            = 100.0;
const double XUConfig::TYRANT_THRESHOLD          = 300.0;
const double XUConfig::EXT_HUD_SCALE             = 300.0;
const double XUConfig::OVR_HUD_SCALE             = 300.0;
const double XUConfig::DELTA_COMPRESSION         = 0.5;
const double XUConfig::DELTA_EXHAUSTED           = 0.8;
const double XUConfig::DELTA_EQUILIBRIUM         = 1.2;
const double XUConfig::DELTA_RUNNING             = 2.0;
const double XUConfig::MEMORY_BREAKOUT           = 1.2;
const double XUConfig::MEMORY_FALSE_BREAK        = 0.8;
const double XUConfig::RELATIVE_EPSILON          = 1e-9;
const double XUConfig::EXT_DIVISOR               = 50.0;
const double XUConfig::MAX_OVEREXTENSION         = 1000.0;
const int    XUConfig::CACHE_GROWTH_FACTOR       = 2;

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: UTILITIES & LIBRARIES                   |
//|                                                                  |
//+------------------------------------------------------------------+
//| INLINE TERNARY LIBRARY - OPTIMIZED                    |
//+------------------------------------------------------------------+
#define TRIT_T  (-1)
#define TRIT_0  (0)
#define TRIT_1  (1)
#define TRIT_IDX(t) (MathMax(0, MathMin(2, (t) + 1)))

#define FLOAT_EPSILON g_FloatEpsilon
#define IS_VALID_PRICE(p) ((p) > FLOAT_EPSILON && MathIsValidNumber(p))
#define IS_GREATER(a, b) ((a) > (b) + FLOAT_EPSILON)
#define IS_LESS(a, b) ((a) < (b) - FLOAT_EPSILON)
#define IS_EQUAL(a, b) (IsEqualRobust((a), (b)))
#define IS_GREATER_EQUAL(a, b) ((a) >= (b) - FLOAT_EPSILON)
#define IS_LESS_EQUAL(a, b) ((a) <= (b) + FLOAT_EPSILON)

bool IsEqualRobust(double a, double b) {
   double diff = MathAbs(a - b);
   double maxVal = MathMax(MathAbs(a), MathAbs(b));
   return (diff <= FLOAT_EPSILON) || (diff <= maxVal * XUConfig::RELATIVE_EPSILON);
}

template<typename T>
T SafeArrayGet(const T &arr[], int idx, T defaultVal) {
   return (idx >= 0 && idx < ArraySize(arr)) ? arr[idx] : defaultVal;
}

template<typename T>
bool SafeArraySet(T &arr[], int idx, T val) {
   if(idx >= 0 && idx < ArraySize(arr)) {
      arr[idx] = val;
      return true;
   }
   return false;
}

double GetSymbolEpsilon() {
   static double epsilon = 0;
   if(epsilon == 0) {
      epsilon = (StringFind(_Symbol, "JPY") >= 0) ? _Point * 2.0 : _Point * 0.5;
      epsilon = MathMax(epsilon, 1e-10);
   }
   return epsilon;
}

//+----+
//| TERNARY LOOKUP TABLE OPTIMIZATION                    |
//+----+
static const int TERNARY_LOOKUP[3][3][3] = {
   {{TRIT_T, TRIT_T, TRIT_0}, {TRIT_T, TRIT_0, TRIT_0}, {TRIT_0, TRIT_0, TRIT_1}},
   {{TRIT_T, TRIT_0, TRIT_0}, {TRIT_0, TRIT_0, TRIT_0}, {TRIT_0, TRIT_0, TRIT_1}},
   {{TRIT_0, TRIT_0, TRIT_1}, {TRIT_0, TRIT_0, TRIT_1}, {TRIT_1, TRIT_1, TRIT_1}}
};

int TernaryConsensusFast(int a, int b, int c) {
   a = MathMax(TRIT_T, MathMin(TRIT_1, a));
   b = MathMax(TRIT_T, MathMin(TRIT_1, b));
   c = MathMax(TRIT_T, MathMin(TRIT_1, c));
   return TERNARY_LOOKUP[TRIT_IDX(a)][TRIT_IDX(b)][TRIT_IDX(c)];
}

int TernaryNOT(int a) {
   if(a == TRIT_1) return TRIT_T;
   if(a == TRIT_T) return TRIT_1;
   return TRIT_0;
}

int TernaryAND(int a, int b) {
   if(a == TRIT_T || b == TRIT_T) return TRIT_T;
   if(a == TRIT_0 || b == TRIT_0) return TRIT_0;
   return TRIT_1;
}

int TernaryOR(int a, int b) {
   if(a == TRIT_1 || b == TRIT_1) return TRIT_1;
   if(a == TRIT_0 || b == TRIT_0) return TRIT_0;
   return TRIT_T;
}

int TernaryConsensus(int a, int b, int c = TRIT_0) {
   return TernaryConsensusFast(a, b, c);
}

int TernarySmooth(int current, int previous, int smoothing = 1) {
   if(current == previous) return current;
   if(current == TRIT_0) return previous;
   if(previous == TRIT_0) return current;
   if(smoothing > 0) return TRIT_0;
   return current;
}

string TernaryToString(int trit) {
   if(trit == TRIT_1) return "BULLISH";
   if(trit == TRIT_T) return "BEARISH";
   return "NEUTRAL";
}

color TernaryToColor(int trit) {
   if(trit == TRIT_1) return clrDodgerBlue;
   if(trit == TRIT_T) return clrDeepPink;
   if(trit == TRIT_T) return clrDeepPink;
   return clrDarkGray;
}

double g_FloatEpsilon = 0.0;

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: DATA STRUCTURES                         |
//|                                                                  |
//+------------------------------------------------------------------+
struct STernaryBias {
   int    ternaryValue;
   int    confidence;
   string direction;
   double strength;
};

struct STernarySignal {
   int    direction;
   int    confidenceTier;
   bool   isValid;
   string rejectionReason;
   int    ternaryConfidence;
};

struct BufferState {
   int bufferCount;
   double initialRangeRatio;
   double lastRangeRatio;
   bool hasGrayCandle;
   int signalDirection;
   datetime triggerBar;
   bool isValid;
   int holdBarsRemaining;
};

struct DailyMemory {
   double high;
   double low;
   double open;
   double close;
   double range;
   double body;
   double atr;
   bool   isBull;
   datetime date;
};

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: RAII UTILITIES                          |
//|                                                                  |
//+------------------------------------------------------------------+
//| RAII HANDLE MANAGEMENT CLASS                    |
//+------------------------------------------------------------------+
class CIndicatorHandle {
private:
   int               m_handle;
   string            m_symbol;
   ENUM_TIMEFRAMES   m_period;
   ENUM_INDICATOR    m_type;
   int               m_param1;
   int               m_param2;
   ENUM_MA_METHOD    m_ma_method;
   ENUM_APPLIED_PRICE m_applied_price;
   bool              m_initialized;

public:
   CIndicatorHandle() : m_handle(INVALID_HANDLE), m_initialized(false),
                        m_ma_method(MODE_SMA), m_applied_price(PRICE_CLOSE) {}
   ~CIndicatorHandle() { Release(); }

   void Release() {
      if(m_handle != INVALID_HANDLE) {
         IndicatorRelease(m_handle);
         m_handle = INVALID_HANDLE;
         m_initialized = false;
      }
   }

   bool CreateATR(string symbol, ENUM_TIMEFRAMES period, int atrPeriod) {
      Release();
      m_symbol = symbol;
      m_period = period;
      m_type = IND_ATR;
      m_param1 = atrPeriod;
      m_handle = iATR(symbol, period, atrPeriod);
      m_initialized = (m_handle != INVALID_HANDLE);
      return m_initialized;
   }

   bool CreateMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod,
                 int maShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice) {
      Release();
      m_symbol = symbol;
      m_period = period;
      m_type = IND_MA;
      m_param1 = maPeriod;
      m_param2 = maShift;
      m_ma_method = maMethod;
      m_applied_price = appliedPrice;
      m_handle = iMA(symbol, period, maPeriod, maShift, maMethod, appliedPrice);
      m_initialized = (m_handle != INVALID_HANDLE);
      return m_initialized;
   }

   bool CreateRSI(string symbol, ENUM_TIMEFRAMES period, int rsiPeriod,
                  ENUM_APPLIED_PRICE appliedPrice) {
      Release();
      m_symbol = symbol;
      m_period = period;
      m_type = IND_RSI;
      m_param1 = rsiPeriod;
      m_applied_price = appliedPrice;
      m_handle = iRSI(symbol, period, rsiPeriod, appliedPrice);
      m_initialized = (m_handle != INVALID_HANDLE);
      return m_initialized;
   }

   bool Validate() {
      if(m_handle == INVALID_HANDLE) return false;
      double test[1];
      return (CopyBuffer(m_handle, 0, 0, 1, test) == 1);
   }

   bool Recover() {
      if(Validate()) return true;
      Print("XU EFFECT v" + XU_VERSION + ": Handle validation failed, attempting recovery...");
      Release();

      switch(m_type) {
         case IND_ATR:
            m_handle = iATR(m_symbol, m_period, m_param1);
            break;
         case IND_MA:
            m_handle = iMA(m_symbol, m_period, m_param1, m_param2,
                    m_ma_method, m_applied_price);
            break;
         case IND_RSI:
            m_handle = iRSI(m_symbol, m_period, m_param1, m_applied_price);
            break;
         default:
            return false;
      }

      m_initialized = (m_handle != INVALID_HANDLE);
      if(m_initialized) Print("XU EFFECT v" + XU_VERSION + ": Handle recovered successfully");
      return m_initialized;
   }

   int GetHandle() const { return m_handle; }
   bool IsValid() const { return m_handle != INVALID_HANDLE; }

   int CopyBufferToArray(int bufferIndex, int startPos, int count, double &arr[]) {
      if(m_handle == INVALID_HANDLE) return 0;
      return CopyBuffer(m_handle, bufferIndex, startPos, count, arr);
   }
};

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: OBJECT CACHING SYSTEM                   |
//|                                                                  |
//+------------------------------------------------------------------+
class CObjectCache {
private:
   struct ObjectEntry {
      string name;
      bool exists;
      datetime lastAccess;
   };
   ObjectEntry m_cache[];
   int m_size;
   int m_capacity;

public:
   CObjectCache() : m_size(0), m_capacity(0) {}

   int FindIndex(const string name) {
      for(int i = 0; i < m_size; i++) {
         if(m_cache[i].name == name) return i;
      }
      return -1;
   }

   bool Exists(const string name) {
      int idx = FindIndex(name);
      if(idx >= 0) {
         m_cache[idx].lastAccess = TimeCurrent();
         return m_cache[idx].exists;
      }
      bool exists = (ObjectFind(0, name) >= 0);
      AddEntry(name, exists);
      return exists;
   }

   void AddEntry(const string name, bool exists) {
      int idx = FindIndex(name);
      if(idx >= 0) {
         m_cache[idx].exists = exists;
         return;
      }

      if(m_size >= m_capacity) {
         int newCapacity = (m_capacity == 0) ? 16 : m_capacity * XUConfig::CACHE_GROWTH_FACTOR;
         ArrayResize(m_cache, newCapacity);
         m_capacity = newCapacity;
      }

      m_cache[m_size].name = name;
      m_cache[m_size].exists = exists;
      m_cache[m_size].lastAccess = TimeCurrent();
      m_size++;
   }

   void MarkDeleted(const string name) {
      int idx = FindIndex(name);
      if(idx >= 0) m_cache[idx].exists = false;
   }

   void Clear() {
      ArrayFree(m_cache);
      m_size = 0;
      m_capacity = 0;
   }
};

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: INPUT PARAMETERS                        |
//|                                                                  |
//+------------------------------------------------------------------+
input group "=== Operation Mode ==="
input int    InpMaxCalcBars      = 5000;
input bool   InpCalculateHistory = false;

input group "=== Performance Optimization ==="
input bool   InpEnablePerformanceMode = true;
input int    InpMaxHUDUpdatesPerSecond = 10;

input group "=== HUD Sizing ==="
input int    InpHUDWidth = 400;
input int    InpHUDBarHeight = 16;
input int    InpHUDTextSize = 10;

input group "=== Ternary Confidence Layer ==="
input bool   InpEnableTernaryConfidence = true;
input int    InpTernaryLookback = 5;
input bool   InpRequireTernaryAlignment = true;
input int    InpMinTernaryConfidence = 1;

input group "=== RSI Ternary Component ==="
input bool   InpEnableRSITernary = true;
input int    InpRSIPeriod = 13;
input int    InpRSIMAPeriod = 16;

input group "=== SEMA Bias Integration ==="
input bool   InpEnableSEMABias = true;
input int    InpSEMAFastPeriod = 13;
input int    InpSEMASlowPeriod = 52;
input bool   InpRequireSEMAConsensus = true;

input group "=== VWAP Settings ==="
input bool   InpSkipWeekendReset = true;
input int    InpMaxGapHours      = 72;
input bool   InpShowVWAPBands    = true;
input double InpBandMultiplier   = 1.0;

input group "=== Dev Bands 2.0 ==="
input bool   InpShowDevBands2    = true;
input double InpDevBandMultiplier = 2.0;

input group "=== Dynamic Extension (Forex/Cross-Asset) ==="
input bool   InpUseDynamicExt    = true;     // Use ATR-based EXT (Normalized)
input double InpExtATRFactor     = 1.0;      // 100% EXT = distance of 1.0 * ATR

input group "=== Session-Static ATR ==="
input bool   InpEnableMTFStaticATR = true;
input int    InpM4ATRPeriod      = 360;
input bool   InpUseSessionStaticATR = true;

input group "=== Volatility Delta Module ==="
input bool   InpEnableDeltaVol     = true;
input int    InpDeltaVolPeriod     = 60;
input bool   InpFilterSnapByDelta  = true;

input group "=== Memory Module ==="
input bool   InpEnableMemoryModule = true;
input bool   InpShowMemoryHUD      = true;
input bool   InpUseYesterdayATR    = true;
input bool   InpShowRangeRatio     = true;
input bool   InpEnableMemoryFlip   = true;

input group "=== 3-Bar Coordination Buffer ==="
input bool   InpEnable3BarBuffer   = true;
input bool   InpRequireExpansion   = true;
input bool   InpRequireCleanRecord = true;
input int    InpBufferMinHoldBars  = 1;

input group "=== Dual HUD ==="
input bool   InpShowDualHUD      = true;
input int    InpHUDHistoryBars   = 20;
input bool   InpSnapBackAlert    = true;
input double InpMaxDecayFactor   = 0.995;

input group "=== Three-Sigma Zone Thresholds ==="
input double InpTruthThreshold   = 50.0;
input double InpLieThreshold     = 300.0;

input group "=== Audio & Alerts ==="
input bool   InpUseTickSound     = true;
input bool   InpMobileAlert      = false;
input bool   InpPushNotification = false;
input bool   InpDesktopAlert     = false;
input int    InpAlertInterval    = 10;
input bool   InpAlertOnNeutral   = false;

input group "=== Dashboard Visuals ==="
input bool   InpShowDashboardBg  = true;
input color  InpDashboardBgColor = C'10,20,20';
input bool   InpShowDashboardBorder = true;
input color  InpDashboardBorderColor = clrSilver;
input int    InpDashboardOpacity = 255;

input group "=== Main Dashboard Position/Size ==="
input int    InpMainBgX          = 1;
input int    InpMainBgY          = 100;
input int    InpMainBgW          = 470;
input int    InpMainBgH          = 100;

input group "=== Status Panel Position/Size ==="
input int    InpStatusBgX        = 1;
input int    InpStatusBgY        = 155;
input int    InpStatusBgW        = 470;
input int    InpStatusBgH        = 110;

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: INDICATOR BUFFERS                       |
//|                                                                  |
//+------------------------------------------------------------------+
double VwapBuffer[];
double CandleOpen[], CandleHigh[], CandleLow[], CandleClose[];
double CandleColor[];
double VwapUpperBuffer[], VwapLowerBuffer[];
double DevBand2Upper[], DevBand2Lower[];
double pv_accum[], v_accum[];
double price_sq_accum[];
double SessionTRAccum[], SessionATR[];
double SessionBarCount[];
double RSIBuffer[];
double RSIMABuffer[];

//+----+
//| TERNARY BUFFERS                    |
//+----+
int TernaryBiasBuffer[];
int TernaryConfidenceBuffer[];
double SEMAFastBuffer[];
double SEMASlowBuffer[];

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: GLOBAL VARIABLES                        |
//|                                                                  |
//+------------------------------------------------------------------+
datetime LastAlertTime = 0;
int LastAlertTrend = 0;
bool UICreated = false;
string CachedTFString = "";
int CurrentObservationState = 0;
datetime ObservationTriggerBar = 0;

BufferState CoordinationBuffer;

datetime LastSnapBackAlertBar = 0;
double LastExtDisplayed = EMPTY_VALUE;
double LastOvrDisplayed = EMPTY_VALUE;
string LastStatusText = "";
string LastStratMsg = "";

bool   g_useMTFStaticATR = true;
double g_atrScaleFactor = 1.0;

bool   g_enableDeltaVol = true;
double CurrentDeltaVol = 1.0;
double ReferenceATR_1H = 0.0;
string CurrentDeltaStatus = "INITIALIZING";
color  CurrentDeltaColor = clrWhite;

double CurrentExtension = 0.0;
double CurrentOverextension = 0.0;
double MaxExtensionUp = 0.0, MaxExtensionDown = 0.0;
double MaxOverextensionUp = 0.0, MaxOverextensionDown = 0.0;
double PreviousExtension = 0.0, PreviousOverextension = 0.0;
datetime LastSnapBackAlert = 0;

int ZoneHistory[];
int VWAPTrendState[];

DailyMemory Yesterday;
DailyMemory Today;

bool g_memoryInitialized = false;
double RangeRatio = 1.0;
double BodyRatio = 1.0;
string MemoryStatus = "";
color MemoryStatusColor = clrDarkGray;
string TwoDayPattern = "";

datetime g_lastMemoryRefresh = 0;
static datetime g_lastHandleCheck = 0;
static ENUM_TIMEFRAMES g_lastTF = PERIOD_CURRENT;

double ExtensionBaseCache[];
datetime ExtensionBaseTime[];
bool ExtensionBaseValid[];
double CachedATR1H = 0.0;
datetime LastATR1HUpdate = 0;
ulong LastHUDUpdateTime = 0;

STernaryBias CurrentTernaryBias;

CIndicatorHandle gHandleATR_M4;
CIndicatorHandle gHandleATR_1H;
CIndicatorHandle gHandleSEMAFast;
CIndicatorHandle gHandleSEMASlow;
CIndicatorHandle gHandleRSI;

double gRSIRunningSum = 0;
int gRSIWindowStart = 0;
int gRSILastCalculatedBar = -1;

bool gSEMABiasActive = false;
bool gRSITernaryActive = false;

int g_handleFailureCount = 0;
static datetime g_nextHandleCheck = 0;
static datetime g_nextRecoveryAttempt = 0;

datetime g_lastBufferBarTime = 0;
static datetime g_lastSessionStart = 0;
static datetime LastAlertBarTime = 0;

int RSITernaryState = TRIT_0;

CObjectCache gObjectCache;

int g_currentArrayCapacity = 0;



//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: FUNCTION PROTOTYPES                     |
//|                                                                  |
//+------------------------------------------------------------------+
// Core System
void ValidateHandles();
void AttemptHandleRecovery();
int  CalculateNewSize(int required);
bool ValidateInputs();

// Calculation Engines
STernaryBias CalculateSEMABias(int shift, double price);
STernaryBias CalculateRSIBiasOptimized(int shift, int rates_total);
void         CalculateRSIMAForBarOptimized(int i, int rates_total, int limit);
STernaryBias GetHybridTernaryBias(int shift, int lookback, int rates_total, double price);
bool         IsTernaryAligned(int signalDirection, int ternaryBias);
int          GetTernaryConfidenceTier(int baseTier, int ternaryConfidence);
int          CalculateZone(double extValue);
double       CalculateATRScaleFactor();
double       CalculateSessionATR(int i, const datetime &time[], const double &high[], const double &low[], const double &close[], bool forceReset);
double       CalculateFallbackATR1H(double sessionATR);
void         UpdateDeltaVolState(double sessionATR, double refATR);
void         CalculateDualMetrics(int i, double closePrice, double vwap, double atrValue, bool isAboveVWAP, double &outExtension, double &outOverextension);
void         UpdateRunningMax(double unsignedExt, double unsignedOvr, bool isAboveVWAP);

// Signal Validation
bool ValidateSniperSignal(int shift, int direction, double currentRangeRatio, bool isGray);
bool IsSignalValidated(int direction, double currentRangeRatio, bool isGray, datetime barTime);

// 3-Bar Buffer System
void InitializeCoordinationBuffer();
void StartCoordinationBuffer(int direction, double currentRangeRatio, datetime barTime);
void UpdateCoordinationBuffer(int direction, double currentRangeRatio, bool isGray, datetime barTime);
void CheckBufferReset(datetime currentBarTime);
string GetBufferStatusText();
color GetBufferStatusColor();

// Memory Module
void InitializeMemoryModule();
void UpdateTodayMemory();
void CheckMemoryRefresh();
void AnalyzeMemoryStatus(double currentPrice);
bool CheckMemoryFlip(bool isBull, int trend);

// UI & Display
void EnsureUIExists();
void InitializeDualHUD();
void UpdateDualHUD();
void UpdateSovereignDisplay(int trend, bool isBull, bool isBear, int currentZone, double ext, double ovr, bool flushBull, bool flushBear, bool contBull, bool contBear, bool memFlipBull, bool memFlipBear, int candleColor, datetime currentBarTime);
void DrawMemoryHUD();
void UpdateObservationState(bool flushBull, bool flushBear, bool contBull, bool contBear, bool memFlipBull, bool memFlipBear, int candleColor, datetime currentBarTime);
void GetObservationColors(color &obs1Color, color &obs2Color, color &obs3Color);
void CheckSnapBackAlerts(datetime currentBarTime);

// Graphics Primitives
void CreateZoneRect(string name, int x, int y, int w, int h, color clr);
void CreateLabel(string name, int x, int y, string text, color clr, int fontSize);
void CreateBackground(string name, int x, int y, int w, int h, color bg_color, ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER);

// Utilities
bool IsTradingGap(datetime t1, datetime t2);
bool IsGrayCandle(int candleColor);

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: CALCULATION ENGINES                     |
//|                                                                  |
//+------------------------------------------------------------------+
//| TERNARY BIAS FUNCTIONS                                           |
//+------------------------------------------------------------------+
STernaryBias CalculateSEMABias(int shift, double price) {
   STernaryBias bias;
   bias.ternaryValue = TRIT_0;
   bias.confidence = 0;
   bias.direction = "";
   bias.strength = 0.0;

   if(!gSEMABiasActive) {
      return bias;
   }

   double fast = SafeArrayGet(SEMAFastBuffer, shift, EMPTY_VALUE);
   double slow = SafeArrayGet(SEMASlowBuffer, shift, EMPTY_VALUE);

   if(fast == EMPTY_VALUE || slow == EMPTY_VALUE) {
      return bias;
   }

   if(fast == EMPTY_VALUE || slow == EMPTY_VALUE) {
      return bias;
   }

   if(!IS_VALID_PRICE(price)) {
      return bias;
   }   bool aboveFast = IS_GREATER(price, fast);
   bool aboveSlow = IS_GREATER(price, slow);
   bool fastAboveSlow = IS_GREATER(fast, slow);

   int priceBias = aboveSlow ? TRIT_1 : TRIT_T;
   int fastBias = aboveFast ? TRIT_1 : TRIT_T;
   int trendBias = fastAboveSlow ? TRIT_1 : TRIT_T;

   bias.ternaryValue = TernaryConsensusFast(priceBias, fastBias, trendBias);

   int agreement = 0;
   if(priceBias == bias.ternaryValue) agreement++;
   if(fastBias == bias.ternaryValue) agreement++;
   if(trendBias == bias.ternaryValue) agreement++;
   bias.confidence = MathMin(agreement, 3);

   bias.direction = (bias.ternaryValue == TRIT_1) ? "UP" :
                    (bias.ternaryValue == TRIT_T) ? "DN" : "";

   if(IS_VALID_PRICE(slow)) {
      double dist = MathAbs(price - slow) / slow;
      bias.strength = MathMin(dist * 1000, 1.0);
   }

   return bias;
}

STernaryBias CalculateRSIBiasOptimized(int shift, int rates_total) {
   STernaryBias bias;
   bias.ternaryValue = TRIT_0;
   bias.confidence = 0;
   bias.direction = "";
   bias.strength = 0.0;

   if(!gRSITernaryActive || !gHandleRSI.IsValid()) {
      return bias;
   }

   double rsi = SafeArrayGet(RSIBuffer, shift, 50.0);
   double rsiMA = SafeArrayGet(RSIMABuffer, shift, 50.0);

   if(!MathIsValidNumber(rsi) || !MathIsValidNumber(rsiMA)) {
      return bias;
   }

   if(rsi > rsiMA && rsi >= 50.0) {
      bias.ternaryValue = TRIT_1;
      bias.confidence = 2;
   }
   else if(rsi < rsiMA && rsi < 50.0) {
      bias.ternaryValue = TRIT_T;
      bias.confidence = 2;
   }
   else {
      bias.ternaryValue = TRIT_0;
      bias.confidence = 1;
   }

   bias.direction = (bias.ternaryValue == TRIT_1) ? "UP" :
                    (bias.ternaryValue == TRIT_T) ? "DN" : "";

   bias.strength = MathAbs(rsi - 50.0) / 50.0;

   return bias;
}

//+------------------------------------------------------------------+
//| v3.11 O(1) RSI Running Sum Engine - Production Ready             |
//+------------------------------------------------------------------+
void CalculateRSIMAForBarOptimized(int i, int rates_total, int limit) {
   if(i < 0 || i >= ArraySize(RSIBuffer)) return;

   // Initialize window if we are at the start or a gap occurs
   if(i == limit || gRSILastCalculatedBar < 0 || i != gRSILastCalculatedBar + 1) {
      gRSIRunningSum = 0;
      int startIdx = MathMax(0, i - InpRSIMAPeriod + 1);
      for(int j = startIdx; j <= i; j++) {
         if(j >= 0 && j < ArraySize(RSIBuffer)) {
            gRSIRunningSum += RSIBuffer[j];
         }
      }
      int windowSize = i - startIdx + 1;
      RSIMABuffer[i] = (windowSize > 0) ? gRSIRunningSum / windowSize : RSIBuffer[i];
      gRSILastCalculatedBar = i;
      return;
   }

   // O(1) Sliding Window Update - Add new bar value
   gRSIRunningSum += RSIBuffer[i];

   if(i >= InpRSIMAPeriod) {
      int idxToRemove = i - InpRSIMAPeriod;
      if(idxToRemove >= 0 && idxToRemove < ArraySize(RSIBuffer)) {
         gRSIRunningSum -= RSIBuffer[idxToRemove]; // Subtract old bar value
      }
      RSIMABuffer[i] = gRSIRunningSum / InpRSIMAPeriod;
   } else {
      RSIMABuffer[i] = gRSIRunningSum / (i + 1);
   }

   gRSILastCalculatedBar = i;
}

STernaryBias GetHybridTernaryBias(int shift, int lookback, int rates_total, double price) {
   STernaryBias bias;

   STernaryBias semaBias = CalculateSEMABias(shift, price);
   STernaryBias rsiBias = CalculateRSIBiasOptimized(shift, rates_total);

   int vwapTrend = TRIT_0;
   if(shift >= 0 && shift < rates_total) {
      int rawTrend = SafeArrayGet(VWAPTrendState, shift, 0);
      if(rawTrend == 1) vwapTrend = TRIT_1;
      else if(rawTrend == -1) vwapTrend = TRIT_T;
   }

   bias.ternaryValue = TernaryConsensusFast(semaBias.ternaryValue, vwapTrend, rsiBias.ternaryValue);

   int agreement = 0;
   if(semaBias.ternaryValue == bias.ternaryValue) agreement++;
   if(vwapTrend == bias.ternaryValue) agreement++;
   if(rsiBias.ternaryValue == bias.ternaryValue) agreement++;
   
   bias.confidence = agreement;

   bias.direction = (bias.ternaryValue == TRIT_1) ? "UP" :
                    (bias.ternaryValue == TRIT_T) ? "DN" : "";

   bias.strength = (semaBias.strength + (vwapTrend != TRIT_0 ? 0.5 : 0.0) + rsiBias.strength) / 3.0;

   RSITernaryState = rsiBias.ternaryValue;

   return bias;
}

bool IsTernaryAligned(int signalDirection, int ternaryBias) {
   if(!InpRequireTernaryAlignment) return true;
   if(ternaryBias == TRIT_0) return true;
   return (signalDirection == ternaryBias);
}

int GetTernaryConfidenceTier(int baseTier, int ternaryConfidence) {
   if(!InpEnableTernaryConfidence) return baseTier;

   if(ternaryConfidence >= 3) {
      return MathMin(baseTier + 1, 3);
   }
   if(ternaryConfidence < InpMinTernaryConfidence) {
      return MathMax(baseTier - 1, 1);
   }
   return baseTier;
}

//+----+
//| UTILITIES                    |
//+----+
bool IsTradingGap(datetime t1, datetime t2) {
   if(t2 - t1 == PeriodSeconds(_Period)) return true;
   if(!InpSkipWeekendReset) return true;
   if(t2 - t1 > InpMaxGapHours * 3600) return false;

   MqlDateTime dt1, dt2;
   TimeToStruct(t1, dt1);
   TimeToStruct(t2, dt2);

   if(dt1.day_of_week == 5 && dt2.day_of_week == 1) return false;
   if(dt1.day_of_week == 5 && dt2.day_of_week == 0) return false;
   if(dt1.day_of_week == 6) return false;

   return true;
}

int CalculateZone(double extValue) {
   double absExt = MathAbs(extValue);
   if(absExt < XUConfig::VIRGIN_THRESHOLD) return 0;
   else if(absExt < XUConfig::KING_THRESHOLD) return 2;
   else if(absExt < XUConfig::TYRANT_THRESHOLD) return 3;
   else return 4;
}

double CalculateATRScaleFactor() {
   ENUM_TIMEFRAMES currentTF = _Period;
   int currentPeriodMinutes = PeriodSeconds(currentTF) / 60;
   int m4PeriodMinutes = 4;
   if(currentPeriodMinutes <= 0) return 1.0;
   if(currentPeriodMinutes == m4PeriodMinutes) return 1.0;
   double ratio = (double)currentPeriodMinutes / (double)m4PeriodMinutes;
   double scale = MathSqrt(ratio);
   if(scale > 10.0) scale = 10.0;
   if(scale < 0.1) scale = 0.1;
   return scale;
}

bool ValidateInputs() {
   if(InpBandMultiplier <= FLOAT_EPSILON) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: BandMultiplier must be > 0");
      return false;
   }
   if(InpDevBandMultiplier <= FLOAT_EPSILON) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: DevBandMultiplier must be > 0");
      return false;
   }
   if(InpUseDynamicExt && InpExtATRFactor <= FLOAT_EPSILON) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: ExtATRFactor must be > 0");
      return false;
   }
   if(InpMaxCalcBars < 100 || InpMaxCalcBars > XUConfig::MAX_ARRAY_SIZE) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: MaxCalcBars must be 100-", XUConfig::MAX_ARRAY_SIZE);
      return false;
   }

   int availableBars = iBars(_Symbol, _Period);
   if(!InpCalculateHistory && InpMaxCalcBars > availableBars) {
      Print("XU EFFECT v" + XU_VERSION + " INFO: MaxCalcBars (", InpMaxCalcBars,
            ") > available history (", availableBars, "). This is normal - indicator will use available bars.");
   }

   if(InpTernaryLookback < 1 || InpTernaryLookback > 20) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: TernaryLookback must be 1-20");
      return false;
   }
   if(InpMinTernaryConfidence < 0 || InpMinTernaryConfidence > 3) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: MinTernaryConfidence must be 0-3");
      return false;
   }
   if(InpHUDWidth < 100 || InpHUDWidth > 1000) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: HUDWidth must be 100-1000");
      return false;
   }
   if(InpHUDBarHeight < 5 || InpHUDBarHeight > 50) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: HUDBarHeight must be 5-50");
      return false;
   }
   if(InpHUDTextSize < 6 || InpHUDTextSize > 20) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: HUDTextSize must be 6-20");
      return false;
   }
   if(InpAlertInterval < 0) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: AlertInterval must be >= 0");
      return false;
   }
   if(InpBufferMinHoldBars < 0 || InpBufferMinHoldBars > 10) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: BufferMinHoldBars must be 0-10");
      return false;
   }

   if(InpTruthThreshold <= 0 || InpLieThreshold <= 0) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: Threshold values must be > 0");
      return false;
   }
   if(InpTruthThreshold >= InpLieThreshold) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: TruthThreshold must be < LieThreshold");
      return false;
   }

   if(InpEnableSEMABias) {
      if(InpSEMAFastPeriod >= InpSEMASlowPeriod) {
         Print("XU EFFECT v" + XU_VERSION + " ERROR: SEMA Fast period must be < SEMA Slow period");
         return false;
      }
      if(InpSEMAFastPeriod < 2) {
         Print("XU EFFECT v" + XU_VERSION + " ERROR: SEMA Fast period must be >= 2");
         return false;
      }
   }

   if(InpEnableRSITernary) {
      if(InpRSIPeriod < 2) {
         Print("XU EFFECT v" + XU_VERSION + " ERROR: RSI Period must be >= 2");
         return false;
      }
      if(InpRSIMAPeriod < 2) {
         Print("XU EFFECT v" + XU_VERSION + " ERROR: RSI MA Period must be >= 2");
         return false;
      }
   }

   if(InpEnableMTFStaticATR && InpM4ATRPeriod < 2) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: M4 ATR Period must be >= 2");
      return false;
   }
   if(InpEnableDeltaVol && InpDeltaVolPeriod < 2) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: Delta Vol ATR Period must be >= 2");
      return false;
   }

   return true;
}

//+----+
//| 3-BAR COORDINATION BUFFER FUNCTIONS                    |
//+----+
void InitializeCoordinationBuffer() {
   CoordinationBuffer.bufferCount = 0;
   CoordinationBuffer.initialRangeRatio = 0;
   CoordinationBuffer.lastRangeRatio = 0;
   CoordinationBuffer.hasGrayCandle = false;
   CoordinationBuffer.signalDirection = 0;
   CoordinationBuffer.triggerBar = 0;
   CoordinationBuffer.isValid = false;
   CoordinationBuffer.holdBarsRemaining = 0;
}

void StartCoordinationBuffer(int direction, double currentRangeRatio, datetime barTime) {
   if(!InpEnable3BarBuffer) {
      CoordinationBuffer.isValid = true;
      return;
   }
   CoordinationBuffer.bufferCount = 1;
   CoordinationBuffer.initialRangeRatio = currentRangeRatio;
   CoordinationBuffer.lastRangeRatio = currentRangeRatio;
   CoordinationBuffer.hasGrayCandle = false;
   CoordinationBuffer.signalDirection = direction;
   CoordinationBuffer.triggerBar = barTime;
   CoordinationBuffer.isValid = false;
   CoordinationBuffer.holdBarsRemaining = InpBufferMinHoldBars;
}

void UpdateCoordinationBuffer(int direction, double currentRangeRatio, bool isGray, datetime barTime) {
   if(!InpEnable3BarBuffer) return;

   if(CoordinationBuffer.signalDirection != direction) {
      if(CoordinationBuffer.holdBarsRemaining > 0) {
         CoordinationBuffer.holdBarsRemaining--;
         return;
      }
      StartCoordinationBuffer(direction, currentRangeRatio, barTime);
      return;
   }

   CoordinationBuffer.holdBarsRemaining = InpBufferMinHoldBars;

   if(isGray && InpRequireCleanRecord) {
      CoordinationBuffer.hasGrayCandle = true;
   }
   bool expansionValid = true;
   if(InpRequireExpansion) {
      expansionValid = IS_GREATER(currentRangeRatio, CoordinationBuffer.lastRangeRatio);
   }
   if(expansionValid && !CoordinationBuffer.hasGrayCandle) {
      CoordinationBuffer.bufferCount++;
      CoordinationBuffer.lastRangeRatio = currentRangeRatio;
   } else if(!expansionValid && InpRequireExpansion) {
      StartCoordinationBuffer(direction, currentRangeRatio, barTime);
      return;
   }
   if(CoordinationBuffer.bufferCount >= XUConfig::BUFFER_BARS_REQUIRED) {
      CoordinationBuffer.isValid = true;
   }
}

bool IsSignalValidated(int direction, double currentRangeRatio, bool isGray, datetime barTime) {
   if(!InpEnable3BarBuffer) return true;
   if(!CoordinationBuffer.isValid) {
      if(CoordinationBuffer.bufferCount == 0 || CoordinationBuffer.signalDirection != direction) {
         StartCoordinationBuffer(direction, currentRangeRatio, barTime);
      } else {
         UpdateCoordinationBuffer(direction, currentRangeRatio, isGray, barTime);
      }
   }
   return CoordinationBuffer.isValid;
}

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: SIGNAL VALIDATION                       |
//|                                                                  |
//+------------------------------------------------------------------+
//| v3.11 REFINED SIGNAL VALIDATION                                  |
//+------------------------------------------------------------------+
bool ValidateSniperSignal(int shift, int direction, double currentRangeRatio, bool isGray) {
   // 1. Check if we are within the 3-Bar Coordination window
   if(InpEnable3BarBuffer && CoordinationBuffer.holdBarsRemaining <= 0) return false;

   // 2. Ternary Consensus Check
   if(InpRequireTernaryAlignment) {
      if(direction == 1 && CurrentTernaryBias.ternaryValue != TRIT_1) return false;
      if(direction == -1 && CurrentTernaryBias.ternaryValue != TRIT_T) return false;
   }

   // 3. Volatility Delta Check (v3.10 preserved)
   if(InpFilterSnapByDelta && CurrentDeltaVol < XUConfig::DELTA_COMPRESSION) return false;

   // 4. Expansion Requirement (v3.09 fixed)
   if(InpRequireExpansion && currentRangeRatio < 1.0) return false;

   return true;
}

void CheckBufferReset(datetime currentBarTime) {
   if(g_lastBufferBarTime == 0) {
      g_lastBufferBarTime = currentBarTime;
      g_lastSessionStart = iTime(_Symbol, PERIOD_D1, 0);
      return;
   }

   datetime currentSessionStart = iTime(_Symbol, PERIOD_D1, 0);
   if(currentSessionStart != g_lastSessionStart) {
      Print("XU EFFECT v" + XU_VERSION + ": New session detected, resetting coordination buffer");
      InitializeCoordinationBuffer();
      g_lastSessionStart = currentSessionStart;
      g_lastBufferBarTime = currentBarTime;
      return;
   }

   datetime expectedTime = g_lastBufferBarTime + PeriodSeconds(_Period);
   datetime gapThreshold = expectedTime + PeriodSeconds(_Period);

   if(InpSkipWeekendReset) {
      MqlDateTime dtLast, dtCurrent;
      TimeToStruct(g_lastBufferBarTime, dtLast);
      TimeToStruct(currentBarTime, dtCurrent);

      if(dtLast.day_of_week == 5 && dtCurrent.day_of_week == 1) {
         g_lastBufferBarTime = currentBarTime;
         return;
      }
   }

   if(currentBarTime > gapThreshold) {
      Print("XU EFFECT v" + XU_VERSION + ": Gap detected (",
            (currentBarTime - expectedTime) / PeriodSeconds(_Period),
            " bars), resetting coordination buffer");
      InitializeCoordinationBuffer();
   }

   g_lastBufferBarTime = currentBarTime;
}

string GetBufferStatusText() {
   if(!InpEnable3BarBuffer) return "";
   if(CoordinationBuffer.isValid) return " [BUFFER: VALIDATED] ";
   if(CoordinationBuffer.bufferCount == 0) return "";
   return StringFormat(" [BUFFER: %d/3] ", CoordinationBuffer.bufferCount);
}

color GetBufferStatusColor() {
   if(!InpEnable3BarBuffer) return clrDarkGray;
   if(CoordinationBuffer.isValid) return clrLime;
   if(CoordinationBuffer.hasGrayCandle) return clrOrange;
   return clrYellow;
}

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: MEMORY MODULE                           |
//|                                                                  |
//+------------------------------------------------------------------+
//| MEMORY MODULE FUNCTIONS                    |
//+------------------------------------------------------------------+
void InitializeMemoryModule() {
   if(!InpEnableMemoryModule) return;
   Yesterday.date = iTime(_Symbol, PERIOD_D1, 1);
   Yesterday.high = iHigh(_Symbol, PERIOD_D1, 1);
   Yesterday.low = iLow(_Symbol, PERIOD_D1, 1);
   Yesterday.open = iOpen(_Symbol, PERIOD_D1, 1);
   Yesterday.close = iClose(_Symbol, PERIOD_D1, 1);
   Yesterday.range = Yesterday.high - Yesterday.low;
   Yesterday.body = MathAbs(Yesterday.close - Yesterday.open);
   Yesterday.isBull = (Yesterday.close >= Yesterday.open);

   double priorDayClose = iClose(_Symbol, PERIOD_D1, 2);
   double tr1 = Yesterday.range;
   double tr2 = MathAbs(Yesterday.high - priorDayClose);
   double tr3 = MathAbs(Yesterday.low - priorDayClose);
   Yesterday.atr = MathMax(tr1, MathMax(tr2, tr3));

   UpdateTodayMemory();
   g_memoryInitialized = true;
   g_lastMemoryRefresh = iTime(_Symbol, PERIOD_D1, 0);
   Print("XU EFFECT v" + XU_VERSION + ": Memory Module initialized");
}

void UpdateTodayMemory() {
   Today.date = iTime(_Symbol, PERIOD_D1, 0);
   Today.high = iHigh(_Symbol, PERIOD_D1, 0);
   Today.low = iLow(_Symbol, PERIOD_D1, 0);
   Today.open = iOpen(_Symbol, PERIOD_D1, 0);
   Today.close = (Today.high + Today.low) / 2.0;
   Today.range = Today.high - Today.low;
   Today.body = MathAbs(Today.close - Today.open);
   Today.isBull = (SymbolInfoDouble(_Symbol, SYMBOL_BID) >= Today.open);
   if(IS_VALID_PRICE(Yesterday.range) && Yesterday.range > FLOAT_EPSILON)
      RangeRatio = Today.range / Yesterday.range;
   if(IS_VALID_PRICE(Yesterday.body) && Yesterday.body > FLOAT_EPSILON)
      BodyRatio = Today.body / Yesterday.body;
}

void CheckMemoryRefresh() {
   if(!InpEnableMemoryModule) return;
   datetime currentDate = iTime(_Symbol, PERIOD_D1, 0);
   if(currentDate != g_lastMemoryRefresh) {
      Print("XU EFFECT v" + XU_VERSION + ": New day detected - refreshing memory module");
      InitializeMemoryModule();
   }
}

void AnalyzeMemoryStatus(double currentPrice) {
   if(!g_memoryInitialized) return;
   UpdateTodayMemory();
   if(IS_GREATER(currentPrice, Yesterday.high)) {
      if(RangeRatio > XUConfig::MEMORY_BREAKOUT && IS_GREATER_EQUAL(CurrentDeltaVol, XUConfig::DELTA_EQUILIBRIUM)) {
         MemoryStatus = "BREAKING MEMORY (Confirmed)";
         MemoryStatusColor = clrLime;
      }
      else if(RangeRatio < XUConfig::MEMORY_FALSE_BREAK || IS_LESS(CurrentDeltaVol, XUConfig::DELTA_EXHAUSTED)) {
         MemoryStatus = "FALSE BREAK (Fade)";
         MemoryStatusColor = clrOrange;
      }
      else {
         MemoryStatus = "Testing PDH";
         MemoryStatusColor = clrYellow;
      }
   }
   else if(IS_LESS(currentPrice, Yesterday.low)) {
      if(RangeRatio > XUConfig::MEMORY_BREAKOUT && IS_GREATER_EQUAL(CurrentDeltaVol, XUConfig::DELTA_EQUILIBRIUM)) {
         MemoryStatus = "BREAKING MEMORY (Confirmed)";
         MemoryStatusColor = clrCrimson;
      }
      else if(RangeRatio < XUConfig::MEMORY_FALSE_BREAK || IS_LESS(CurrentDeltaVol, XUConfig::DELTA_EXHAUSTED)) {
         MemoryStatus = "FALSE BREAK (Fade)";
         MemoryStatusColor = clrOrange;
      }
      else {
         MemoryStatus = "Testing PDL";
         MemoryStatusColor = clrYellow;
      }
   }
   else if(IS_GREATER(currentPrice, Yesterday.close)) {
      MemoryStatus = "Bullish Acceptance";
      MemoryStatusColor = clrDodgerBlue;
   }
   else if(IS_LESS(currentPrice, Yesterday.close)) {
      MemoryStatus = "Bearish Acceptance";
      MemoryStatusColor = clrDeepPink;
   }
   else {
      MemoryStatus = "At Settlement";
      MemoryStatusColor = clrWhite;
   }
   bool yestBull = Yesterday.isBull;
   bool todayBull = Today.isBull;
   double currentClose = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   if(yestBull && todayBull && IS_GREATER(currentClose, Yesterday.close)) {
      TwoDayPattern = "Trend Acceleration (Bull)";
   }
   else if(!yestBull && !todayBull && IS_LESS(currentClose, Yesterday.close)) {
      TwoDayPattern = "Trend Acceleration (Bear)";
   }
   else if(yestBull && !todayBull) {
      TwoDayPattern = "Key Reversal (Bearish)";
   }
   else if(!yestBull && todayBull) {
      TwoDayPattern = "Key Reversal (Bullish)";
   }
   else if(IS_LESS(Today.range, Yesterday.range * 0.8)) {
      TwoDayPattern = "Inside Day (Squeeze)";
   }
   else {
      TwoDayPattern = "Consolidation";
   }
}

bool CheckMemoryFlip(bool isBull, int trend) {
   if(!InpEnableMemoryFlip || !g_memoryInitialized) return false;
   double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   if(isBull && !Yesterday.isBull && IS_GREATER(currentPrice, Yesterday.close) &&
      trend == 1 && IS_GREATER_EQUAL(CurrentDeltaVol, XUConfig::DELTA_EQUILIBRIUM) && IS_LESS(CurrentDeltaVol, XUConfig::DELTA_RUNNING)) {
      return true;
   }
   if(!isBull && Yesterday.isBull && IS_LESS(currentPrice, Yesterday.close) &&
      trend == -1 && IS_GREATER_EQUAL(CurrentDeltaVol, XUConfig::DELTA_EQUILIBRIUM) && IS_LESS(CurrentDeltaVol, XUConfig::DELTA_RUNNING)) {
      return true;
   }
   return false;
}

void DrawMemoryHUD() {
   if(!InpShowMemoryHUD || !g_memoryInitialized) return;
   string prefix = "XU_MEM_";
   int baseX = 10;
   int baseY = 214;
   CreateLabel(prefix + "Title", baseX, baseY, "=== MEMORY MODULE ===", clrLightGray, 10);
   CreateLabel(prefix + "Pattern", baseX, baseY + 14, "Pattern: " + TwoDayPattern, MemoryStatusColor, 9);
   string ratioText = StringFormat("RangeRatio: %.2fx | BodyRatio: %.2fx", RangeRatio, BodyRatio);
   CreateLabel(prefix + "Ratios", baseX, baseY + 26, ratioText, clrLightGray, 9);
   CreateLabel(prefix + "Status", baseX, baseY + 40, "Status: " + MemoryStatus, MemoryStatusColor, 9);
   string levelsText = StringFormat("Yest: H=%.5f L=%.5f C=%.5f", Yesterday.high, Yesterday.low, Yesterday.close);
   CreateLabel(prefix + "Levels", baseX, baseY + 54, levelsText, C'200,130,0', 9);
}

//+----+
//| SESSION-STATIC ATR FUNCTIONS                    |
//+----+
double CalculateSessionATR(int i, const datetime &time[], const double &high[],
                    const double &low[], const double &close[], bool forceReset) {
   if(i < 0 || i >= ArraySize(high) || i >= ArraySize(low) || i >= ArraySize(close)) {
      return FLOAT_EPSILON * 10;
   }

   double tr1 = high[i] - low[i];
   double tr2 = 0, tr3 = 0;

   if(i > 0 && i < ArraySize(close)) {
      tr2 = MathAbs(high[i] - close[i-1]);
      tr3 = MathAbs(low[i] - close[i-1]);
   }

   double trueRange = MathMax(tr1, MathMax(tr2, tr3));

   bool dayChange = false;
   bool sessionBreak = false;

   if(i > 0 && i < ArraySize(time)) {
      dayChange = (time[i]/86400 != time[i-1]/86400);
      sessionBreak = !IsTradingGap(time[i-1], time[i]);
   }

   bool newSession = (i == 0) || dayChange || sessionBreak || forceReset;

   if(newSession) {
      SessionTRAccum[i] = trueRange;
      SessionBarCount[i] = 1.0;
   } else if(i > 0) {
      SessionTRAccum[i] = SessionTRAccum[i-1] + trueRange;
      SessionBarCount[i] = SessionBarCount[i-1] + 1.0;
   } else {
      SessionTRAccum[i] = trueRange;
      SessionBarCount[i] = 1.0;
   }

   double barCount = SessionBarCount[i];
   double atr = (barCount > FLOAT_EPSILON) ? SessionTRAccum[i] / barCount : trueRange;
   double minATR = 5 * _Point;
   if(atr < minATR) atr = minATR;
   return atr;
}

double CalculateFallbackATR1H(double sessionATR) {
   int currentPeriodMinutes = PeriodSeconds(_Period) / 60;
   if(currentPeriodMinutes <= 0) currentPeriodMinutes = 1;
   double scaleFactor = MathSqrt((double)currentPeriodMinutes / 60.0);
   if(!IS_VALID_PRICE(scaleFactor) || scaleFactor <= FLOAT_EPSILON) scaleFactor = 1.0;
   double estimated1H_ATR = sessionATR / scaleFactor;
   if(!IS_VALID_PRICE(estimated1H_ATR) || estimated1H_ATR <= FLOAT_EPSILON) estimated1H_ATR = sessionATR;
   return estimated1H_ATR;
}

void UpdateDeltaVolState(double sessionATR, double refATR) {
   if(!g_enableDeltaVol || !IS_VALID_PRICE(refATR) || refATR <= FLOAT_EPSILON) {
      CurrentDeltaVol = 1.0;
      CurrentDeltaStatus = "DISABLED";
      CurrentDeltaColor = clrDarkGray;
      return;
   }
   ReferenceATR_1H = refATR;
   CurrentDeltaVol = (IS_VALID_PRICE(sessionATR) && sessionATR > FLOAT_EPSILON) ? sessionATR / ReferenceATR_1H : 1.0;
   if(!MathIsValidNumber(CurrentDeltaVol) || CurrentDeltaVol <= FLOAT_EPSILON) CurrentDeltaVol = 1.0;

   if(IS_LESS(CurrentDeltaVol, XUConfig::DELTA_COMPRESSION)) {
      CurrentDeltaStatus = "COMPRESSION";
      CurrentDeltaColor = clrDodgerBlue;
   }
   else if(IS_LESS_EQUAL(CurrentDeltaVol, XUConfig::DELTA_EXHAUSTED)) {
      CurrentDeltaStatus = "EXHAUSTED LIE";
      CurrentDeltaColor = clrLimeGreen;
   }
   else if(IS_LESS(CurrentDeltaVol, XUConfig::DELTA_EQUILIBRIUM)) {
      CurrentDeltaStatus = "EQUILIBRIUM";
      CurrentDeltaColor = clrWhite;
   }
   else if(IS_LESS(CurrentDeltaVol, XUConfig::DELTA_RUNNING)) {
      CurrentDeltaStatus = "RUNNING LIE";
      CurrentDeltaColor = clrYellow;
   }
   else {
      CurrentDeltaStatus = "VOLATILITY SHOCK";
      CurrentDeltaColor = clrCrimson;
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: UI & DISPLAY SYSTEM                     |
//|                                                                  |
//+------------------------------------------------------------------+
//| DUAL HUD FUNCTIONS                    |
//+------------------------------------------------------------------+
void InitializeDualHUD() {
   MaxExtensionUp = MaxExtensionDown = 0.0;
   MaxOverextensionUp = MaxOverextensionDown = 0.0;
   PreviousExtension = PreviousOverextension = 0.0;
   LastExtDisplayed = EMPTY_VALUE;
   LastOvrDisplayed = EMPTY_VALUE;
   LastStatusText = "";
   LastStratMsg = "";
}

void CalculateDualMetrics(int i, double closePrice, double vwap, double atrValue, bool isAboveVWAP,
                    double &outExtension, double &outOverextension) {
   if(!IS_VALID_PRICE(closePrice) || !IS_VALID_PRICE(vwap)) {
      outExtension = 0;
      outOverextension = 0;
      return;
   }

   double priceExt = isAboveVWAP ? (closePrice - vwap) : (vwap - closePrice);
   if(!IS_VALID_PRICE(priceExt) || priceExt < 0) priceExt = 0;

   // Dynamic EXT: Use ATR as the baseline unit instead of fixed 50.0 points
   // If configured, 100% EXT = 1.0 * ATR distance from VWAP
   double divisor = XUConfig::EXT_DIVISOR;
   if(InpUseDynamicExt && IS_VALID_PRICE(atrValue) && atrValue > FLOAT_EPSILON) {
      divisor = atrValue * InpExtATRFactor;
   }

   double unsignedExt = (priceExt / divisor) * 100.0;
   outExtension = isAboveVWAP ? unsignedExt : -unsignedExt;

   double atrDistance = atrValue * 1.5;
   if(!IS_VALID_PRICE(atrDistance) || atrDistance <= FLOAT_EPSILON) atrDistance = FLOAT_EPSILON * 10;

   double unsignedOvr = (atrDistance > FLOAT_EPSILON) ? (priceExt / atrDistance) * 100.0 : 0;

   unsignedOvr = MathMin(unsignedOvr, XUConfig::MAX_OVEREXTENSION);

   outOverextension = isAboveVWAP ? unsignedOvr : -unsignedOvr;
}

void UpdateRunningMax(double unsignedExt, double unsignedOvr, bool isAboveVWAP) {
   if(!MathIsValidNumber(unsignedExt)) unsignedExt = 0;
   if(!MathIsValidNumber(unsignedOvr)) unsignedOvr = 0;

   if(isAboveVWAP) {
      MaxExtensionUp = MathMax(unsignedExt, MaxExtensionUp * InpMaxDecayFactor);
      MaxOverextensionUp = MathMax(unsignedOvr, MaxOverextensionUp * InpMaxDecayFactor);
   } else {
      MaxExtensionDown = MathMax(unsignedExt, MaxExtensionDown * InpMaxDecayFactor);
      MaxOverextensionDown = MathMax(unsignedOvr, MaxOverextensionDown * InpMaxDecayFactor);
   }
}

void CheckSnapBackAlerts(datetime currentBarTime) {
   if(!InpSnapBackAlert) return;
   double prevExtAbs = MathAbs(PreviousExtension);
   double currExtAbs = MathAbs(CurrentExtension);
   double prevOvrAbs = MathAbs(PreviousOverextension);
   double currOvrAbs = MathAbs(CurrentOverextension);
   bool extWasTyrant = (prevExtAbs >= XUConfig::KING_THRESHOLD);
   bool extNowKing = (currExtAbs < XUConfig::KING_THRESHOLD && currExtAbs >= XUConfig::VIRGIN_THRESHOLD);
   bool ovrWasLie = (prevOvrAbs >= XUConfig::TYRANT_THRESHOLD);
   bool ovrNowStretched = (currOvrAbs < XUConfig::TYRANT_THRESHOLD && currOvrAbs >= XUConfig::KING_THRESHOLD);
   bool sameSide = (PreviousExtension * CurrentExtension > 0) || (PreviousExtension == 0);
   bool deltaFilterPass = !InpFilterSnapByDelta || (IS_LESS_EQUAL(CurrentDeltaVol, XUConfig::DELTA_EXHAUSTED));
   if((extWasTyrant && extNowKing) || (ovrWasLie && ovrNowStretched)) {
      if(sameSide && currentBarTime != LastSnapBackAlertBar && deltaFilterPass) {
         string direction = (CurrentExtension >= 0) ? "ABOVE" : "BELOW";
         string deltaInfo = "";
         if(g_enableDeltaVol) {
            deltaInfo = StringFormat(" | ΔVol %.2f (%s)", CurrentDeltaVol, CurrentDeltaStatus);
         }
         string alertMsg = StringFormat("XU EFFECT v" + XU_VERSION + " SNAP-BACK %s VWAP: EXT %+.0f%% | OVR %+.0f%%%s | %s %s",
                    direction, CurrentExtension, CurrentOverextension, deltaInfo, _Symbol, CachedTFString);
         if(InpDesktopAlert) Alert(alertMsg);
         if(InpPushNotification) SendNotification(alertMsg);
         Print("XU EFFECT v" + XU_VERSION + " Snap-Back: ", alertMsg);
         LastSnapBackAlertBar = currentBarTime;
      }
   }
   PreviousExtension = CurrentExtension;
   PreviousOverextension = CurrentOverextension;
}

//+----+
//| DUAL HUD RENDERING                    |
//+----+
void UpdateDualHUD() {
   if(!InpShowDualHUD) return;

   if(InpShowDashboardBg) {
      int bgX = InpMainBgX;
      int bgY = InpMainBgY;
      int bgW = InpMainBgW;
      int bgH = InpMainBgH;

      if(InpEnableMemoryModule && InpShowMemoryHUD && g_memoryInitialized) {
         bgH += 85;
      }

      CreateBackground("XU_Dash_BG_Main", bgX, bgY, bgW, bgH, InpDashboardBgColor);
   } else {
      ObjectDelete(0, "XU_Dash_BG_Main");
      gObjectCache.MarkDeleted("XU_Dash_BG_Main");
   }



   if(MathAbs(CurrentExtension - LastExtDisplayed) < 0.5 &&
      MathAbs(CurrentOverextension - LastOvrDisplayed) < 0.5) {
      return;
   }
   LastExtDisplayed = CurrentExtension;
   LastOvrDisplayed = CurrentOverextension;

   int hudX = 10;
   int hudY = 106;
   int halfWidth = InpHUDWidth / 2;
   int totalWidth = InpHUDWidth;
   int centerX = hudX + halfWidth;
   int barHeight = InpHUDBarHeight;

   int extVirginW = (int)(halfWidth * (XUConfig::VIRGIN_THRESHOLD / XUConfig::EXT_HUD_SCALE));
   int extKingW = (int)(halfWidth * ((XUConfig::KING_THRESHOLD - XUConfig::VIRGIN_THRESHOLD) / XUConfig::EXT_HUD_SCALE));
   int extTyrantW = halfWidth - extVirginW - extKingW;
   if(extTyrantW < 5) extTyrantW = 5;
   if(extKingW < 5) extKingW = 5;
   if(extVirginW < 5) extVirginW = 5;

   CreateZoneRect("XU_EXT_L_Tyrant", hudX, hudY + 12, extTyrantW, barHeight, C'100,0,0');
   CreateZoneRect("XU_EXT_L_King", hudX + extTyrantW, hudY + 12, extKingW, barHeight, C'160,140,0');
   CreateZoneRect("XU_EXT_L_Virgin", hudX + extTyrantW + extKingW, hudY + 12, extVirginW, barHeight, C'0,120,0');
   CreateZoneRect("XU_EXT_R_Virgin", centerX, hudY + 12, extVirginW, barHeight, C'0,120,0');
   CreateZoneRect("XU_EXT_R_King", centerX + extVirginW, hudY + 12, extKingW, barHeight, C'160,140,0');
   CreateZoneRect("XU_EXT_R_Tyrant", centerX + extVirginW + extKingW, hudY + 12, extTyrantW, barHeight, C'100,0,0');
   CreateZoneRect("XU_EXT_Center", centerX - 1, hudY + 10, 2, barHeight + 4, clrGold);

   double absExt = MathAbs(CurrentExtension);
   color extColor; string extStatus, extPsych;
   if(absExt < XUConfig::VIRGIN_THRESHOLD) {
      extColor = clrLime; extStatus = "VIRGIN"; extPsych = "Safe Discovery";
   }
   else if(absExt < XUConfig::KING_THRESHOLD) {
      extColor = clrYellow; extStatus = "KING"; extPsych = "Early FOMO";
   }
   else if(absExt < XUConfig::TYRANT_THRESHOLD) {
      extColor = clrOrange; extStatus = "TYRANT"; extPsych = "Structural Stress";
   }
   else {
      extColor = clrRed; extStatus = "LIE (3σ+)"; extPsych = "Maximum Fiction";
   }
   CreateLabel("XU_EXT_Label", hudX, hudY,
               StringFormat("EXT: %+.0f%% [%s] | %s | MAX: +%.0f%% / -%.0f%%",
               CurrentExtension, extStatus, extPsych, MaxExtensionUp, MaxExtensionDown), extColor, InpHUDTextSize);

   double extDisplay = MathMax(-XUConfig::EXT_HUD_SCALE, MathMin(XUConfig::EXT_HUD_SCALE, CurrentExtension));
   int extMarkerPos = centerX + (int)((extDisplay / XUConfig::EXT_HUD_SCALE) * halfWidth);
   extMarkerPos = MathMax(hudX, MathMin(hudX + totalWidth - 3, extMarkerPos));
   CreateZoneRect("XU_EXT_Marker", extMarkerPos, hudY + 10, 3, barHeight + 4, clrWhite);

   int ovrBaseX = 10, ovrBaseY = 135;
   int ovrCenterX = ovrBaseX + halfWidth;
   int ovrVirginW = (int)(halfWidth * (XUConfig::VIRGIN_THRESHOLD / XUConfig::OVR_HUD_SCALE));
   int ovrKingW = (int)(halfWidth * ((XUConfig::KING_THRESHOLD - XUConfig::VIRGIN_THRESHOLD) / XUConfig::OVR_HUD_SCALE));
   int ovrTyrantW = halfWidth - ovrVirginW - ovrKingW;
   if(ovrTyrantW < 5) ovrTyrantW = 5;
   if(ovrKingW < 5) ovrKingW = 5;
   if(ovrVirginW < 5) ovrVirginW = 5;

   CreateZoneRect("XU_OVR_L_Red", ovrBaseX, ovrBaseY + 12, ovrTyrantW, barHeight, C'100,0,0');
   CreateZoneRect("XU_OVR_L_Yellow", ovrBaseX + ovrTyrantW, ovrBaseY + 12, ovrKingW, barHeight, C'160,140,0');
   CreateZoneRect("XU_OVR_L_Green", ovrBaseX + ovrTyrantW + ovrKingW, ovrBaseY + 12, ovrVirginW, barHeight, C'0,120,0');
   CreateZoneRect("XU_OVR_R_Green", ovrCenterX, ovrBaseY + 12, ovrVirginW, barHeight, C'0,120,0');
   CreateZoneRect("XU_OVR_R_Yellow", ovrCenterX + ovrVirginW, ovrBaseY + 12, ovrKingW, barHeight, C'160,140,0');
   CreateZoneRect("XU_OVR_R_Red", ovrCenterX + ovrVirginW + ovrKingW, ovrBaseY + 12, ovrTyrantW, barHeight, C'100,0,0');
   CreateZoneRect("XU_OVR_Center", ovrCenterX - 1, ovrBaseY + 10, 2, barHeight + 4, clrSilver);

   double absOvr = MathAbs(CurrentOverextension);
   color ovrColor; string ovrStatus, ovrTruth;
   if(absOvr < XUConfig::VIRGIN_THRESHOLD) {
      ovrColor = clrLime; ovrStatus = "TRUTH"; ovrTruth = "Honest Move";
   }
   else if(absOvr < XUConfig::KING_THRESHOLD) {
      ovrColor = clrYellow; ovrStatus = "STRETCHED"; ovrTruth = "Structural Stress";
   }
   else if(absOvr < XUConfig::TYRANT_THRESHOLD) {
      ovrColor = clrOrange; ovrStatus = "STRESSED"; ovrTruth = "High Volatility";
   }
   else {
      ovrColor = clrRed; ovrStatus = "LIE (3σ+)"; ovrTruth = "Statistical Fiction";
   }
   CreateLabel("XU_OVR_Label", ovrBaseX, ovrBaseY,
               StringFormat("OVR: %+.0f%% [%s] | %s | MAX: +%.0f%% /-%.0f%%",
               CurrentOverextension, ovrStatus, ovrTruth, MaxOverextensionUp, MaxOverextensionDown), ovrColor, InpHUDTextSize);

   double ovrDisplay = MathMax(-XUConfig::OVR_HUD_SCALE, MathMin(XUConfig::OVR_HUD_SCALE, CurrentOverextension));
   int ovrMarkerPos = ovrCenterX + (int)((ovrDisplay / XUConfig::OVR_HUD_SCALE) * halfWidth);
   ovrMarkerPos = MathMax(ovrBaseX, MathMin(ovrBaseX + totalWidth - 3, ovrMarkerPos));
   CreateZoneRect("XU_OVR_Marker", ovrMarkerPos, ovrBaseY + 10, 3, barHeight + 4, clrWhite);

   if(g_enableDeltaVol) {
      int deltaBaseX = 10, deltaBaseY = 165;
      int deltaTotalWidth = InpHUDWidth;
      CreateZoneRect("XU_Delta_Bar", deltaBaseX, deltaBaseY + 12, deltaTotalWidth, barHeight, C'30,30,30');
      double deltaPercent = MathMin(CurrentDeltaVol / 3.0, 1.0) * 100.0;
      int deltaFilled = (int)(deltaPercent / 100.0 * deltaTotalWidth);
      if(deltaFilled > deltaTotalWidth) deltaFilled = deltaTotalWidth;
      if(deltaFilled < 0) deltaFilled = 0;
      color deltaBarColor = CurrentDeltaColor;
      if(deltaFilled > 0) {
         CreateZoneRect("XU_Delta_Marker", deltaBaseX, deltaBaseY + 12, deltaFilled, barHeight, deltaBarColor);
      }
      string deltaImplication = "";
      if(IS_LESS(CurrentDeltaVol, XUConfig::DELTA_COMPRESSION)) deltaImplication = "Vol collapse imminent";
      else if(IS_LESS_EQUAL(CurrentDeltaVol, XUConfig::DELTA_EXHAUSTED)) deltaImplication = "Snap-back probable - Strike zone";
      else if(IS_LESS(CurrentDeltaVol, XUConfig::DELTA_EQUILIBRIUM)) deltaImplication = "Normal regime";
      else if(IS_LESS(CurrentDeltaVol, XUConfig::DELTA_RUNNING)) deltaImplication = "Momentum continuation - Don't fade";
      else deltaImplication = "Extreme volatility detected";
      CreateLabel("XU_Delta_Label", deltaBaseX, deltaBaseY,
                  StringFormat("ΔVol: %.2f [%s] | %s", CurrentDeltaVol, CurrentDeltaStatus, deltaImplication),
                  CurrentDeltaColor, InpHUDTextSize);
   }

   if(InpEnableTernaryConfidence) {
      int ternaryBaseX = 90, ternaryBaseY = 197;

      string ternaryText = StringFormat("TERNARY HUD: %s (Conf: %d/3)",
                    TernaryToString(CurrentTernaryBias.ternaryValue),
                    CurrentTernaryBias.confidence);
      color ternaryClr = TernaryToColor(CurrentTernaryBias.ternaryValue);
      if(CurrentTernaryBias.confidence >= 3) {
         ternaryText = "★ " + ternaryText + " ★";
      }
      CreateLabel("XU_Ternary_Label", ternaryBaseX, ternaryBaseY, ternaryText, ternaryClr, InpHUDTextSize);
   }
}

void CreateZoneRect(string name, int x, int y, int w, int h, color clr) {
   bool exists = gObjectCache.Exists(name);

   if(!exists) {
      ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
      ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
      ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
      gObjectCache.AddEntry(name, true);
   }

   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_XSIZE, w);
   ObjectSetInteger(0, name, OBJPROP_YSIZE, h);
   ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clr);
   ObjectSetInteger(0, name, OBJPROP_BACK, false);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
   ObjectSetInteger(0, name, OBJPROP_ZORDER, 100);
}

void CreateLabel(string name, int x, int y, string text, color clr, int fontSize) {
   if(StringLen(text) == 0) text = " ";

   bool exists = gObjectCache.Exists(name);

   if(!exists) {
      ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
      ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
      ObjectSetString(0, name, OBJPROP_FONT, "Consolas");
      gObjectCache.AddEntry(name, true);
   }

   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetString(0, name, OBJPROP_TEXT, text);
   ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
   ObjectSetInteger(0, name, OBJPROP_BACK, false);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
   ObjectSetInteger(0, name, OBJPROP_ZORDER, 100);
}

void CreateBackground(string name, int x, int y, int w, int h, color bg_color, ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER) {
   bool exists = gObjectCache.Exists(name);

   if(!exists) {
      ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
      ObjectSetInteger(0, name, OBJPROP_CORNER, corner);
      ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
      gObjectCache.AddEntry(name, true);
   }

   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_XSIZE, w);
   ObjectSetInteger(0, name, OBJPROP_YSIZE, h);

   uint argbColor = ColorToARGB(bg_color, (uchar)InpDashboardOpacity);
   ObjectSetInteger(0, name, OBJPROP_BGCOLOR, argbColor);
   ObjectSetInteger(0, name, OBJPROP_BACK, false);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
   ObjectSetInteger(0, name, OBJPROP_ZORDER, 100);

   if(InpShowDashboardBorder) {
      ObjectSetInteger(0, name, OBJPROP_COLOR, InpDashboardBorderColor);
      ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
   } else {
      ObjectSetInteger(0, name, OBJPROP_COLOR, clrNONE);
   }
}

//+----+
//| DASHBOARD FUNCTIONS                    |
//+----+
void EnsureUIExists() {
   if(InpShowDashboardBg) {
      string bgName = "XU_Dash_BG_Status";
      CreateBackground(bgName, InpStatusBgX, InpStatusBgY, InpStatusBgW, InpStatusBgH, InpDashboardBgColor, CORNER_LEFT_LOWER);
   } else {
      ObjectDelete(0, "XU_Dash_BG_Status");
      gObjectCache.MarkDeleted("XU_Dash_BG_Status");
   }

   string header = "XU_Header_Main", status = "XU_Sovereign_Status";
   string strat = "XU_Strategy_Event";
   string n1 = "XU_Note_1", n2 = "XU_Note_2", n3 = "XU_Note_3";

   if(!gObjectCache.Exists(header)) {
      ObjectCreate(0, header, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, header, OBJPROP_CORNER, CORNER_LEFT_UPPER);
      ObjectSetInteger(0, header, OBJPROP_XDISTANCE, 120);
      ObjectSetInteger(0, header, OBJPROP_YDISTANCE, 10);
      ObjectSetInteger(0, header, OBJPROP_FONTSIZE, 42);
      ObjectSetString(0, header, OBJPROP_FONT, "Impact");
      ObjectSetInteger(0, header, OBJPROP_ZORDER, 100);
      gObjectCache.AddEntry(header, true);
   }

   if(!gObjectCache.Exists(strat)) {
      ObjectCreate(0, strat, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, strat, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSetInteger(0, strat, OBJPROP_XDISTANCE, 10);
      ObjectSetInteger(0, strat, OBJPROP_YDISTANCE, 45+20);
      ObjectSetInteger(0, strat, OBJPROP_FONTSIZE, 10);
      ObjectSetString(0, strat, OBJPROP_FONT, "Verdana Bold");
      ObjectSetInteger(0, strat, OBJPROP_COLOR, clrNONE);
      ObjectSetInteger(0, strat, OBJPROP_ZORDER, 100);
      gObjectCache.AddEntry(strat, true);
   }

   if(!gObjectCache.Exists(status)) {
      ObjectCreate(0, status, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, status, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSetInteger(0, status, OBJPROP_XDISTANCE, 10);
      ObjectSetInteger(0, status, OBJPROP_YDISTANCE, 65+22);
      ObjectSetInteger(0, status, OBJPROP_FONTSIZE, 11);
      ObjectSetString(0, status, OBJPROP_FONT, "Courier New");
      ObjectSetString(0, status, OBJPROP_TEXT, " [ INITIALIZING... ] ");
      ObjectSetInteger(0, status, OBJPROP_COLOR, clrDarkGray);
      ObjectSetInteger(0, status, OBJPROP_ZORDER, 100);
      gObjectCache.AddEntry(status, true);
   }

   if(!gObjectCache.Exists(n1)) {
      ObjectCreate(0, n1, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, n1, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSetInteger(0, n1, OBJPROP_XDISTANCE, 22);
      ObjectSetInteger(0, n1, OBJPROP_YDISTANCE, 125+22);
      ObjectSetInteger(0, n1, OBJPROP_FONTSIZE, 9);
      ObjectSetString(0, n1, OBJPROP_FONT, "Verdana");
      ObjectSetInteger(0, n1, OBJPROP_COLOR, clrLightSlateGray);
      ObjectSetString(0, n1, OBJPROP_TEXT, "OBS 1: MOMENTUM FLUSH [VWAP Cross + ΔVol]");
      ObjectSetInteger(0, n1, OBJPROP_ZORDER, 100);
      gObjectCache.AddEntry(n1, true);
   }

   if(!gObjectCache.Exists(n2)) {
      ObjectCreate(0, n2, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, n2, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSetInteger(0, n2, OBJPROP_XDISTANCE, 22);
      ObjectSetInteger(0, n2, OBJPROP_YDISTANCE, 107+22);
      ObjectSetInteger(0, n2, OBJPROP_FONTSIZE, 9);
      ObjectSetString(0, n2, OBJPROP_FONT, "Verdana");
      ObjectSetInteger(0, n2, OBJPROP_COLOR, clrLightSlateGray);
      ObjectSetString(0, n2, OBJPROP_TEXT, "OBS 2: CONTINUATION [VWAP Hold + Extension]");
      ObjectSetInteger(0, n2, OBJPROP_ZORDER, 100);
      gObjectCache.AddEntry(n2, true);
   }

   if(!gObjectCache.Exists(n3)) {
      ObjectCreate(0, n3, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, n3, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSetInteger(0, n3, OBJPROP_XDISTANCE, 22);
      ObjectSetInteger(0, n3, OBJPROP_YDISTANCE, 89+22);
      ObjectSetInteger(0, n3, OBJPROP_FONTSIZE, 9);
      ObjectSetString(0, n3, OBJPROP_FONT, "Verdana");
      ObjectSetInteger(0, n3, OBJPROP_COLOR, clrLightSlateGray);
      ObjectSetString(0, n3, OBJPROP_TEXT, "OBS 3: MEMORY FLIP [PDC Reclaim + VWAP]");
      ObjectSetInteger(0, n3, OBJPROP_ZORDER, 100);
      gObjectCache.AddEntry(n3, true);
   }

   UICreated = true;
   ChartRedraw();
}

bool IsGrayCandle(int candleColor) {
   return (candleColor == 0);
}

void UpdateObservationState(bool flushBull, bool flushBear, bool contBull, bool contBear,
                    bool memFlipBull, bool memFlipBear,
                    int candleColor, datetime currentBarTime) {
   if(IsGrayCandle(candleColor) && CurrentObservationState != 0) {
      CurrentObservationState = 0;
      ObservationTriggerBar = 0;
      InitializeCoordinationBuffer();
      return;
   }
   if(CurrentObservationState != 0) return;
   if(flushBull) {
      CurrentObservationState = 1;
      ObservationTriggerBar = currentBarTime;
   }
   else if(flushBear) {
      CurrentObservationState = 2;
      ObservationTriggerBar = currentBarTime;
   }
   else if(contBull) {
      CurrentObservationState = 3;
      ObservationTriggerBar = currentBarTime;
   }
   else if(contBear) {
      CurrentObservationState = 4;
      ObservationTriggerBar = currentBarTime;
   }
   else if(memFlipBull) {
      CurrentObservationState = 5;
      ObservationTriggerBar = currentBarTime;
   }
   else if(memFlipBear) {
      CurrentObservationState = 6;
      ObservationTriggerBar = currentBarTime;
   }
}

void GetObservationColors(color &obs1Color, color &obs2Color, color &obs3Color) {
   obs1Color = clrLightSlateGray;
   obs2Color = clrLightSlateGray;
   obs3Color = clrLightSlateGray;
   switch(CurrentObservationState) {
      case 1: obs1Color = clrDodgerBlue; break;
      case 2: obs1Color = clrDeepPink; break;
      case 3: obs2Color = clrDodgerBlue; break;
      case 4: obs2Color = clrDeepPink; break;
      case 5: obs3Color = clrDodgerBlue; break;
      case 6: obs3Color = clrDeepPink; break;
      default: break;
   }
}

void UpdateSovereignDisplay(int trend, bool isBull, bool isBear, int currentZone, double ext, double ovr,
                    bool flushBull, bool flushBear, bool contBull, bool contBear,
                    bool memFlipBull, bool memFlipBear,
                    int candleColor, datetime currentBarTime) {
   if(InpEnablePerformanceMode && InpMaxHUDUpdatesPerSecond > 0) {
      ulong currentTime = GetTickCount64();
      int maxUpdates = MathMax(InpMaxHUDUpdatesPerSecond, 1);
      ulong updateInterval = (ulong)(1000 / maxUpdates);
      if(currentTime - LastHUDUpdateTime < updateInterval) return;
      LastHUDUpdateTime = currentTime;
   }

   string header = "XU_Header_Main", name = "XU_Sovereign_Status";
   string strat = "XU_Strategy_Event";
   string n1 = "XU_Note_1", n2 = "XU_Note_2", n3 = "XU_Note_3";
   ObjectSetString(0, header, OBJPROP_TEXT, _Symbol + " " + CachedTFString);
   color hC = isBull ? clrDodgerBlue : (isBear ? clrDeepPink : clrDarkGray);
   ObjectSetInteger(0, header, OBJPROP_COLOR, hC);
   UpdateObservationState(flushBull, flushBear, contBull, contBear, memFlipBull, memFlipBear,
                    candleColor, currentBarTime);
   color obs1Color, obs2Color, obs3Color;
   GetObservationColors(obs1Color, obs2Color, obs3Color);
   ObjectSetInteger(0, n1, OBJPROP_COLOR, obs1Color);
   ObjectSetInteger(0, n2, OBJPROP_COLOR, obs2Color);
   ObjectSetInteger(0, n3, OBJPROP_COLOR, obs3Color);
   string stratMsg = "";
   color stratColor = clrNONE;
   if(IS_GREATER_EQUAL(CurrentDeltaVol, XUConfig::DELTA_RUNNING)) {
      stratMsg = "★ RUNNING LIE — DO NOT FADE ★";
      stratColor = clrRed;
   }
   else if(currentZone == 3 && IS_LESS_EQUAL(CurrentDeltaVol, XUConfig::DELTA_EXHAUSTED)) {
      stratMsg = "★ EXHAUSTED LIE — SNAP-BACK ★";
      stratColor = clrGreen;
   }
   else if((flushBull || flushBear) && IS_LESS(CurrentDeltaVol, XUConfig::DELTA_COMPRESSION)) {
      stratMsg = "★ VOLATILITY SQUEEZE — COILED SPRING ★";
      stratColor = clrAqua;
   }
   else if((contBull || contBear) && IS_GREATER(CurrentDeltaVol, XUConfig::DELTA_EXHAUSTED) && IS_LESS(CurrentDeltaVol, XUConfig::DELTA_EQUILIBRIUM)) {
      stratMsg = "★ SOVEREIGN CONTINUATION ★";
      stratColor = clrWhite;
   }
   else if((memFlipBull || memFlipBear) && g_memoryInitialized) {
      stratMsg = "★ MEMORY FLIP — INSTITUTIONAL SHIFT ★";
      stratColor = clrGold;
   }
   if(InpEnableTernaryConfidence && stratMsg == "" && CurrentTernaryBias.ternaryValue != TRIT_0) {
      if(CurrentTernaryBias.confidence >= 3) {
         stratMsg = StringFormat("★ TERNARY CONFIRMED: %s ★", TernaryToString(CurrentTernaryBias.ternaryValue));
         stratColor = TernaryToColor(CurrentTernaryBias.ternaryValue);
      }
   }
   if(stratMsg != LastStratMsg) {
      ObjectSetString(0, strat, OBJPROP_TEXT, stratMsg);
      ObjectSetInteger(0, strat, OBJPROP_COLOR, stratColor);
      LastStratMsg = stratMsg;
   }
   string state; color c;
   double absExt = MathAbs(ext);
   double absOvr = MathAbs(ovr);
   string bufferSuffix = InpEnable3BarBuffer ? GetBufferStatusText() : "";
   string ternarySuffix = "";
   if(InpEnableTernaryConfidence) {
      string ternarySymbol = (CurrentTernaryBias.ternaryValue == TRIT_1) ? "▲" :
                    (CurrentTernaryBias.ternaryValue == TRIT_T) ? "▼" : "◆";
      string rsiSymbol = (RSITernaryState == TRIT_1) ? "R+" :
                    (RSITernaryState == TRIT_T) ? "R-" : "R0";
      ternarySuffix = StringFormat(" [%s%d|%s]", ternarySymbol, CurrentTernaryBias.confidence, rsiSymbol);
   }
   if(currentZone == 0) {
      state = " [ VIRGIN TERRITORY (<0.5σ) — OBSERVE ] " + bufferSuffix + ternarySuffix;
      c = clrLime;
   }
   else if(currentZone == 1) {
      string kingStatus;
      if(absOvr < XUConfig::VIRGIN_THRESHOLD) kingStatus = " [ KING (0.5-1σ) — LEGS ] ";
      else if(absOvr < XUConfig::TYRANT_THRESHOLD) kingStatus = " [ KING (0.5-1σ) — VERIFY ] ";
      else kingStatus = " [ KING TRAP ] ";
      state = kingStatus + bufferSuffix + ternarySuffix;
      if(absOvr < XUConfig::VIRGIN_THRESHOLD) c = clrDodgerBlue;
      else c = clrYellow;
   }
   else if(currentZone == 2) {
      string tyrantStatus;
      if(absOvr < XUConfig::KING_THRESHOLD) tyrantStatus = " [ TYRANT (1-3σ) — HONEST ] ";
      else if(absOvr < XUConfig::TYRANT_THRESHOLD) tyrantStatus = " [ TYRANT (1-3σ) STRESS ] ";
      else tyrantStatus = " [ TYRANT TRAP ] ";
      state = tyrantStatus + bufferSuffix + ternarySuffix;
      if(absOvr < XUConfig::KING_THRESHOLD) c = clrOrange;
      else c = clrRed;
   }
   else {
      string deltaState = "";
      if(g_enableDeltaVol) {
         if(IS_LESS_EQUAL(CurrentDeltaVol, XUConfig::DELTA_EXHAUSTED)) deltaState = " [EXHAUSTED]";
         else if(IS_LESS(CurrentDeltaVol, XUConfig::DELTA_EQUILIBRIUM)) deltaState = "";
         else if(IS_LESS(CurrentDeltaVol, XUConfig::DELTA_RUNNING)) deltaState = " [RUNNING]";
         else deltaState = " [SHOCK]";
      }
      state = " [ LIE (≥3σ)" + deltaState + " — STATISTICAL FICTION ] " + bufferSuffix + ternarySuffix;
      c = C'200,50,50';
   }
   if(state != LastStatusText) {
      ObjectSetString(0, name, OBJPROP_TEXT, state);
      ObjectSetInteger(0, name, OBJPROP_COLOR, c);
      LastStatusText = state;
   }
   UpdateDualHUD();
   if(InpEnableMemoryModule && InpShowMemoryHUD) DrawMemoryHUD();
}

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: CORE SYSTEM                             |
//|                                                                  |
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
   if(!ValidateInputs()) return INIT_FAILED;
   g_FloatEpsilon = (StringFind(_Symbol, "JPY") >= 0) ? _Point * 2.0 : _Point * 0.5;
   g_FloatEpsilon = MathMax(g_FloatEpsilon, 1e-9);

   SetIndexBuffer(0, VwapBuffer);
   SetIndexBuffer(1, CandleOpen);
   SetIndexBuffer(2, CandleHigh);
   SetIndexBuffer(3, CandleLow);
   SetIndexBuffer(4, CandleClose);
   SetIndexBuffer(5, CandleColor, INDICATOR_COLOR_INDEX);
   SetIndexBuffer(6, VwapUpperBuffer);
   SetIndexBuffer(7, VwapLowerBuffer);
   SetIndexBuffer(8, DevBand2Upper);
   SetIndexBuffer(9, DevBand2Lower);
   SetIndexBuffer(10, pv_accum, INDICATOR_CALCULATIONS);
   SetIndexBuffer(11, v_accum, INDICATOR_CALCULATIONS);
   SetIndexBuffer(12, price_sq_accum, INDICATOR_CALCULATIONS);
   SetIndexBuffer(13, SessionTRAccum, INDICATOR_CALCULATIONS);
   SetIndexBuffer(14, SessionATR, INDICATOR_CALCULATIONS);
   SetIndexBuffer(15, SessionBarCount, INDICATOR_CALCULATIONS);
   SetIndexBuffer(16, RSIBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(17, RSIMABuffer, INDICATOR_CALCULATIONS);

   g_enableDeltaVol = InpEnableDeltaVol;
   g_useMTFStaticATR = InpEnableMTFStaticATR;
   g_atrScaleFactor = CalculateATRScaleFactor();

   if(g_useMTFStaticATR) {
      if(!gHandleATR_M4.CreateATR(_Symbol, PERIOD_M4, InpM4ATRPeriod)) {
         Print("XU EFFECT v" + XU_VERSION + ": Failed to create M4 ATR handle. Falling back.");
         g_useMTFStaticATR = false;
      }
   }

   if(g_enableDeltaVol) {
      if(!gHandleATR_1H.CreateATR(_Symbol, PERIOD_H1, InpDeltaVolPeriod)) {
         Print("XU EFFECT v" + XU_VERSION + ": Failed to create 1H ATR handle. Delta Vol disabled.");
         g_enableDeltaVol = false;
      }
   }

   gSEMABiasActive = false;
   if(InpEnableSEMABias) {
      if(!gHandleSEMAFast.CreateMA(_Symbol, _Period, InpSEMAFastPeriod, 0, MODE_EMA, PRICE_CLOSE) ||
         !gHandleSEMASlow.CreateMA(_Symbol, _Period, InpSEMASlowPeriod, 0, MODE_EMA, PRICE_CLOSE)) {
         Print("XU EFFECT v" + XU_VERSION + ": Failed to create SEMA handles. SEMA Bias disabled.");
         gSEMABiasActive = false;
      } else {
         gSEMABiasActive = true;
      }
   }

   gRSITernaryActive = false;
   if(InpEnableRSITernary) {
      if(!gHandleRSI.CreateRSI(_Symbol, _Period, InpRSIPeriod, PRICE_CLOSE)) {
         Print("XU EFFECT v" + XU_VERSION + ": Failed to create RSI handle. RSI Ternary disabled.");
         gRSITernaryActive = false;
      } else {
         gRSITernaryActive = true;
         gRSIRunningSum = 0;
         gRSIWindowStart = 0;
         gRSILastCalculatedBar = -1;
         Print("XU EFFECT v" + XU_VERSION + ": RSI Ternary Component initialized (O(1) optimized)");
      }
   }

   int initialSize = XUConfig::INITIAL_ARRAY_SIZE;
   g_currentArrayCapacity = initialSize;

   ArrayResize(ZoneHistory, initialSize);
   ArrayResize(VWAPTrendState, initialSize);

   if(InpEnableTernaryConfidence) {
      ArrayResize(TernaryBiasBuffer, initialSize);
      ArrayResize(TernaryConfidenceBuffer, initialSize);
   }

   if(InpEnableSEMABias) {
      ArrayResize(SEMAFastBuffer, initialSize);
      ArrayResize(SEMASlowBuffer, initialSize);
   }

   ArrayResize(ExtensionBaseCache, initialSize);
   ArrayResize(ExtensionBaseTime, initialSize);
   ArrayResize(ExtensionBaseValid, initialSize);

   ArrayResize(RSIBuffer, initialSize);
   ArrayResize(RSIMABuffer, initialSize);

   CurrentObservationState = 0;
   ObservationTriggerBar = 0;
   InitializeCoordinationBuffer();

   CachedTFString = EnumToString(_Period);
   StringReplace(CachedTFString, "PERIOD_", "");
   g_lastTF = _Period;

   InitializeDualHUD();

   if(InpEnableMemoryModule) InitializeMemoryModule();

   CurrentTernaryBias.ternaryValue = TRIT_0;
   CurrentTernaryBias.confidence = 0;
   CurrentTernaryBias.direction = "";
   CurrentTernaryBias.strength = 0.0;

   g_nextHandleCheck = TimeCurrent() + XUConfig::HANDLE_CHECK_INTERVAL_SEC;
   g_nextRecoveryAttempt = TimeCurrent() + XUConfig::HANDLE_RECOVERY_INTERVAL_SEC;
   g_handleFailureCount = 0;
   g_lastBufferBarTime = 0;
   g_lastSessionStart = 0;
   LastAlertBarTime = 0;

   gObjectCache.Clear();
   ObjectsDeleteAll(0, "XU_");
   ChartRedraw();

   Print("XU EFFECT v" + XU_VERSION + ": SIMPLIFIED EDITION loaded.");
   Print("XU EFFECT v" + XU_VERSION + ": v3.10 - Account Protection Layer REMOVED");
   Print("XU EFFECT v" + XU_VERSION + ": v3.10 - Crimson ΔVol Lockout REMOVED");
   Print("XU EFFECT v" + XU_VERSION + ": RSI MA O(1) optimization: ENABLED");
   Print("XU EFFECT v" + XU_VERSION + ": Exponential array growth: ENABLED");
   Print("XU EFFECT v" + XU_VERSION + ": Object caching system: ENABLED");
   Print("XU EFFECT v" + XU_VERSION + ": Ternary lookup tables: ENABLED");
   Print("XU EFFECT v" + XU_VERSION + ": RAII handle management: ENABLED");
   Print("XU EFFECT v" + XU_VERSION + ": All v3.09 fixes preserved");

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function - v3.11 Memory Safety           |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   // 1. Release RAII Handles
   gHandleATR_M4.Release();
   gHandleATR_1H.Release();
   gHandleSEMAFast.Release();
   gHandleSEMASlow.Release();
   gHandleRSI.Release();

   // 2. Clear Object Cache & Chart Objects
   gObjectCache.Clear();
   ObjectsDeleteAll(0, "XU_"); // Use unique prefix to avoid conflicts

   // 3. Free dynamic arrays
   ArrayFree(ZoneHistory);
   ArrayFree(VWAPTrendState);
   ArrayFree(TernaryBiasBuffer);
   ArrayFree(TernaryConfidenceBuffer);
   ArrayFree(ExtensionBaseCache);
   ArrayFree(ExtensionBaseTime);
   ArrayFree(ExtensionBaseValid);
   ArrayFree(RSIBuffer);
   ArrayFree(RSIMABuffer);
   ArrayFree(SEMAFastBuffer);
   ArrayFree(SEMASlowBuffer);

   // 4. Reset global state
   UICreated = false;
   LastStatusText = "";
   LastStratMsg = "";
   LastExtDisplayed = EMPTY_VALUE;
   LastOvrDisplayed = EMPTY_VALUE;
   CurrentObservationState = 0;
   ObservationTriggerBar = 0;
   g_memoryInitialized = false;
   InitializeCoordinationBuffer();
   gRSITernaryActive = false;
   g_currentArrayCapacity = 0;

   EventKillTimer();
   Print("XU EFFECT v" + XU_VERSION + ": System Shutdown Clean. Reason: ", reason);
}

//+------------------------------------------------------------------+
//|                                                                  |
//|                 SECTION: DATA MANAGEMENT                         |
//|                                                                  |
//+------------------------------------------------------------------+
//| Validate Handles                             |
//+------------------------------------------------------------------+
void ValidateHandles() {
   datetime now = TimeCurrent();
   if(now < g_nextHandleCheck) return;
   g_nextHandleCheck = now + XUConfig::HANDLE_CHECK_INTERVAL_SEC;

   if(g_useMTFStaticATR && gHandleATR_M4.IsValid()) {
      if(!gHandleATR_M4.Validate()) {
         g_handleFailureCount++;
         Print("XU EFFECT v" + XU_VERSION + ": M4 ATR handle validation failed (failure ", g_handleFailureCount, ")");
         if(g_handleFailureCount > 3) {
            Print("XU EFFECT v" + XU_VERSION + ": Too many handle failures, disabling MTF ATR");
            g_useMTFStaticATR = false;
         }
         gHandleATR_M4.Recover();
      }
   }

   if(g_enableDeltaVol && gHandleATR_1H.IsValid()) {
      if(!gHandleATR_1H.Validate()) {
         Print("XU EFFECT v" + XU_VERSION + ": 1H ATR handle validation failed");
         gHandleATR_1H.Recover();
      }
   }

   if(gRSITernaryActive && gHandleRSI.IsValid()) {
      if(!gHandleRSI.Validate()) {
         Print("XU EFFECT v" + XU_VERSION + ": RSI handle validation failed");
         if(!gHandleRSI.Recover()) {
            gRSITernaryActive = false;
         }
      }
   }
}

void AttemptHandleRecovery() {
   datetime now = TimeCurrent();
   if(now < g_nextRecoveryAttempt) return;
   g_nextRecoveryAttempt = now + XUConfig::HANDLE_RECOVERY_INTERVAL_SEC;

   static int recoveryPhase = 0;

   switch(recoveryPhase) {
      case 0:
         if(!g_useMTFStaticATR && InpEnableMTFStaticATR) {
            if(gHandleATR_M4.CreateATR(_Symbol, PERIOD_M4, InpM4ATRPeriod)) {
               g_useMTFStaticATR = true;
               Print("XU EFFECT v" + XU_VERSION + ": M4 ATR handle recovered successfully");
               g_handleFailureCount = 0;
            }
         }
         break;

      case 1:
         if(!g_enableDeltaVol && InpEnableDeltaVol) {
            if(gHandleATR_1H.CreateATR(_Symbol, PERIOD_H1, InpDeltaVolPeriod)) {
               g_enableDeltaVol = true;
               Print("XU EFFECT v" + XU_VERSION + ": 1H ATR handle recovered successfully");
            }
         }
         break;

      case 2:
         if(!gRSITernaryActive && InpEnableRSITernary) {
            if(gHandleRSI.CreateRSI(_Symbol, _Period, InpRSIPeriod, PRICE_CLOSE)) {
               gRSITernaryActive = true;
               gRSILastCalculatedBar = -1;
               Print("XU EFFECT v" + XU_VERSION + ": RSI handle recovered successfully");
            }
         }
         break;
   }

   recoveryPhase = (recoveryPhase + 1) % 3;
}

int CalculateNewSize(int required) {
   if(required <= g_currentArrayCapacity) return g_currentArrayCapacity;

   if(required > XUConfig::MAX_ARRAY_SIZE) {
      Print("XU EFFECT v" + XU_VERSION + " WARNING: Required size ", required, " exceeds MAX_ARRAY_SIZE");
      required = XUConfig::MAX_ARRAY_SIZE;
   }

   int newSize = (int)(g_currentArrayCapacity * XUConfig::GROWTH_FACTOR);
   if(newSize < required + 1000) newSize = required + 1000;

   if(newSize - g_currentArrayCapacity > XUConfig::MAX_GROWTH_STEP) {
      newSize = g_currentArrayCapacity + XUConfig::MAX_GROWTH_STEP;
   }

   newSize = MathMin(newSize, XUConfig::MAX_ARRAY_SIZE);
   g_currentArrayCapacity = newSize;

   return newSize;
}

//+------------------------------------------------------------------+
//| OnCalculate - Main calculation function                           |
//|                                                                   |
//| This is the core calculation function called by MetaTrader on     |
//| every tick or bar update. It calculates VWAP, deviation bands,    |
//| ATR values, RSI, ternary bias, and updates the HUD display.       |
//|                                                                   |
//| Parameters:                                                       |
//|   rates_total     - Total number of bars available                |
//|   prev_calculated - Number of bars calculated in previous call    |
//|   time[]          - Array of bar timestamps                       |
//|   open[]          - Array of open prices                          |
//|   high[]          - Array of high prices                          |
//|   low[]           - Array of low prices                           |
//|   close[]         - Array of close prices                         |
//|   tick_volume[]   - Array of tick volumes                         |
//|   volume[]        - Array of trade volumes                        |
//|   spread[]        - Array of spreads                              |
//|                                                                   |
//| Returns:                                                          |
//|   Number of bars calculated (rates_total on success)              |
//+------------------------------------------------------------------+
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[]) {

   // Validate minimum data requirement
   if(rates_total < 2) return 0;

   // Validate input array sizes match rates_total
   if(ArraySize(open) < rates_total || ArraySize(high) < rates_total ||
      ArraySize(low) < rates_total || ArraySize(close) < rates_total ||
      ArraySize(time) < rates_total || ArraySize(tick_volume) < rates_total) {
      Print("XU EFFECT v" + XU_VERSION + " ERROR: Input array size mismatch");
      return prev_calculated;
   }

   if(ArraySize(ZoneHistory) < rates_total + 1000) {
      int newSize = CalculateNewSize(rates_total + 1000);

      ArrayResize(ZoneHistory, newSize);
      ArrayResize(VWAPTrendState, newSize);
      if(InpEnableTernaryConfidence) {
         ArrayResize(TernaryBiasBuffer, newSize);
         ArrayResize(TernaryConfidenceBuffer, newSize);
      }
      if(InpEnablePerformanceMode) {
         ArrayResize(ExtensionBaseCache, newSize);
         ArrayResize(ExtensionBaseTime, newSize);
         ArrayResize(ExtensionBaseValid, newSize);
      }
      if(gRSITernaryActive) {
         ArrayResize(RSIBuffer, newSize);
         ArrayResize(RSIMABuffer, newSize);
      }
      if(gRSITernaryActive) {
         ArrayResize(RSIBuffer, newSize);
         ArrayResize(RSIMABuffer, newSize);
      }
      if(InpEnableSEMABias) {
         ArrayResize(SEMAFastBuffer, newSize);
         ArrayResize(SEMASlowBuffer, newSize);
      }
   }

   if(_Period != g_lastTF) {
      CachedTFString = EnumToString(_Period);
      StringReplace(CachedTFString, "PERIOD_", "");
      g_lastTF = _Period;
      g_atrScaleFactor = CalculateATRScaleFactor();
      gRSILastCalculatedBar = -1;
      Print("XU EFFECT v" + XU_VERSION + ": Timeframe changed to ", CachedTFString, " - recalculated scale factor");
   }

   CheckMemoryRefresh();
   ValidateHandles();
   AttemptHandleRecovery();

   if(rates_total > 0) {
      CheckBufferReset(time[rates_total - 1]);
   }

   int limit;
   if(prev_calculated == 0) {
      limit = InpCalculateHistory ? 0 : MathMax(1, rates_total - InpMaxCalcBars);
      // v3.11 UX FIX: Informational message instead of Warning
      PrintFormat("XU EFFECT v%s: Info - Processing %d bars (System optimized for O(1) performance).", XU_VERSION, limit);
      if(InpEnablePerformanceMode) {
         ArrayInitialize(ExtensionBaseValid, false);
      }
      gRSIRunningSum = 0;
      gRSIWindowStart = 0;
      gRSILastCalculatedBar = -1;
   } else {
      limit = prev_calculated - 1;
      if(limit < 0) limit = 0;
   }

   double atrM4Buffer[];
   double atr1HBuffer[];

   int atrM4Copied = 0;
   if(g_useMTFStaticATR && gHandleATR_M4.IsValid()) {
      atrM4Copied = gHandleATR_M4.CopyBufferToArray(0, 0, rates_total, atrM4Buffer);
   }

   int atr1HCopied = 0;
   if(g_enableDeltaVol && gHandleATR_1H.IsValid()) {
      atr1HCopied = gHandleATR_1H.CopyBufferToArray(0, 0, rates_total, atr1HBuffer);
   }

   // Bulk Copy optimization
   if(gSEMABiasActive) {
      if(gHandleSEMAFast.IsValid()) gHandleSEMAFast.CopyBufferToArray(0, 0, rates_total, SEMAFastBuffer);
      if(gHandleSEMASlow.IsValid()) gHandleSEMASlow.CopyBufferToArray(0, 0, rates_total, SEMASlowBuffer);
   }
   
   if(gRSITernaryActive && gHandleRSI.IsValid()) {
       CopyBuffer(gHandleRSI.GetHandle(), 0, 0, rates_total, RSIBuffer);
   }

   bool isHighTF = (PeriodSeconds(_Period) >= PeriodSeconds(PERIOD_H1));

   for(int i = limit; i < rates_total; i++) {
      if(i < 0 || i >= ArraySize(open) || i >= ArraySize(high) ||
         i >= ArraySize(low) || i >= ArraySize(close) || i >= ArraySize(time)) {
         continue;
      }

      bool dayChange = false;
      bool sessionBreak = false;

      if(i > 0) {
         dayChange = (time[i]/86400 != time[i-1]/86400);
         sessionBreak = !IsTradingGap(time[i-1], time[i]);
      }

      bool forceReset = (i == 0) || (i == limit && prev_calculated == 0);
      bool newSession = (i == 0) || dayChange || sessionBreak || forceReset;

      double typ = (high[i] + low[i] + close[i]) / 3.0;
      double vol = MathMax((double)tick_volume[i], 1.0);

      if(newSession) {
         pv_accum[i] = typ * vol;
         v_accum[i] = vol;
         price_sq_accum[i] = (typ * typ) * vol;
      } else if(i > 0) {
         pv_accum[i] = SafeArrayGet(pv_accum, i-1, 0.0) + (typ * vol);
         v_accum[i] = SafeArrayGet(v_accum, i-1, 0.0) + vol;
         price_sq_accum[i] = SafeArrayGet(price_sq_accum, i-1, 0.0) + ((typ * typ) * vol);
      } else {
         pv_accum[i] = typ * vol;
         v_accum[i] = vol;
         price_sq_accum[i] = (typ * typ) * vol;
      }

      double vwap = typ;
      double volAccum = v_accum[i];

      if(MathIsValidNumber(volAccum) && volAccum > XUConfig::VWAP_MIN_VOLUME &&
         MathIsValidNumber(pv_accum[i]) && pv_accum[i] > FLOAT_EPSILON) {
         vwap = pv_accum[i] / volAccum;
      }

      if(!MathIsValidNumber(vwap) || vwap <= FLOAT_EPSILON) {
         vwap = close[i];
      }
      if(!MathIsValidNumber(vwap) || vwap <= FLOAT_EPSILON) {
         vwap = (high[i] + low[i]) / 2.0;
      }
      if(!MathIsValidNumber(vwap) || vwap <= FLOAT_EPSILON) {
         vwap = typ;
      }

      VwapBuffer[i] = vwap;

      if(InpShowVWAPBands && MathIsValidNumber(volAccum) && volAccum > XUConfig::VWAP_MIN_VOLUME &&
         MathIsValidNumber(price_sq_accum[i])) {
         double mean_sq = price_sq_accum[i] / volAccum;
         double variance = mean_sq - (vwap * vwap);
         if(variance < 0 || !MathIsValidNumber(variance)) variance = 0;
         double std_dev = MathSqrt(variance) * InpBandMultiplier;
         VwapUpperBuffer[i] = vwap + std_dev;
         VwapLowerBuffer[i] = vwap - std_dev;

         if(InpShowDevBands2 && !isHighTF) {
            double dev2 = std_dev * InpDevBandMultiplier;
            DevBand2Upper[i] = vwap + dev2;
            DevBand2Lower[i] = vwap - dev2;
         } else {
            DevBand2Upper[i] = DevBand2Lower[i] = EMPTY_VALUE;
         }
      } else {
         VwapUpperBuffer[i] = VwapLowerBuffer[i] = EMPTY_VALUE;
         DevBand2Upper[i] = DevBand2Lower[i] = EMPTY_VALUE;
      }

      double atrValue = 0;
      if(InpUseSessionStaticATR) {
         atrValue = CalculateSessionATR(i, time, high, low, close, forceReset);
         SessionATR[i] = atrValue;
      }
      else if(g_useMTFStaticATR && atrM4Copied > 0) {
         int bufferIdx = rates_total - 1 - i;
         if(bufferIdx >= 0 && bufferIdx < atrM4Copied && IS_VALID_PRICE(atrM4Buffer[bufferIdx])) {
            atrValue = atrM4Buffer[bufferIdx] * g_atrScaleFactor;
            SessionATR[i] = atrValue;
         } else {
            atrValue = CalculateSessionATR(i, time, high, low, close, forceReset);
            SessionATR[i] = atrValue;
         }
      } else {
         double tr1 = high[i] - low[i];
         double tr2 = 0, tr3 = 0;
         if(i > 0 && i < ArraySize(close)) {
            tr2 = MathAbs(high[i] - close[i-1]);
            tr3 = MathAbs(low[i] - close[i-1]);
         }
         atrValue = MathMax(tr1, MathMax(tr2, tr3));
         double minATR = 5 * _Point;
         if(atrValue < minATR || !MathIsValidNumber(atrValue)) atrValue = minATR;
         SessionATR[i] = atrValue;
      }

      double typicalPrice = (high[i] + low[i]) / 2.0;
      if(IS_VALID_PRICE(typicalPrice) && IS_VALID_PRICE(atrValue)) {
         if(atrValue > typicalPrice * 0.5) atrValue = typicalPrice * 0.5;
      }

      double ext = 0, ovr = 0;
      if(IS_VALID_PRICE(vwap)) {
         bool isAboveVWAP = IS_GREATER(close[i], vwap);
         CalculateDualMetrics(i, close[i], vwap, atrValue, isAboveVWAP, ext, ovr);
         SafeArraySet(ZoneHistory, i, CalculateZone(ext));

         int prevTrend = (i > 0) ? SafeArrayGet(VWAPTrendState, i-1, 0) : 0;
         int currTrend = prevTrend;
         if(IS_GREATER(close[i], vwap + atrValue * 0.1)) currTrend = 1;
         else if(IS_LESS(close[i], vwap - atrValue * 0.1)) currTrend = -1;
         else currTrend = 0;
         SafeArraySet(VWAPTrendState, i, currTrend);

         if(i == rates_total - 1) {
            CurrentExtension = ext;
            CurrentOverextension = ovr;
            UpdateRunningMax(MathAbs(ext), MathAbs(ovr), isAboveVWAP);
         }
      } else {
         SafeArraySet(ZoneHistory, i, 0);
         SafeArraySet(VWAPTrendState, i, 0);
      }


      if(gRSITernaryActive && gHandleRSI.IsValid()) {
         // RSIBuffer is now pre-filled in bulk before loop
         CalculateRSIMAForBarOptimized(i, rates_total, limit);
      }

      if(InpEnableTernaryConfidence) {
         STernaryBias bias = GetHybridTernaryBias(i, InpTernaryLookback, rates_total, close[i]);
         SafeArraySet(TernaryBiasBuffer, i, bias.ternaryValue);
         SafeArraySet(TernaryConfidenceBuffer, i, bias.confidence);

         if(i == rates_total - 1) {
            CurrentTernaryBias = bias;
         }
      }

      if(g_enableDeltaVol && gHandleATR_1H.IsValid() && i == rates_total - 1) {
         double atr1H_Val = 0;
         datetime currentTime = TimeCurrent();
         if(currentTime - LastATR1HUpdate >= 60) {
            double buff[1];
            if(CopyBuffer(gHandleATR_1H.GetHandle(), 0, 0, 1, buff) > 0 && MathIsValidNumber(buff[0])) {
               CachedATR1H = buff[0];
               LastATR1HUpdate = currentTime;
            }
         }
         atr1H_Val = CachedATR1H;

         if(!IS_VALID_PRICE(atr1H_Val)) {
            atr1H_Val = CalculateFallbackATR1H(SessionATR[i]);
         }
         UpdateDeltaVolState(SessionATR[i], atr1H_Val);
      }

      CandleOpen[i] = open[i];
      CandleHigh[i] = high[i];
      CandleLow[i] = low[i];
      CandleClose[i] = close[i];

      int trend = SafeArrayGet(VWAPTrendState, i, 0);
      bool isBull = (trend == 1);
      bool isBear = (trend == -1);

      bool isUp = IS_GREATER_EQUAL(close[i], open[i]);
      bool aboveVWAP = IS_GREATER(close[i], vwap);

      if(aboveVWAP) {
         CandleColor[i] = isUp ? 1 : 0;
      } else {
         CandleColor[i] = isUp ? 0 : 2;
      }

      if(i == rates_total - 1) {
         EnsureUIExists();
         if(InpEnableMemoryModule && g_memoryInitialized) AnalyzeMemoryStatus(close[i]);

         bool flushBull = false, flushBear = false;
         bool contBull = false, contBear = false;
         bool memFlipBull = false, memFlipBear = false;

         if(i > 0) {
            int prevTrend = SafeArrayGet(VWAPTrendState, i-1, 0);
            int currTrend = SafeArrayGet(VWAPTrendState, i, 0);
            flushBull = (currTrend == 1 && prevTrend != 1 && IS_GREATER(close[i], VwapBuffer[i]));
            flushBear = (currTrend == -1 && prevTrend != -1 && IS_LESS(close[i], VwapBuffer[i]));
            contBull = (currTrend == 1 && prevTrend == 1 && IS_GREATER(close[i], VwapBuffer[i]) &&
                    MathAbs(CurrentExtension) > XUConfig::VIRGIN_THRESHOLD);
            contBear = (currTrend == -1 && prevTrend == -1 && IS_LESS(close[i], VwapBuffer[i]) &&
                    MathAbs(CurrentExtension) > XUConfig::VIRGIN_THRESHOLD);
            if(InpEnableMemoryModule) {
               memFlipBull = CheckMemoryFlip(true, currTrend);
               memFlipBear = CheckMemoryFlip(false, currTrend);
            }
         }

         int currTrend = SafeArrayGet(VWAPTrendState, i, 0);
         UpdateSovereignDisplay(currTrend, isBull, isBear, SafeArrayGet(ZoneHistory, i, 0), CurrentExtension, CurrentOverextension,
                    flushBull, flushBear, contBull, contBear, memFlipBull, memFlipBear,
                    (int)CandleColor[i], time[i]);
         CheckSnapBackAlerts(time[i]);

         int nT = isBull ? 1 : (isBear ? -1 : 0);
         bool ternaryAligned = IsTernaryAligned(nT, CurrentTernaryBias.ternaryValue);

         if(nT != 0 && nT != LastAlertTrend) {
            datetime now = TimeCurrent();
            bool timeThrottle = (InpAlertInterval > 0) && ((now - LastAlertTime) < InpAlertInterval);
            bool barThrottle = (time[i] == LastAlertBarTime);

            if(!timeThrottle && !barThrottle) {
               string deltaInfo = "";
               if(g_enableDeltaVol) deltaInfo = StringFormat(" | ΔVol %.2f (%s)", CurrentDeltaVol, CurrentDeltaStatus);
               string bufferInfo = InpEnable3BarBuffer ? GetBufferStatusText() : "";
               string ternaryInfo = "";
               if(InpEnableTernaryConfidence) {
                  string ternarySymbol = ternaryAligned ? "✓" : "✗";
                  string rsiSymbol = (RSITernaryState == TRIT_1) ? "R+" :
                    (RSITernaryState == TRIT_T) ? "R-" : "R0";
                  ternaryInfo = StringFormat(" | TERNARY %s %s|%s", ternarySymbol,
                    TernaryToString(CurrentTernaryBias.ternaryValue), rsiSymbol);
               }
               string msg = StringFormat("XU EFFECT v" + XU_VERSION + " SOVEREIGN %s | %s %s | EXT %+.0f%% OVR %+.0f%%%s%s%s",
                    (nT == 1) ? "BULLISH" : "BEARISH", _Symbol, CachedTFString,
                    CurrentExtension, CurrentOverextension, deltaInfo, bufferInfo, ternaryInfo);

               bool shouldAlert = true;
               if(InpRequireTernaryAlignment && !ternaryAligned) {
                  shouldAlert = false;
                  Print("XU EFFECT v" + XU_VERSION + ": Alert suppressed - Ternary misalignment detected");
               }

               if(InpDesktopAlert && shouldAlert) Alert(msg);
               if(InpPushNotification && shouldAlert) SendNotification(msg);
               if(InpMobileAlert && shouldAlert) SendNotification(msg);
               LastAlertTime = now;
               LastAlertBarTime = time[i];
               LastAlertTrend = nT;
            }
         }
      }
   }
   return(rates_total);
}
//+----+
//| End of XU EFFECT v3.11
//+----+


