# ============================================================
# Weighted Alpha Indicator with Swing/Day Auto Function + #Scanner compatibility
#
# Author: ANTWERKS | Revision: 2025-10-21
# ============================================================
declare lower;
# === Auto Mode Selection ===
# Automatically switches based on chart timeframe
# 0 = Swing mode, 1 = Day mode
def mode = if GetAggregationPeriod() <= AggregationPeriod.FIFTEEN_MIN then 1 else 0;
input lengthSwing = 60;     # bars for swing mode (about 3 months)
input lengthDay = 90;       # bars for intraday mode (~90 1m-15m bars)
input decayStart = 0.5;     # older bar weight (linear mode)
input decayFactor = 0.95;   # exponential factor (day mode)
input bullishThreshold = 5; # bullish % threshold
input showLabel = yes;
def price = close;
def barsAvailable = BarNumber();
# === Choose lookback length ===
def useLen = if mode == 0 then lengthSwing else lengthDay;
def useLenSafe = if useLen < 1 then 1 else useLen;
# Pre-calc linear step (ok to compute even if not used in day mode)
def step = (1 - decayStart) / Max(useLenSafe - 1, 1);
# === WeightedSum and WeightTotal computed via inline conditional folds ===
def weightedSum = if mode == 0 then
    fold i = 0 to useLenSafe - 1 with s = 0 while 1 do
        s + (if !IsNaN(GetValue(price, i)) and GetValue(price, i) > 0
             then ((price - GetValue(price, i)) / GetValue(price, i)) * (1 - i * step)
             else 0)
else
    fold iA = 0 to useLenSafe - 1 with sA = 0 while 1 do
        sA + (if !IsNaN(GetValue(price, iA)) and GetValue(price, iA) > 0
             then ((price - GetValue(price, iA)) / GetValue(price, iA)) * Power(decayFactor, iA)
             else 0);
def weightTotal = if mode == 0 then
    fold j = 0 to useLenSafe - 1 with w = 0 while 1 do
        w + (if !IsNaN(GetValue(price, j)) and GetValue(price, j) > 0
             then (1 - j * step)
             else 0)
else
    fold jA = 0 to useLenSafe - 1 with wA = 0 while 1 do
        wA + (if !IsNaN(GetValue(price, jA)) and GetValue(price, jA) > 0
             then Power(decayFactor, jA)
             else 0);
# Protect against divide by zero
def weightedAlpha = 100 * (weightedSum / Max(weightTotal, 1));
# === Plot Weighted Alpha ===
plot WA1 = weightedAlpha;
WA1.SetLineWeight(2);
WA1.AssignValueColor(
    if WA1 > bullishThreshold then Color.DARK_GREEN
    else if WA1> 0 then Color.GREEN
    else if WA1 < 0 then Color.RED
    else Color.GRAY
);
# === Mode Labels ===
AddLabel(showLabel,
    "Mode: " + (if mode == 0 then "Swing" else "Day") +
    " | WA: " + AsText(Round(WA1, 2)) + "%",
    if WA1 > bullishThreshold then Color.DARK_GREEN
    else if WA1 > 0 then Color.GREEN
    else Color.RED
);
# === Bullish Scanner Output ===
plot BullishScan = WA1 > bullishThreshold;
BullishScan.SetDefaultColor(Color.GREEN);
# ============================================================