# A market regime + timing engine
# WEEKLY_ENGINE_MACRO_CYCLE_ALIGNMENT
# ANTWERKS 04/17/2026
########################################################
declare lower;
#========================
# AUTO TIMEFRAME DETECTION
#========================
def agg = GetAggregationPeriod();
def is5m = agg == AggregationPeriod.FIVE_MIN;
def is15m = agg == AggregationPeriod.FIFTEEN_MIN;
def is30m = agg == AggregationPeriod.THIRTY_MIN;
def weekLength =
if is5m then 1380
else if is15m then 460
else if is30m then 230
else 460;
def threeWeekLength = weekLength * 3;
#========================
# WEEKLY ENGINE (FAST)
#========================
def emaW = ExpAverage(close, weekLength);
def slopeW = emaW - emaW[10];
def atrW = Average(TrueRange(high, close, low), weekLength);
def normW = slopeW / atrW;
#========================
# 3-WEEK ENGINE (SLOW)
#========================
def ema3W = ExpAverage(close, threeWeekLength);
def slope3W = ema3W - ema3W[20];
def atr3W = Average(TrueRange(high, close, low), threeWeekLength);
def norm3W = slope3W / atr3W;
#========================
# STATES
#========================
def bullW = normW > 0.02;
def bearW = normW < -0.02;
def bull3W = norm3W > 0.02;
def bear3W = norm3W < -0.02;
def alignBull = bullW and bull3W;
def alignBear = bearW and bear3W;
def conflict =
(bullW and bear3W) or
(bearW and bull3W);
#========================
# HISTOGRAM (WEEKLY)
#========================
plot WeeklyCycle = normW;
WeeklyCycle.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
WeeklyCycle.SetLineWeight(3);
WeeklyCycle.AssignValueColor(
if alignBull then Color.GREEN
else if alignBear then Color.RED
else if conflict then Color.YELLOW
else Color.GRAY
);
#========================
# 3-WEEK OVERLAY (LINE)
#========================
def slope3 = norm3W - norm3W[5];
plot MacroCycle = norm3W;
MacroCycle.SetDefaultColor(Color.CYAN);
MacroCycle.SetLineWeight(2);
MacroCycle.AssignValueColor(
if norm3W > 0 and slope3 > 0 then Color.GREEN
else if norm3W > 0 and slope3 <= 0 then Color.DARK_GREEN
else if norm3W < 0 and slope3 < 0 then Color.RED
else if norm3W < 0 and slope3 >= 0 then Color.DARK_RED
else Color.GRAY
);
#========================
# ZERO LINE
#========================
plot Zero = 0;
Zero.SetDefaultColor(Color.GRAY);
Zero.SetStyle(Curve.SHORT_DASH);
#========================
# LABEL ENGINE
#========================
AddLabel(yes,
if alignBull then "FULL BULL ALIGNMENT (1W + 3W)"
else if alignBear then "FULL BEAR ALIGNMENT (1W + 3W)"
else if conflict then "CYCLE CONFLICT (CHOP / TRANSITION)"
else "WEAK / NEUTRAL",
if alignBull then Color.GREEN
else if alignBear then Color.RED
else if conflict then Color.YELLOW
else Color.GRAY
);
#========================
# VOLATILITY COMPRESSION
#========================
input shortATRLength = 14;
# short-term volatility
def atrShort = Average(TrueRange(high, close, low), shortATRLength);
# already defined:
# atrW (weekly ATR)
def compressionRatio = atrShort / atrW;
# thresholds (tuneable)
input compressionThreshold = 0.45;
input expansionThreshold = 1.2;
def isCompression = compressionRatio < compressionThreshold;
def isExpansion = compressionRatio > expansionThreshold;
def compressZone =
if isCompression then 0 else Double.NaN;
def compressionRelease =
isCompression[1] and !isCompression;
plot ExpansionTrigger =
if compressionRelease then normW else Double.NaN;
ExpansionTrigger.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
ExpansionTrigger.SetDefaultColor(Color.CYAN);
ExpansionTrigger.SetLineWeight(3);
def exhaustion =
normW > 0.08 or normW < -0.08;
AddCloud(compressZone, 0, Color.DARK_GRAY, Color.DARK_GRAY);
plot CompressionDot =
if isCompression then normW else Double.NaN;
CompressionDot.SetPaintingStrategy(PaintingStrategy.POINTS);
CompressionDot.SetDefaultColor(Color.YELLOW);
CompressionDot.SetLineWeight(3);
plot ExpansionDot =
if isExpansion then normW else Double.NaN;
ExpansionDot.SetPaintingStrategy(PaintingStrategy.POINTS);
ExpansionDot.SetDefaultColor(Color.CYAN);
ExpansionDot.SetLineWeight(3);
AddLabel(yes,
if isCompression then "COMPRESSION (BUILDING ENERGY)"
else if isExpansion then "EXPANSION (MOVE ACTIVE)"
else "NORMAL VOL",
if isCompression then Color.YELLOW
else if isExpansion then Color.CYAN
else Color.GRAY
);
AddLabel(exhaustion,
if normW > 0 then "BULL EXHAUSTION"
else "BEAR EXHAUSTION",
Color.ORANGE
);