//+------------------------------------------------------------------+
//|                                                XU EFFECT v7.98   |
//|                                  TRIT-CLIP GENOME - A+ EDITION   |
//|                  PRODUCTION HARDENED | ATOMIC I/O | VAULT-READY|
//|                                     [ MT4 EXPERIMENTAL PORT ]    |
//+------------------------------------------------------------------+
/*
      ██╗  ██╗██╗   ██╗      ███████╗███████╗███████╗███████╗ ██████╗████████╗
      ╚██╗██╔╝██║   ██║      ██╔════╝██╔════╝██╔════╝██╔════╝██╔════╝╚══██╔══╝
       ╚███╔╝ ██║   ██║      █████╗  █████╗  █████╗  █████╗  ██║        ██║
       ██╔██╗ ██║   ██║      ██╔══╝  ██╔══╝  ██╔══╝  ██╔══╝  ██║        ██║
      ██╔╝ ██╗╚██████╔╝      ███████╗██║     ██║     ███████╗╚██████╗   ██║
      ╚═╝  ╚═╝ ╚═════╝       ╚══════╝╚═╝     ╚═╝     ╚══════╝ ╚═════╝   ╚═╝
      
      XU EFFECT v7.98 — TRIT-CLIP GENOME (Vault-Ready Edition)
      Status: PRODUCTION | HomeLAB v4.0 Certified | Coil + dH Export
      FIXED: VWAP accumulation, division by zero, file I/O, Hebbian reset
      FIXED v7.98: Adaptive deadzone, _Digits price display, timestamp logs
      MT4 PORT: 16-Buffer Custom Histogram Candles & Direct iMA polling.
*/
#property copyright "XU AI & The Cognitive Collective"
#property version   "7.98"
#property strict
#property indicator_chart_window
#property indicator_buffers 16

#property indicator_color1  clrGold          // VWAP
#property indicator_color2  clrDodgerBlue    // EMA Fast
#property indicator_color3  clrOrange        // EMA Slow
#property indicator_color4  clrWhite         // Trigger

#define MAX_BARS          5000
#define PANEL_UPDATE_SEC  1
#define JSON_UPDATE_SEC   5
#define MIN_BARS_REQUIRED 50
#define MAX_STATES        10
#define MAX_REDRAW_MS     250

input string s_core = "=== CORE SETTINGS ===";
input bool   InpShowVWAP          = true;
input int    InpEMAFast           = 11;
input int    InpEMASlow           = 13;
input int    InpTriggerPeriod     = 8;
input int    InpTriggerShift      = 5;

input string s_gen = "=== GENOME SETTINGS ===";
input bool   InpUseTRITGenome     = true;
input double InpTRITSensitivity   = 25.0;
input double InpTRITDeadZone      = 0.000001; 
input int    InpTRITMemoryPeriod  = 5;
input int    InpHebbianPeriod     = 13;
input bool   InpAutoScale         = true;
input double InpMinScale          = 1.0;
input double InpMaxScale          = 25.0;
input bool   InpUseCoilRandomization = false;

input string s_sess = "=== SESSION SETTINGS ===";
input bool   InpUseSessionReset   = true;
input int    InpMaxSessionGapHours= 4;

input string s_out = "=== OUTPUT SETTINGS ===";
input bool   InpFileOutput        = false;

input string s_head = "=== HEADER SETTINGS ===";
input bool   InpShowHeader        = true;
input int    InpHeaderFontSize    = 42;
input int    InpHeaderXOffset     = 120;
input int    InpHeaderYOffset     = 10;
input color  InpHeaderBullColor   = clrDodgerBlue;
input color  InpHeaderBearColor   = clrCrimson;
input color  InpHeaderNeutralColor= clrDarkGray;

input string s_vcd = "=== GTC VCD PANEL ===";
input bool   InpShowVCDPanel      = true;
input int    InpVCDPanelX         = 20;
input int    InpVCDPanelY         = 120;
input int    InpVCDPanelWidth     = 360;
input int    InpVCDPanelHeight    = 263;

input string s_alerts = "=== ALERTS ===";
input bool   InpUseAlerts         = true;

//--- Buffers
double VWAPBuf[];
double EMABufFast[];
double EMABufSlow[];
double TriggerBuf[];

// MT4 Candle Buffers (Bull, Bear, Neutral)
double BullWickTop[]; double BullWickBot[]; double BullBodyTop[]; double BullBodyBot[];
double BearWickTop[]; double BearWickBot[]; double BearBodyTop[]; double BearBodyBot[];
double NeutWickTop[]; double NeutWickBot[]; double NeutBodyTop[]; double NeutBodyBot[];

color g_bgColor;

//--- State structure
struct ChartState
{
    double  tritMemory;
    double  currentTritMemory;   // Live tick memory
    double  hebbianEMA;
    double  currentHebbianEMA;   // Live tick EMA
    bool    hebbianSeeded;
    datetime lastBarTime;
    string  chartID;
    double  pvAccum[];
    double  vAccum[];
    datetime lastJsonOpen;
    int     jsonHandle;
    datetime lastJsonWrite;
    double  lastJsonHebbian;
    double  lastJsonPrice;
    int     lastJsonColor;
    datetime lastPanelUpdate;
    uint    lastRedrawTick;
    string  symbol;
    int     period;
    bool    arraysAllocated;
   
    void AllocateArrays()
    {
        if(!arraysAllocated)
        {
            ArrayResize(pvAccum, MAX_BARS);
            ArrayResize(vAccum, MAX_BARS);
            ArraySetAsSeries(pvAccum, true);
            ArraySetAsSeries(vAccum, true);
            ArrayInitialize(pvAccum, 0.0);
            ArrayInitialize(vAccum, 0.0);
            arraysAllocated = true;
        }
    }
};
ChartState g_states[MAX_STATES];

string g_currentChartID;
string g_currentSymbol;
int    g_currentPeriod;
string g_tfName;
double g_symbolPoint;

//--- Colors
#define GTC_BLACK         C'10,10,12'
#define GTC_GLASS         C'25,25,35'
#define GTC_NEON_GRAYBLUE C'38,88,125'
#define GTC_NEON_CYAN     C'0,255,242'
#define GTC_NEON_RED      clrOrangeRed
#define GTC_TEXT_DIM      C'180,180,180'
#define GTC_NEON_YELLOW   C'255,255,100'
#define GTC_NEON_GREEN    clrLime
#define GTC_WHITE         C'255,255,255'

//--- Signal state
struct SignalState
{
   int      candleColor;
   int      stTernary;
   int      mtTernary;
   int      ltTernary;
   double   vwap;
   double   emaFast;
   double   emaSlow;
   double   trigger;
   double   price;
   double   hebbian;
   double   hebbian_delta;
   double   coil_tightness;
   double   coil_power;
   double   vwap_distance;
   int      trit_sum;
   datetime barTime;

   void Clear()
   {
      candleColor = 2; 
      stTernary = mtTernary = ltTernary = 0;
      vwap = emaFast = emaSlow = trigger = price = hebbian = 0.5;
      hebbian_delta = coil_tightness = coil_power = vwap_distance = 0.0;
      trit_sum = 0; 
      barTime = 0;
   }

   void Calculate(double closePrice, double vwapVal, double emaF, double emaS, 
                  double trigVal, datetime timeVal, double prevHebbian)
   {
      price = closePrice; 
      vwap = vwapVal; 
      emaFast = emaF; 
      emaSlow = emaS; 
      trigger = trigVal; 
      barTime = timeVal;
      
      mtTernary = (emaFast > emaSlow) ? 1 : (emaFast < emaSlow) ? -1 : 0;
      ltTernary = (price > vwap && vwap > 0) ? 1 : (price < vwap && vwap > 0) ? -1 : 0;
      
      double emaMid = (emaFast + emaSlow) * 0.5;
      bool aboveVWAP = (price > vwap && vwap > 0);
      bool aboveEMAMid = (price > emaMid && emaMid > 0);
      
      if(aboveVWAP && aboveEMAMid) stTernary = 1;
      else if(!aboveVWAP && !aboveEMAMid) stTernary = -1;
      else stTernary = 0;

      if(stTernary == 1) candleColor = 0;
      else if(stTernary == -1) candleColor = 1;
      else candleColor = 2;

      vwap_distance = price - vwap;
      trit_sum = stTernary + mtTernary + ltTernary;
      hebbian_delta = hebbian - prevHebbian;

      double bandWidth = MathMax(0.0001, MathAbs(trigger - vwap) * 1.8);
      double distToCenter = MathAbs(price - (trigger + vwap) * 0.5);
      
      if(bandWidth < _Point * 10)
         coil_tightness = 50.0;
      else
         coil_tightness = MathMax(0.0, MathMin(100.0, 100.0 * (1.0 - distToCenter / bandWidth)));
      
      coil_power = (coil_tightness / 100.0) * (MathAbs(hebbian - 0.5) * 2.0);
   }

   string GetActionString()
   {
      if(candleColor == 0) return "BULLISH -- BUY";
      if(candleColor == 1) return "BEARISH -- SELL";
      return "NEUTRAL -- WAIT";
   }

   string GetConsensusString()
   {
      if(stTernary == mtTernary && mtTernary == ltTernary && stTernary != 0)
         return (stTernary == 1) ? "FULL BULL" : "FULL BEAR";
      return "MIXED";
   }
};
SignalState g_currentSignal;

//--- Helper functions
string GetObjectPrefix() 
{
   return "XU98_" + IntegerToString(ChartID()) + "_";
}

string GetTFName()
{
   switch(_Period)
   {
      case PERIOD_M1:  return "M1";
      case PERIOD_M5:  return "M5";
      case PERIOD_M15: return "M15";
      case PERIOD_M30: return "M30";
      case PERIOD_H1:  return "H1";
      case PERIOD_H4:  return "H4";
      case PERIOD_D1:  return "D1";
      case PERIOD_W1:  return "W1";
      case PERIOD_MN1: return "MN1";
      default: return "M" + IntegerToString(_Period);
   }
}

string GetTimeString(datetime dt)
{
   MqlDateTime mqlTime;
   TimeToStruct(dt, mqlTime);
   return StringFormat("%02d:%02d", mqlTime.hour, mqlTime.min);
}

color StateToColor(int state)
{
   if(state == 0) return InpHeaderBullColor;
   if(state == 1) return InpHeaderBearColor;
   return InpHeaderNeutralColor;
}

int GetCandleColor(double price, double vwap, double emaFast, double emaSlow)
{
   double emaMid = (emaFast + emaSlow) * 0.5;
   bool aboveVWAP = (price > vwap && vwap > 0);
   bool aboveEMAMid = (price > emaMid && emaMid > 0);
   if(aboveVWAP && aboveEMAMid) return 0;
   if(!aboveVWAP && !aboveEMAMid) return 1;
   return 2;
}

bool IsSessionGap(datetime curr, datetime prev)
{
   if(!InpUseSessionReset) return false;
   if(InpMaxSessionGapHours <= 0) return false;
   MqlDateTime ct, pt;
   TimeToStruct(curr, ct);
   TimeToStruct(prev, pt);
   if(ct.day != pt.day || ct.mon != pt.mon || ct.year != pt.year) return true;
   if(curr - prev > InpMaxSessionGapHours * 3600) return true;
   return false;
}

double GetAdaptiveDeadZone()
{
   double point = (g_symbolPoint > 0) ? g_symbolPoint : _Point;
   double adaptive = InpTRITDeadZone * MathMax(point * 1000.0, 0.000001);
   return MathMax(adaptive, 1e-9);
}

int GetCurrentStateIndex()
{
   string chartID = _Symbol + "_" + IntegerToString(_Period) + "_" + IntegerToString(ChartID());
   g_currentChartID = chartID;
  
   for(int i = 0; i < MAX_STATES; i++)
   {
      if(g_states[i].chartID == chartID)
      {
         if(g_states[i].symbol != _Symbol || g_states[i].period != _Period)
         {
            Print("XU EFFECT v7.98: Chart ", ChartID(), " changed - Resetting state");
            g_states[i].hebbianSeeded = false;
            g_states[i].hebbianEMA = 0.0;
            g_states[i].currentHebbianEMA = 0.0;
            g_states[i].tritMemory = 0.0;
            g_states[i].currentTritMemory = 0.0;
            g_states[i].lastBarTime = 0;
            g_states[i].symbol = _Symbol;
            g_states[i].period = _Period;
            g_states[i].lastJsonWrite = 0;
            g_states[i].lastJsonColor = -1;
            g_states[i].lastJsonHebbian = -1.0;
            g_states[i].lastJsonPrice = 0.0;
            g_states[i].lastPanelUpdate = 0;
            if(g_states[i].arraysAllocated)
            {
               ArrayInitialize(g_states[i].pvAccum, 0.0);
               ArrayInitialize(g_states[i].vAccum, 0.0);
            }
         }
         return i;
      }
   }
  
   for(int i = 0; i < MAX_STATES; i++)
   {
      if(g_states[i].chartID == "")
      {
         g_states[i].chartID = chartID;
         g_states[i].symbol = _Symbol;
         g_states[i].period = _Period;
         g_states[i].tritMemory = 0.0;
         g_states[i].currentTritMemory = 0.0;
         g_states[i].hebbianEMA = 0.0;
         g_states[i].currentHebbianEMA = 0.0;
         g_states[i].hebbianSeeded = false;
         g_states[i].lastBarTime = 0;
         g_states[i].lastJsonOpen = 0;
         g_states[i].jsonHandle = INVALID_HANDLE;
         g_states[i].lastJsonWrite = 0;
         g_states[i].lastJsonColor = -1;
         g_states[i].lastJsonHebbian = -1.0;
         g_states[i].lastJsonPrice = 0.0;
         g_states[i].lastPanelUpdate = 0;
         g_states[i].lastRedrawTick = 0;
         g_states[i].arraysAllocated = false;
         g_states[i].AllocateArrays();
         return i;
      }
   }
  
   Print("XU EFFECT v7.98: State buffer full, reusing index 0");
   g_states[0].chartID = chartID;
   g_states[0].symbol = _Symbol;
   g_states[0].period = _Period;
   g_states[0].tritMemory = 0.0;
   g_states[0].currentTritMemory = 0.0;
   g_states[0].hebbianEMA = 0.0;
   g_states[0].currentHebbianEMA = 0.0;
   g_states[0].hebbianSeeded = false;
   g_states[0].lastBarTime = 0;
   g_states[0].lastJsonOpen = 0;
   g_states[0].jsonHandle = INVALID_HANDLE;
   g_states[0].lastJsonWrite = 0;
   g_states[0].lastJsonColor = -1;
   g_states[0].lastJsonHebbian = -1.0;
   g_states[0].lastJsonPrice = 0.0;
   g_states[0].lastPanelUpdate = 0;
   g_states[0].lastRedrawTick = 0;
   if(!g_states[0].arraysAllocated)
   {
      g_states[0].arraysAllocated = false;
      g_states[0].AllocateArrays();
   }
   else
   {
      ArrayInitialize(g_states[0].pvAccum, 0.0);
      ArrayInitialize(g_states[0].vAccum, 0.0);
   }
   return 0;
}

bool CreateOrUpdateLabel(string name, int x, int y, string text, string font, int size, color clr)
{
   string uniqueName = GetObjectPrefix() + name;
   if(ObjectFind(0, uniqueName) >= 0)
   {
      ObjectSetInteger(0, uniqueName, OBJPROP_XDISTANCE, x);
      ObjectSetInteger(0, uniqueName, OBJPROP_YDISTANCE, y);
      ObjectSetString(0, uniqueName, OBJPROP_TEXT, text);
      ObjectSetString(0, uniqueName, OBJPROP_FONT, font);
      ObjectSetInteger(0, uniqueName, OBJPROP_FONTSIZE, size);
      ObjectSetInteger(0, uniqueName, OBJPROP_COLOR, clr);
      return true;
   }
   if(!ObjectCreate(0, uniqueName, OBJ_LABEL, 0, 0, 0)) return false;
   ObjectSetInteger(0, uniqueName, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, uniqueName, OBJPROP_YDISTANCE, y);
   ObjectSetString(0, uniqueName, OBJPROP_TEXT, text);
   ObjectSetString(0, uniqueName, OBJPROP_FONT, font);
   ObjectSetInteger(0, uniqueName, OBJPROP_FONTSIZE, size);
   ObjectSetInteger(0, uniqueName, OBJPROP_COLOR, clr);
   ObjectSetInteger(0, uniqueName, OBJPROP_SELECTABLE, false);
   return true;
}

bool CreateOrUpdateRect(string name, int x, int y, int w, int h, color bgColor)
{
   string uniqueName = GetObjectPrefix() + name;
   if(ObjectFind(0, uniqueName) >= 0)
   {
      ObjectSetInteger(0, uniqueName, OBJPROP_XDISTANCE, x);
      ObjectSetInteger(0, uniqueName, OBJPROP_YDISTANCE, y);
      ObjectSetInteger(0, uniqueName, OBJPROP_XSIZE, w);
      ObjectSetInteger(0, uniqueName, OBJPROP_YSIZE, h);
      ObjectSetInteger(0, uniqueName, OBJPROP_BGCOLOR, bgColor);
      return true;
   }
   if(!ObjectCreate(0, uniqueName, OBJ_RECTANGLE_LABEL, 0, 0, 0)) return false;
   ObjectSetInteger(0, uniqueName, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, uniqueName, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, uniqueName, OBJPROP_XSIZE, w);
   ObjectSetInteger(0, uniqueName, OBJPROP_YSIZE, h);
   ObjectSetInteger(0, uniqueName, OBJPROP_BGCOLOR, bgColor);
   ObjectSetInteger(0, uniqueName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
   ObjectSetInteger(0, uniqueName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, uniqueName, OBJPROP_SELECTABLE, false);
   return true;
}

bool UpdateLabelOptimized(string name, string text, color clr = clrNONE)
{
   string uniqueName = GetObjectPrefix() + name;
   if(ObjectFind(0, uniqueName) < 0) return false;
   string currentText = ObjectGetString(0, uniqueName, OBJPROP_TEXT);
   if(currentText != text)
       ObjectSetString(0, uniqueName, OBJPROP_TEXT, text);
   if(clr != clrNONE)
   {
       color currentClr = (color)ObjectGetInteger(0, uniqueName, OBJPROP_COLOR);
       if(currentClr != clr)
           ObjectSetInteger(0, uniqueName, OBJPROP_COLOR, clr);
   }
   return true;
}

void DeleteAllObjects()
{
   string prefix = GetObjectPrefix();
   int total = ObjectsTotal(0, 0, -1);
   for(int i = total - 1; i >= 0; i--)
   {
      string name = ObjectName(0, i, 0, -1);
      if(StringFind(name, prefix) == 0)
         ObjectDelete(0, name);
   }
   ChartRedraw();
}

void CreateHeader()
{
   if(!InpShowHeader) return;
   string header = GetObjectPrefix() + "Header_Main";
   if(ObjectFind(0, header) >= 0) return;
   if(!ObjectCreate(0, header, OBJ_LABEL, 0, 0, 0)) return;
   ObjectSetInteger(0, header, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, header, OBJPROP_XDISTANCE, InpHeaderXOffset);
   ObjectSetInteger(0, header, OBJPROP_YDISTANCE, InpHeaderYOffset);
   ObjectSetInteger(0, header, OBJPROP_FONTSIZE, InpHeaderFontSize);
   ObjectSetString(0, header, OBJPROP_FONT, "Impact");
   ObjectSetInteger(0, header, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, header, OBJPROP_HIDDEN, true);
}

void UpdateHeader(int candleColor)
{
   if(!InpShowHeader) return;
   string header = GetObjectPrefix() + "Header_Main";
   if(ObjectFind(0, header) < 0) return;
   ObjectSetString(0, header, OBJPROP_TEXT, _Symbol + " " + g_tfName);
   ObjectSetInteger(0, header, OBJPROP_COLOR, StateToColor(candleColor));
}

void CreateVCDPanel()
{
   if(!InpShowVCDPanel) return;
   string testObj = GetObjectPrefix() + "VCD_BG";
   if(ObjectFind(0, testObj) >= 0) return;
   int x = InpVCDPanelX;
   int y = InpVCDPanelY;
   int w = InpVCDPanelWidth;
   int h = InpVCDPanelHeight;
   CreateOrUpdateRect("VCD_BG", x, y, w, h, GTC_GLASS);
   CreateOrUpdateRect("VCD_FRAME", x-1, y-1, w+2, h+2, GTC_NEON_GRAYBLUE);
   CreateOrUpdateRect("VCD_HEADER", x+2, y+2, w-4, 30, GTC_BLACK);
   CreateOrUpdateLabel("VCD_Title", x+12, y+8, "LIVE DATA STREAM // v7.98", "Arial Black", 10, GTC_NEON_GRAYBLUE);
   CreateOrUpdateLabel("VCD_Valid", x+w-55, y+10, "ATOMIC", "Arial Black", 9, GTC_NEON_GRAYBLUE);
   int lineY = y + 34;
   CreateOrUpdateRect("VCD_TOP_LINE", x+5, lineY, w-10, 1, GTC_NEON_GRAYBLUE);
   lineY += 20;
   CreateOrUpdateLabel("VCD_TF", x+12, lineY-15, "", "Arial Bold", 10, GTC_NEON_YELLOW);
   CreateOrUpdateLabel("VCD_Time", x+w-85, lineY-15, "", "Arial Bold", 9, GTC_NEON_CYAN);
   lineY += 4;
   CreateOrUpdateRect("VCD_SEP1", x+5, lineY, w-10, 1, GTC_NEON_CYAN);
   lineY += 12;
   CreateOrUpdateLabel("VCD_Candle", x+12, lineY-4, "CANDLE:", "Arial Bold", 9, GTC_WHITE);
   CreateOrUpdateLabel("VCD_CandleVal", x+85, lineY-4, "", "Arial Bold", 9, GTC_NEON_CYAN);
   CreateOrUpdateLabel("VCD_Trend", x+210, lineY-4, "TREND:", "Arial Bold", 9, GTC_WHITE);
   CreateOrUpdateLabel("VCD_TrendVal", x+270, lineY-4, "", "Arial Bold", 9, GTC_NEON_CYAN);
   lineY += 30;
   CreateOrUpdateLabel("VCD_Update", x+12, lineY-18, "LAST UPDATE:", "Arial Bold", 9, GTC_WHITE);
   CreateOrUpdateLabel("VCD_UpdateVal", x+110, lineY-18, "", "Arial Bold", 9, GTC_NEON_CYAN);
   lineY += 4;
   CreateOrUpdateRect("VCD_SEP2", x+5, lineY, w-10, 1, GTC_TEXT_DIM);
   lineY += 8;
   CreateOrUpdateLabel("VCD_Hebbian", x+15, lineY, "GENOME:", "Arial Bold", 9, GTC_WHITE);
   CreateOrUpdateLabel("VCD_HebbianVal", x+85, lineY, "", "Arial Bold", 9, GTC_NEON_CYAN);
   CreateOrUpdateLabel("VCD_Price", x+210+13, lineY, "PRICE:", "Arial Bold", 9, GTC_WHITE);
   CreateOrUpdateLabel("VCD_PriceVal", x+264+13, lineY, "", "Arial Bold", 9, GTC_NEON_CYAN);
   lineY += 28;
   CreateOrUpdateLabel("VCD_VWAP_Label", x+32, lineY-14, "VWAP:", "Arial Bold", 9, GTC_WHITE);
   CreateOrUpdateLabel("VCD_VWAP_Val", x+82, lineY-14, "", "Arial Bold", 9, GTC_TEXT_DIM);
   CreateOrUpdateLabel("VCD_VWAP_Status", x+215+12, lineY-14, "", "Arial Bold", 9, GTC_NEON_RED);
   lineY += 4;
   CreateOrUpdateRect("VCD_SEP3", x+5, lineY, w-10, 1, GTC_TEXT_DIM);
   lineY += 34;
   CreateOrUpdateLabel("VCD_Ternary", x+12, lineY-26, "TERNARY:", "Arial Bold", 9, GTC_WHITE);
   CreateOrUpdateLabel("VCD_ST", x+90, lineY-26, "ST:0", "Arial Bold", 9, GTC_TEXT_DIM);
   CreateOrUpdateLabel("VCD_MT", x+130, lineY-26, "MT:0", "Arial Bold", 9, GTC_TEXT_DIM);
   CreateOrUpdateLabel("VCD_LT", x+170, lineY-26, "LT:0", "Arial Bold", 9, GTC_TEXT_DIM);
   CreateOrUpdateLabel("VCD_Consensus", x+230, lineY-26, "", "Arial Bold", 9, GTC_TEXT_DIM);
   lineY += 4;
   CreateOrUpdateRect("VCD_SEP4", x+5, lineY-8, w-10, 1, GTC_TEXT_DIM);
   lineY -= 1;
   CreateOrUpdateLabel("VCD_Signal_Label", x+16, lineY, "TRIGGER:", "Arial Bold", 9, GTC_WHITE);
   CreateOrUpdateLabel("VCD_Signal_Status", x+204+10, lineY, "", "Arial Bold", 9, GTC_NEON_RED);
   CreateOrUpdateLabel("VCD_Signal_Val", x+82, lineY, "", "Arial Bold", 10, GTC_TEXT_DIM);
   lineY += 18;
   CreateOrUpdateLabel("VCD_Action", x+12, lineY+12, "ACTION:", "Arial Bold", 11, GTC_WHITE);
   CreateOrUpdateLabel("VCD_ActionVal", x+85, lineY+12, "", "Arial Bold", 11, GTC_NEON_CYAN);
   lineY += 4;
   CreateOrUpdateRect("VCD_BOTTOM_LINE", x+5, lineY, w-10, 1, GTC_NEON_GRAYBLUE);
   CreateOrUpdateRect("VCD_FOOTER", x+2, y+h-28, w-4, 26, GTC_BLACK);
   CreateOrUpdateLabel("VCD_Footer", x+12, y+h-22, "JSON -> HomeLAB", "Arial Bold", 8, GTC_NEON_GRAYBLUE);
   CreateOrUpdateLabel("VCD_Preset", x+258, y+h-22, "VAULT-READY", "Arial Bold", 9, GTC_NEON_GRAYBLUE);
}

void UpdateVCDPanel(SignalState &sig)
{
   if(!InpShowVCDPanel) return;
   int stateIdx = GetCurrentStateIndex();
   if(stateIdx < 0) return;
  
   datetime now = TimeCurrent();
   if(now - g_states[stateIdx].lastPanelUpdate < PANEL_UPDATE_SEC) return;
   g_states[stateIdx].lastPanelUpdate = now;
   CreateVCDPanel();
   string tfText = " " + _Symbol + " " + g_tfName + " TF STATUS";
   UpdateLabelOptimized("VCD_TF", tfText, GTC_NEON_YELLOW);
   UpdateLabelOptimized("VCD_Time", GetTimeString(now), GTC_NEON_CYAN);
   string candleText = (sig.candleColor == 0) ? "[BUY] (BULLISH)" : (sig.candleColor == 1) ? "[SELL] (BEARISH)" : "[WAIT] (NEUTRAL)";
   color candleColor = (sig.candleColor == 0) ? GTC_NEON_CYAN : (sig.candleColor == 1) ? GTC_NEON_RED : GTC_TEXT_DIM;
   UpdateLabelOptimized("VCD_CandleVal", candleText, candleColor);
   string trendText = (sig.mtTernary == 1) ? "[BULLISH]" : (sig.mtTernary == -1) ? "[BEARISH]" : "NEUTRAL";
   color trendColor = (sig.mtTernary == 1) ? GTC_NEON_CYAN : (sig.mtTernary == -1) ? GTC_NEON_RED : GTC_TEXT_DIM;
   UpdateLabelOptimized("VCD_TrendVal", trendText, trendColor);
   UpdateLabelOptimized("VCD_UpdateVal", GetTimeString(now), GTC_NEON_CYAN);
   color hebColor = (sig.hebbian > 0.7) ? GTC_NEON_GREEN : (sig.hebbian > 0.5) ? GTC_NEON_CYAN : GTC_TEXT_DIM;
   UpdateLabelOptimized("VCD_HebbianVal", StringFormat("%.4f", sig.hebbian), hebColor);
   
   UpdateLabelOptimized("VCD_PriceVal", DoubleToString(sig.price, _Digits), GTC_NEON_CYAN);
   
   string vwapStatus = (sig.ltTernary == 1) ? "[ABOVE VWAP]" : (sig.ltTernary == -1) ? "[BELOW VWAP]" : "[NO VWAP]";
   color vwapColor = (sig.ltTernary == 1) ? GTC_NEON_CYAN : (sig.ltTernary == -1) ? GTC_NEON_RED : GTC_TEXT_DIM;
   UpdateLabelOptimized("VCD_VWAP_Status", vwapStatus, vwapColor);
   UpdateLabelOptimized("VCD_VWAP_Val", DoubleToString(sig.vwap, _Digits), GTC_TEXT_DIM);
   
   UpdateLabelOptimized("VCD_ST", StringFormat("ST:%d", sig.stTernary), (sig.stTernary == 1) ? GTC_NEON_CYAN : (sig.stTernary == -1) ? GTC_NEON_RED : GTC_TEXT_DIM);
   UpdateLabelOptimized("VCD_MT", StringFormat("MT:%d", sig.mtTernary), (sig.mtTernary == 1) ? GTC_NEON_CYAN : (sig.mtTernary == -1) ? GTC_NEON_RED : GTC_TEXT_DIM);
   UpdateLabelOptimized("VCD_LT", StringFormat("LT:%d", sig.ltTernary), (sig.ltTernary == 1) ? GTC_NEON_CYAN : (sig.ltTernary == -1) ? GTC_NEON_RED : GTC_TEXT_DIM);
   
   bool consensus = (sig.stTernary == sig.mtTernary && sig.mtTernary == sig.ltTernary && sig.stTernary != 0);
   string consText = consensus ? "[CONSENSUS]" : "     [MIXED]";
   color consColor = consensus ? ((sig.stTernary == 1) ? GTC_NEON_CYAN : GTC_NEON_RED) : GTC_TEXT_DIM;
   UpdateLabelOptimized("VCD_Consensus", consText, consColor);
   
   string sigStatus = " [NO TRIGGER]";
   color sigColor = GTC_TEXT_DIM;
   string sigVal = "---";
   if(sig.trigger != EMPTY_VALUE && sig.trigger > 0)
   {
      sigStatus = (sig.price > sig.trigger) ? "[ABOVE TRIGGER]" : "[BELOW TRIGGER]";
      sigColor = (sig.price > sig.trigger) ? GTC_NEON_CYAN : GTC_NEON_RED;
      sigVal = DoubleToString(sig.trigger, _Digits);
   }
   UpdateLabelOptimized("VCD_Signal_Status", sigStatus, sigColor);
   UpdateLabelOptimized("VCD_Signal_Val", sigVal, GTC_TEXT_DIM);
   
   string actionText = (sig.candleColor == 0) ? "[BUY SIGNAL]" : (sig.candleColor == 1) ? "[SELL SIGNAL]" : "[NEUTRAL -- WAIT]";
   color actionColor = (sig.candleColor == 0) ? GTC_NEON_CYAN : (sig.candleColor == 1) ? GTC_NEON_RED : GTC_TEXT_DIM;
   UpdateLabelOptimized("VCD_ActionVal", actionText, actionColor);
   
   static bool pulse = false;
   pulse = !pulse;
   UpdateLabelOptimized("VCD_Valid", pulse ? "ATOMIC" : " SYNC", pulse ? GTC_NEON_CYAN : GTC_NEON_GRAYBLUE);
   ChartRedraw();
}

string GenerateJSON(SignalState &sig, datetime now)
{
   return StringFormat(
      "{\"version\":\"7.98\",\"symbol\":\"%s\",\"tf\":\"%s\","
      "\"hebbian\":%.4f,\"hebbian_delta\":%.6f,"
      "\"vwap\":%.*f,\"price\":%.*f,\"vwap_distance\":%.*f,"
      "\"ema_fast\":%.*f,\"ema_slow\":%.*f,\"trigger\":%.*f,"
      "\"coil_tightness\":%.2f,\"coil_power\":%.4f,"
      "\"trit_sum\":%d,"
      "\"candle_color\":%d,\"action\":\"%s\","
      "\"timestamp\":%I64d,\"st_ternary\":%d,\"mt_ternary\":%d,"
      "\"lt_ternary\":%d,\"consensus\":\"%s\",\"bar_time\":%I64d,"
      "\"derived\":{\"trit_sum\":%d,\"vwap_dist\":%.*f,\"dH\":%.6f,\"coil\":%.2f}}",
      _Symbol, g_tfName,
      sig.hebbian, sig.hebbian_delta,
      _Digits, sig.vwap, _Digits, sig.price, _Digits, sig.vwap_distance,
      _Digits, sig.emaFast, _Digits, sig.emaSlow, _Digits, sig.trigger,
      sig.coil_tightness, sig.coil_power,
      sig.trit_sum,
      sig.candleColor, sig.GetActionString(),
      (long)now, sig.stTernary, sig.mtTernary, sig.ltTernary,
      sig.GetConsensusString(), (long)sig.barTime,
      sig.trit_sum, _Digits, sig.vwap_distance, sig.hebbian_delta, sig.coil_tightness
   );
}

void WriteJSON(SignalState &sig)
{
   if(!InpFileOutput) return;
   int stateIdx = GetCurrentStateIndex();
   if(stateIdx < 0) return;
  
   datetime now = TimeCurrent();
   bool colorChanged = (sig.candleColor != g_states[stateIdx].lastJsonColor);
   bool hebbianChanged = (MathAbs(sig.hebbian - g_states[stateIdx].lastJsonHebbian) > 0.05);
   bool priceChanged = (MathAbs(sig.price - g_states[stateIdx].lastJsonPrice) > _Point * 5);
   bool timeElapsed = (now - g_states[stateIdx].lastJsonWrite >= JSON_UPDATE_SEC);
   
   if(!timeElapsed && !colorChanged && !hebbianChanged && !priceChanged) return;

   g_states[stateIdx].lastJsonWrite = now;
   g_states[stateIdx].lastJsonColor = sig.candleColor;
   g_states[stateIdx].lastJsonHebbian = sig.hebbian;
   g_states[stateIdx].lastJsonPrice = sig.price;

   string json = GenerateJSON(sig, now);
   
   string cleanSymbol = _Symbol;
   StringReplace(cleanSymbol, "/", "");
   StringReplace(cleanSymbol, "\\", "");
   StringReplace(cleanSymbol, ":", "");
   StringReplace(cleanSymbol, " ", "");
   
   string baseFilename = "HomeLAB_Signal_" + cleanSymbol + "_" + g_tfName;
   string tempFilename = baseFilename + ".tmp";
   string finalFilename = baseFilename + ".json";
  
   int handle = FileOpen(tempFilename, FILE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON);
   if(handle == INVALID_HANDLE) 
   {
      Print("XU EFFECT: Failed to open temp file, error: ", GetLastError());
      return;
   }
  
   FileWriteString(handle, json);
   FileFlush(handle);
   FileClose(handle);
  
   FileDelete(finalFilename, FILE_COMMON);
  
   if(!FileMove(tempFilename, FILE_COMMON, finalFilename, FILE_REWRITE|FILE_COMMON))
   {
      handle = FileOpen(finalFilename, FILE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_COMMON);
      if(handle != INVALID_HANDLE)
      {
         FileWriteString(handle, json);
         FileFlush(handle);
         FileClose(handle);
      }
      else
      {
         Print("XU EFFECT: Fallback write failed, error: ", GetLastError());
      }
   }
   
   if(FileIsExist(tempFilename, FILE_COMMON))
      FileDelete(tempFilename, FILE_COMMON);
}

bool ValidateInputs()
{
   if(InpEMAFast <= 0 || InpEMAFast > 200) return false;
   if(InpEMASlow <= 0 || InpEMASlow > 200) return false;
   if(InpTriggerPeriod <= 0 || InpTriggerPeriod > 100) return false;
   if(InpTriggerShift < 0 || InpTriggerShift > 50) return false;
   if(InpHebbianPeriod < 1 || InpHebbianPeriod > 100) return false;
   if(InpTRITSensitivity <= 0 || InpTRITSensitivity > 100) return false;
   if(InpTRITDeadZone < 0 || InpTRITDeadZone > 0.5) return false;
   if(InpTRITMemoryPeriod < 1 || InpTRITMemoryPeriod > 100) return false;
   if(InpMinScale < 0.1 || InpMinScale > 50) return false;
   if(InpMaxScale < 0.5 || InpMaxScale > 100) return false;
   if(InpMaxSessionGapHours < 0 || InpMaxSessionGapHours > 48) return false;
   
   if(InpEMAFast >= InpEMASlow)
   {
      Print("ERROR: EMA Fast must be < EMA Slow");
      return false;
   }
   
   if(InpMinScale >= InpMaxScale)
   {
      Print("ERROR: Min Scale must be < Max Scale");
      return false;
   }
   
   return true;
}

int OnInit()
{
   Print("XU EFFECT v7.98 MT4 PORT Initializing...");
   
   g_symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   Print("XU EFFECT v7.98: Symbol ", _Symbol, " Point=", g_symbolPoint, " Digits=", _Digits);
   
   MathSrand((uint)TimeLocal());
   DeleteAllObjects();
   if(!ValidateInputs()) return INIT_PARAMETERS_INCORRECT;

   g_currentPeriod = _Period;
   g_tfName = GetTFName();
   g_currentSignal.Clear();
  
   int stateIdx = GetCurrentStateIndex();
   if(stateIdx >= 0)
   {
      g_states[stateIdx].AllocateArrays();
   }
  
   SetIndexBuffer(0, VWAPBuf); SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2, clrGold);
   SetIndexBuffer(1, EMABufFast); SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 1, clrDodgerBlue);
   SetIndexBuffer(2, EMABufSlow); SetIndexStyle(2, DRAW_LINE, STYLE_SOLID, 1, clrOrange);
   SetIndexBuffer(3, TriggerBuf); SetIndexStyle(3, DRAW_LINE, STYLE_SOLID, 2, clrWhite);
   
   SetIndexShift(3, InpTriggerShift);

   g_bgColor = (color)ChartGetInteger(ChartID(), CHART_COLOR_BACKGROUND);

   // Bullish Candles (Buffers 4-7)
   SetIndexBuffer(4, BullWickTop); SetIndexStyle(4, DRAW_HISTOGRAM, STYLE_SOLID, 1, clrDodgerBlue);
   SetIndexBuffer(5, BullWickBot); SetIndexStyle(5, DRAW_HISTOGRAM, STYLE_SOLID, 1, g_bgColor);
   SetIndexBuffer(6, BullBodyTop); SetIndexStyle(6, DRAW_HISTOGRAM, STYLE_SOLID, 3, clrDodgerBlue);
   SetIndexBuffer(7, BullBodyBot); SetIndexStyle(7, DRAW_HISTOGRAM, STYLE_SOLID, 3, g_bgColor);

   // Bearish Candles (Buffers 8-11)
   SetIndexBuffer(8, BearWickTop); SetIndexStyle(8, DRAW_HISTOGRAM, STYLE_SOLID, 1, clrCrimson);
   SetIndexBuffer(9, BearWickBot); SetIndexStyle(9, DRAW_HISTOGRAM, STYLE_SOLID, 1, g_bgColor);
   SetIndexBuffer(10, BearBodyTop); SetIndexStyle(10, DRAW_HISTOGRAM, STYLE_SOLID, 3, clrCrimson);
   SetIndexBuffer(11, BearBodyBot); SetIndexStyle(11, DRAW_HISTOGRAM, STYLE_SOLID, 3, g_bgColor);

   // Neutral Candles (Buffers 12-15)
   SetIndexBuffer(12, NeutWickTop); SetIndexStyle(12, DRAW_HISTOGRAM, STYLE_SOLID, 1, clrGray);
   SetIndexBuffer(13, NeutWickBot); SetIndexStyle(13, DRAW_HISTOGRAM, STYLE_SOLID, 1, g_bgColor);
   SetIndexBuffer(14, NeutBodyTop); SetIndexStyle(14, DRAW_HISTOGRAM, STYLE_SOLID, 3, clrGray);
   SetIndexBuffer(15, NeutBodyBot); SetIndexStyle(15, DRAW_HISTOGRAM, STYLE_SOLID, 3, g_bgColor);
   
   CreateHeader();
   CreateVCDPanel();
   
   SignalState dummy;
   dummy.Clear();
   dummy.price = Bid;
   dummy.hebbian = 0.5000;
   dummy.vwap = dummy.price - 10 * _Point;
   dummy.candleColor = 2;
   UpdateVCDPanel(dummy);
   
   Print("XU EFFECT v7.98 MT4 PORT Initialized - Vault-Ready Edition");
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{
   for(int i = 0; i < MAX_STATES; i++)
   {
      if(g_states[i].jsonHandle != INVALID_HANDLE)
      {
         FileClose(g_states[i].jsonHandle);
         g_states[i].jsonHandle = INVALID_HANDLE;
      }
   }
   
   DeleteAllObjects();
   ChartRedraw();
   Print("XU Effect v7.98 UNLOADED (Reason: ", reason, ")");
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   if(rates_total < MIN_BARS_REQUIRED) return 0;
   
   ArraySetAsSeries(time, true);
   ArraySetAsSeries(open, true);
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);
   ArraySetAsSeries(close, true);
   ArraySetAsSeries(tick_volume, true);

   int stateIdx = GetCurrentStateIndex();
   if(stateIdx < 0) return 0;
  
   g_states[stateIdx].AllocateArrays();
   
   if(prev_calculated > 0 && rates_total > prev_calculated)
   {
      int shift = rates_total - prev_calculated;
      if(shift > 0 && shift < MAX_BARS)
      {
         ArrayCopy(g_states[stateIdx].pvAccum, g_states[stateIdx].pvAccum, shift, 0, MAX_BARS - shift);
         ArrayCopy(g_states[stateIdx].vAccum, g_states[stateIdx].vAccum, shift, 0, MAX_BARS - shift);
         for(int i = 0; i < shift && i < MAX_BARS; i++)
         {
            g_states[stateIdx].pvAccum[i] = 0.0;
            g_states[stateIdx].vAccum[i] = 0.0;
         }
      }
   }
  
   int limit = rates_total - prev_calculated;
   if(limit == 0) limit = 1;
   if(prev_calculated == 0)
      limit = MathMin(rates_total, MAX_BARS - 1);
  
   uint currentTick = GetTickCount();
   double adaptiveDeadzone = GetAdaptiveDeadZone();
   
   // MT4 specific Handle array population
   for(int i = limit - 1; i >= 0; i--)
   {
      if(i >= MAX_BARS - 1) continue;
      
      EMABufFast[i] = iMA(NULL, 0, InpEMAFast, 0, MODE_EMA, PRICE_CLOSE, i);
      EMABufSlow[i] = iMA(NULL, 0, InpEMASlow, 0, MODE_EMA, PRICE_CLOSE, i);
      TriggerBuf[i] = iMA(NULL, 0, InpTriggerPeriod, 0, MODE_SMMA, PRICE_CLOSE, i);

      // Default out candles
      BullWickTop[i]=EMPTY_VALUE; BullWickBot[i]=EMPTY_VALUE; BullBodyTop[i]=EMPTY_VALUE; BullBodyBot[i]=EMPTY_VALUE;
      BearWickTop[i]=EMPTY_VALUE; BearWickBot[i]=EMPTY_VALUE; BearBodyTop[i]=EMPTY_VALUE; BearBodyBot[i]=EMPTY_VALUE;
      NeutWickTop[i]=EMPTY_VALUE; NeutWickBot[i]=EMPTY_VALUE; NeutBodyTop[i]=EMPTY_VALUE; NeutBodyBot[i]=EMPTY_VALUE;
      
      // Calculate VWAP
      if(tick_volume[i] > 0)
      {
         double typicalPrice = (high[i] + low[i] + close[i]) / 3.0;
         double vol = (double)tick_volume[i];
         
         if(i == rates_total - 1 || (prev_calculated == 0 && i == limit - 1)) {
            g_states[stateIdx].pvAccum[i] = typicalPrice * vol;
            g_states[stateIdx].vAccum[i] = vol;
         } else {
            if(IsSessionGap(time[i], time[i+1])) {
               g_states[stateIdx].pvAccum[i] = typicalPrice * vol;
               g_states[stateIdx].vAccum[i] = vol;
            } else {
               g_states[stateIdx].pvAccum[i] = g_states[stateIdx].pvAccum[i+1] + typicalPrice * vol;
               g_states[stateIdx].vAccum[i] = g_states[stateIdx].vAccum[i+1] + vol;
            }
         }
         VWAPBuf[i] = (g_states[stateIdx].vAccum[i] > 0) ? g_states[stateIdx].pvAccum[i] / g_states[stateIdx].vAccum[i] : close[i];
      }
      else
      {
         VWAPBuf[i] = (i < limit - 1) ? VWAPBuf[i+1] : close[i];
      }

      // --- HISTORICAL & LIVE GENOME PROCESSING ---
      
      double emaFastVal = EMABufFast[i];
      double emaSlowVal = EMABufSlow[i];
      double triggerValue = TriggerBuf[i];
      double vwapValue = VWAPBuf[i];
      
      // Handle Live Tick Initialization
      if(i == 0)
      {
         bool isNewBar = (g_states[stateIdx].lastBarTime > 0 && time[0] != g_states[stateIdx].lastBarTime);
         if(isNewBar) {
            // Commit tick-state to historical memory on bar close
            g_states[stateIdx].hebbianEMA = g_states[stateIdx].currentHebbianEMA;
            g_states[stateIdx].tritMemory = g_states[stateIdx].currentTritMemory;
         }
      }

      double alpha = 2.0 / (InpHebbianPeriod + 1.0);
      
      // Seed values on first ever calculation
      if(!g_states[stateIdx].hebbianSeeded) {
         g_states[stateIdx].hebbianEMA = close[i];
         g_states[stateIdx].currentHebbianEMA = close[i];
         g_states[stateIdx].tritMemory = 0.0;          // FIXED: Base ratio is around 0.0, not 0.5
         g_states[stateIdx].currentTritMemory = 0.0;
         g_states[stateIdx].hebbianSeeded = true;
      }
      
      double genomeVal = 0.5;
      
      if(InpUseTRITGenome)
      {
         double T = triggerValue;
         double I = emaSlowVal;
         double tritRatio = 0.0;
         
         if(MathIsValidNumber(I) && MathIsValidNumber(T) && MathAbs(I) > 0.0000001)
         {
            double denominator = I + T;
            if(MathAbs(denominator) >= 0.0000001)
            {
               double absDiff = MathAbs(T - I);
               tritRatio = (T - I) / denominator * 2.0;
               
               if(InpAutoScale && MathAbs(tritRatio) < 0.05)
               {
                  double percentDiff = absDiff / MathAbs(I);
                  double scale = MathMin(InpMaxScale, MathMax(InpMinScale, 1.0 / (percentDiff * 100.0 + 0.0005)));
                  tritRatio *= scale;
               }
               tritRatio = MathMax(-8.0, MathMin(8.0, tritRatio));
            }
            
            double tritAlpha = 2.0 / (InpTRITMemoryPeriod + 1.0);
            
            if(i > 0) {
               // HISTORICAL BARS: Permanently update memory
               g_states[stateIdx].hebbianEMA = alpha * close[i] + (1.0 - alpha) * g_states[stateIdx].hebbianEMA;
               g_states[stateIdx].tritMemory = (tritAlpha * tritRatio) + (1.0 - tritAlpha) * g_states[stateIdx].tritMemory;
               
               double surprise = tritRatio - g_states[stateIdx].tritMemory;
               double genomeRaw = 0.5;
               if(MathAbs(surprise) > adaptiveDeadzone) genomeRaw = 0.5 + (surprise * InpTRITSensitivity);
               genomeVal = MathMax(0.0, MathMin(1.0, genomeRaw)); 
            } 
            else {
               // LIVE BAR: Update tick memory temporarily
               g_states[stateIdx].currentHebbianEMA = alpha * close[0] + (1.0 - alpha) * g_states[stateIdx].hebbianEMA;
               g_states[stateIdx].currentTritMemory = (tritAlpha * tritRatio) + (1.0 - tritAlpha) * g_states[stateIdx].tritMemory;
               
               double surprise = tritRatio - g_states[stateIdx].tritMemory;
               double genomeRaw = 0.5;
               if(MathAbs(surprise) > adaptiveDeadzone) genomeRaw = 0.5 + (surprise * InpTRITSensitivity);
               
               // Apply coil bias only on live bar for performance
               double currentCoilTightness = 50.0;
               double bandWidth = MathMax(0.0001, MathAbs(triggerValue - vwapValue) * 1.8);
               double distToCenter = MathAbs(close[0] - (triggerValue + vwapValue) * 0.5);
               
               if(bandWidth >= _Point * 10)
                  currentCoilTightness = MathMax(0.0, MathMin(100.0, 100.0 * (1.0 - distToCenter / bandWidth)));

               double coilBias = 0.0;
               if(currentCoilTightness > 50.0) {
                  coilBias = 0.62 * (genomeRaw - 0.5);
                  if(InpUseCoilRandomization) coilBias += (MathRand() % 100) * 0.0008 - 0.04;
               }
               genomeVal = MathMax(0.0, MathMin(1.0, genomeRaw + coilBias));
            }
         }
      }
      else
      {
         // Fallback Hebbian logic
         if(i > 0) {
            g_states[stateIdx].hebbianEMA = alpha * close[i] + (1.0 - alpha) * g_states[stateIdx].hebbianEMA;
            genomeVal = 0.5;
         } else {
            g_states[stateIdx].currentHebbianEMA = alpha * close[0] + (1.0 - alpha) * g_states[stateIdx].hebbianEMA;
            if(g_states[stateIdx].hebbianEMA > 0) {
               double diffVal = (close[0] - g_states[stateIdx].hebbianEMA) / g_states[stateIdx].hebbianEMA;
               genomeVal = MathMax(0.0, MathMin(1.0, 0.5 + (diffVal * InpTRITSensitivity * 10.0)));
            }
         }
      }
      
      // Calculate signal based on history or live tick
      double prevHebbian = g_states[stateIdx].lastJsonHebbian > 0 ? g_states[stateIdx].lastJsonHebbian : 0.5;
      SignalState tempSignal;
      tempSignal.Clear();
      tempSignal.hebbian = genomeVal;
      tempSignal.Calculate(close[i], vwapValue, emaFastVal, emaSlowVal, triggerValue, time[i], prevHebbian);
      
      int col = tempSignal.candleColor;
      
      // Paint Candles
      double maxBody = MathMax(open[i], close[i]);
      double minBody = MathMin(open[i], close[i]);
      if(col == 0) { BullWickTop[i]=high[i]; BullWickBot[i]=low[i]; BullBodyTop[i]=maxBody; BullBodyBot[i]=minBody; }
      else if(col == 1) { BearWickTop[i]=high[i]; BearWickBot[i]=low[i]; BearBodyTop[i]=maxBody; BearBodyBot[i]=minBody; }
      else { NeutWickTop[i]=high[i]; NeutWickBot[i]=low[i]; NeutBodyTop[i]=maxBody; NeutBodyBot[i]=minBody; }
      
      // Execute live updates if we are on the current bar
      if(i == 0)
      {
         g_currentSignal = tempSignal; // Save to global for UI
         
         static int lastAlertColor = -1;
         static datetime lastAlertTime = 0;
         if(InpUseAlerts && col != lastAlertColor && lastAlertColor != -1 && time[0] != lastAlertTime)
         {
            if(col == 0) Alert(_Symbol, " [M", _Period, "] XU EFFECT: Candle color changed to Blue (BULLISH)!");
            else if(col == 1) Alert(_Symbol, " [M", _Period, "] XU EFFECT: Candle color changed to Red (BEARISH)!");
            else if(col == 2) Alert(_Symbol, " [M", _Period, "] XU EFFECT: Candle color changed to Gray (NEUTRAL)!");
            
            lastAlertColor = col;
            lastAlertTime = time[0];
         }
         if(lastAlertColor == -1) lastAlertColor = col;
         
         UpdateHeader(g_currentSignal.candleColor);
         UpdateVCDPanel(g_currentSignal);
         WriteJSON(g_currentSignal);
         
         g_states[stateIdx].lastBarTime = time[0];
      }
   }
   
   // Handle background color changes for Hollow Candles
   color currentBg = (color)ChartGetInteger(ChartID(), CHART_COLOR_BACKGROUND);
   if(currentBg != g_bgColor)
   {
      g_bgColor = currentBg;
      SetIndexStyle(5, DRAW_HISTOGRAM, STYLE_SOLID, 1, g_bgColor);
      SetIndexStyle(7, DRAW_HISTOGRAM, STYLE_SOLID, 3, g_bgColor);
      SetIndexStyle(9, DRAW_HISTOGRAM, STYLE_SOLID, 1, g_bgColor);
      SetIndexStyle(11, DRAW_HISTOGRAM, STYLE_SOLID, 3, g_bgColor);
      SetIndexStyle(13, DRAW_HISTOGRAM, STYLE_SOLID, 1, g_bgColor);
      SetIndexStyle(15, DRAW_HISTOGRAM, STYLE_SOLID, 3, g_bgColor);
   }

   if(currentTick - g_states[stateIdx].lastRedrawTick > (uint)MAX_REDRAW_MS)
   {
      ChartRedraw();
      g_states[stateIdx].lastRedrawTick = currentTick;
   }
  
   return rates_total;
}
//+------------------------------------------------------------------+