declare upper;

# =========================
# Inputs
# =========================
input showDateWindowOnly = yes;
input startDate = 20251216;  # YYYYMMDD
input endDate   = 20260128;  # YYYYMMDD

input lockLevels = yes;

input showFibLines = yes;
input showZones = yes;
input showTargets = yes;
input show78Line = yes;
input showTimeTurns = yes;
input showLabels = yes;

# Zone retracement (50% - 62%)
input zoneTopPct = 0.50;
input zoneBotPct = 0.62;

# 78.6%
input retrace78Pct = 0.786;

# Gann time turns as % of window length
input pct45  = 0.45;
input pct90  = 0.90;
input pct180 = 1.80;

# Gann PRICE multipliers of range
input showGannPrice = yes;
input showGannPriceLabels = yes;
input g45mult  = 0.25;
input g90mult  = 0.50;
input g180mult = 1.00;
input g360mult = 2.00;

# =========================
# Date window logic
# =========================
def bn = BarNumber();
def yyyymmdd = GetYYYYMMDD();
def inWin = yyyymmdd >= startDate and yyyymmdd <= endDate;

# If "date window only" = yes, plots only inside the window
def plotOK = if showDateWindowOnly then inWin else 1;

# =========================
# Swing high/low INSIDE date window
# =========================
def winHigh_raw = HighestAll(if inWin then high else Double.NaN);
def winLow_raw  = LowestAll(if inWin then low  else Double.NaN);

def winHigh = if lockLevels then HighestAll(winHigh_raw) else winHigh_raw;
def winLow  = if lockLevels then HighestAll(winLow_raw)  else winLow_raw;

def hiBar = HighestAll(if inWin and high == winHigh then bn else 0);
def loBar = HighestAll(if inWin and low  == winLow  then bn else 0);

# Direction: Low before High = bullish swing, else bearish
def isBullish = loBar < hiBar;

def rng = winHigh - winLow;

# =========================
# Fib retracement levels (NORMAL)
# =========================
# We always measure retracements from the swing:
# Bullish: from High down
# Bearish: from Low up
def fib0   = if isBullish then winHigh else winLow;
def fib236 = if isBullish then winHigh - rng * 0.236 else winLow + rng * 0.236;
def fib382 = if isBullish then winHigh - rng * 0.382 else winLow + rng * 0.382;
def fib50  = if isBullish then winHigh - rng * 0.500 else winLow + rng * 0.500;
def fib618 = if isBullish then winHigh - rng * 0.618 else winLow + rng * 0.618;
def fib786 = if isBullish then winHigh - rng * 0.786 else winLow + rng * 0.786;
def fib100 = if isBullish then winLow  else winHigh;  # opposite end of swing

# Plot the standard fib lines
plot F0   = if showFibLines and plotOK then HighestAll(fib0)   else Double.NaN;
plot F236 = if showFibLines and plotOK then HighestAll(fib236) else Double.NaN;
plot F382 = if showFibLines and plotOK then HighestAll(fib382) else Double.NaN;
plot F50  = if showFibLines and plotOK then HighestAll(fib50)  else Double.NaN;
plot F618 = if showFibLines and plotOK then HighestAll(fib618) else Double.NaN;
plot F786 = if showFibLines and plotOK then HighestAll(fib786) else Double.NaN;
plot F100 = if showFibLines and plotOK then HighestAll(fib100) else Double.NaN;

F0.SetDefaultColor(Color.GRAY);
F236.SetDefaultColor(Color.GRAY);
F382.SetDefaultColor(Color.GRAY);
F50.SetDefaultColor(Color.GRAY);
F618.SetDefaultColor(Color.GRAY);
F786.SetDefaultColor(Color.GRAY);
F100.SetDefaultColor(Color.GRAY);

F0.SetStyle(Curve.LONG_DASH);
F236.SetStyle(Curve.SHORT_DASH);
F382.SetStyle(Curve.SHORT_DASH);
F50.SetStyle(Curve.SHORT_DASH);
F618.SetStyle(Curve.SHORT_DASH);
F786.SetStyle(Curve.SHORT_DASH);
F100.SetStyle(Curve.LONG_DASH);

F0.HideBubble(); F236.HideBubble(); F382.HideBubble(); F50.HideBubble();
F618.HideBubble(); F786.HideBubble(); F100.HideBubble();

# =========================
# Your BUY/SELL zone (50–62) + targets
# =========================
def zoneHi = Max(fib50, fib618);
def zoneLo = Min(fib50, fib618);

plot BullZoneHi = if showZones and plotOK and isBullish then HighestAll(zoneHi) else Double.NaN;
plot BullZoneLo = if showZones and plotOK and isBullish then HighestAll(zoneLo) else Double.NaN;
plot BearZoneHi = if showZones and plotOK and !isBullish then HighestAll(zoneHi) else Double.NaN;
plot BearZoneLo = if showZones and plotOK and !isBullish then HighestAll(zoneLo) else Double.NaN;

BullZoneHi.SetDefaultColor(Color.GREEN);
BullZoneLo.SetDefaultColor(Color.GREEN);
BearZoneHi.SetDefaultColor(Color.RED);
BearZoneLo.SetDefaultColor(Color.RED);

AddCloud(BullZoneHi, BullZoneLo, Color.LIGHT_GREEN, Color.LIGHT_GREEN);
AddCloud(BearZoneHi, BearZoneLo, Color.LIGHT_RED, Color.LIGHT_RED);

# Your “trigger” logic (same as before)
def trigger = if isBullish then zoneLo else zoneHi;

def T62_val  = if isBullish then trigger + rng * 0.618 else trigger - rng * 0.618;
def T78_val  = if isBullish then trigger + rng * 0.786 else trigger - rng * 0.786;
def T100_val = if isBullish then trigger + rng * 1.000 else trigger - rng * 1.000;

plot Target62  = if showTargets and plotOK then HighestAll(T62_val)  else Double.NaN;
plot Target78  = if showTargets and plotOK then HighestAll(T78_val)  else Double.NaN;
plot Target100 = if showTargets and plotOK then HighestAll(T100_val) else Double.NaN;

Target62.SetDefaultColor(Color.BLUE);  Target62.SetLineWeight(2);
Target78.SetDefaultColor(Color.BLUE);  Target78.SetLineWeight(3);
Target100.SetDefaultColor(Color.BLUE); Target100.SetLineWeight(4);

Target62.HideBubble(); Target78.HideBubble(); Target100.HideBubble();

# Optional: highlight the 78.6 retrace (same as F786 but colored to direction)
plot Retrace78 = if show78Line and plotOK then HighestAll(fib786) else Double.NaN;
Retrace78.AssignValueColor(if isBullish then Color.GREEN else Color.RED);
Retrace78.SetStyle(Curve.LONG_DASH);
Retrace78.SetLineWeight(2);
Retrace78.HideBubble();

# =========================
# Gann PRICE levels
# =========================
def gannAnchor = if isBullish then winLow else winHigh;

def G45 = if isBullish then gannAnchor + rng * g45mult else gannAnchor - rng * g45mult;
def G90 = if isBullish then gannAnchor + rng * g90mult else gannAnchor - rng * g90mult;
def G180 = if isBullish then gannAnchor + rng * g180mult else gannAnchor - rng * g180mult;
def G360 = if isBullish then gannAnchor + rng * g360mult else gannAnchor - rng * g360mult;

plot Gann45  = if showGannPrice and plotOK then HighestAll(G45)  else Double.NaN;
plot Gann90  = if showGannPrice and plotOK then HighestAll(G90)  else Double.NaN;
plot Gann180 = if showGannPrice and plotOK then HighestAll(G180) else Double.NaN;
plot Gann360 = if showGannPrice and plotOK then HighestAll(G360) else Double.NaN;

Gann45.SetDefaultColor(Color.RED);
Gann90.SetDefaultColor(Color.RED);
Gann180.SetDefaultColor(Color.RED);
Gann360.SetDefaultColor(Color.RED);

Gann45.SetStyle(Curve.SHORT_DASH);
Gann90.SetStyle(Curve.SHORT_DASH);
Gann180.SetStyle(Curve.MEDIUM_DASH);
Gann360.SetStyle(Curve.LONG_DASH);

Gann45.SetLineWeight(1);
Gann90.SetLineWeight(1);
Gann180.SetLineWeight(2);
Gann360.SetLineWeight(3);

Gann45.HideBubble(); Gann90.HideBubble(); Gann180.HideBubble(); Gann360.HideBubble();

# =========================
# Gann TIME turns (based on window length)
# =========================
def firstBarInWin = LowestAll(if inWin then bn else Double.NaN);
def lastBarInWin  = HighestAll(if inWin then bn else Double.NaN);
def windowBars = lastBarInWin - firstBarInWin;

def off45  = Round(windowBars * pct45, 0);
def off90  = Round(windowBars * pct90, 0);
def off180 = Round(windowBars * pct180, 0);

def turnAnchor = if isBullish then hiBar else loBar;

AddVerticalLine(showTimeTurns and plotOK and bn == turnAnchor + off45,  "T+" + off45,  Color.BLACK);
AddVerticalLine(showTimeTurns and plotOK and bn == turnAnchor + off90,  "T+" + off90,  Color.BLACK);
AddVerticalLine(showTimeTurns and plotOK and bn == turnAnchor + off180, "T+" + off180, Color.BLACK);

# =========================
# Labels (clean / no stats)
# =========================
AddLabel(showLabels and plotOK,
    "DATE WINDOW: " + startDate + " to " + endDate,
    Color.WHITE);

AddLabel(showLabels and plotOK,
    (if isBullish then "BULLISH SWING" else "BEARISH SWING") +
    " | High: " + Round(winHigh, 2) + " Low: " + Round(winLow, 2),
    if isBullish then Color.GREEN else Color.RED);

AddLabel(showLabels and showZones and plotOK,
    (if isBullish then "BUY ZONE: " else "SELL ZONE: ") + Round(zoneLo, 2) + " - " + Round(zoneHi, 2),
    if isBullish then Color.GREEN else Color.RED);

AddLabel(showLabels and showGannPriceLabels and showGannPrice and plotOK,
    "GANN 45/90/180/360: " + Round(G45, 2) + " | " + Round(G90, 2) + " | " + Round(G180, 2) + " | " + Round(G360, 2),
    Color.RED);
