Why have 5 indicators on your screen when you can have just one! Let's do a Fusion.
Python:
# Unified Signal (MACD + RSI + ATR + VWAP + Volume Pressure)
# + MACD Slope/Momentum + RSI Momentum ZLEMA + Adaptive EMA(8) Weight
# Accuracy features: dynamic majority, price confirmation, cooldown, optional ATR gate
# Outputs: BUY (1), SELL (-1), NONE (0) and colors price bars
# Tuning tips:
# Fewer whipsaws → raise confirmLen to 3 or cooldownBars to 3.
# More signals → lower majorityFrac to 0.6 or disable useATRGate.
# If volume pressure is noisy on your tickers → increase pressureEMA to 8–10 and/or pressureThreshold to ~0.12.
# Hidden Intent Composite (MACD/RSI/ATR + 12 Signals) - Fixed
# Clean compile: no AddChartColor, no invalid VWAP params, no ternary operator.
# Version 1.1
declare lower;
#-------------------------
# -------- Inputs --------
#-------------------------
input rsiBuy = 55;
input rsiSell = 45;
input atrLength = 14;
# Feature toggles
input useVolumePressure = yes; # (1)
input useVWAPRejection = yes; # (4)
input useStopHuntReversal = yes; # (5)
input useMomentumVolumeDiv = yes; # (10)
input useRelativeStrength = yes; # (11)
input useOpeningDriveFailure = yes; # (12)
input usePOCShiftProxy = yes; # (7) (lightweight proxy, not VolumeProfile)
input useRangeVolRegime = yes; # (9)
input useOBVDivergence = yes; # (3)
input useVWAPSlopeShift = yes; # extra context
input useEMA8Intent = yes; # your 8-EMA “3-vote” rule
input useATRTrendFilter = yes; # ATR% slope
# Weights
input wVolumePressure = 2;
input wVWAPRejection = 2;
input wStopHuntReversal = 2;
input wMomentumVolumeDiv = 2;
input wRelativeStrength = 2;
input wOpeningDriveFailure = 2;
input wPOCShiftProxy = 2;
input wRangeVolRegime = 1;
input wOBVDivergence = 2;
input wVWAPSlopeShift = 1;
input wEMA8Intent = 3;
input wATRTrendFilter = 1;
# Relative Strength
input rsSymbol = "QQQ";
input rsLen = 20;
# Opening Drive window (minutes after 09:30)
input odMinutes = 30;
# Smoothing
input smoothEMA = 5;
# Visuals
input showBubbles = no;
input paintBars = yes; # set yes to color price bars
input showComponents = no;
input showScoreLabel = yes;
#-------------------------
# ----- Base Series ------
#-------------------------
def na = Double.NaN;
def c = close;
def o = open;
def h = high;
def l = low;
def v = volume;
# MACD
def macdDiff = MACD()."Diff";
# RSI
def rsi = RSI();
# ATR & ATR%
def atr = ATR(length = atrLength);
def atrPct = if c != 0 then atr / c * 100 else 0;
# EMA8
def ema = ExpAverage(c, 20);
# ---------- Custom Session VWAP (RTH reset at 09:30) ----------
def newDay = GetDay() <> GetDay()[1];
def rthStart = SecondsFromTime(0930) == 0;
def sessionReset = newDay or rthStart;
def tp = (h + l + c) / 3;
def cumPV = if sessionReset then tp * v else cumPV[1] + tp * v;
def cumV = if sessionReset then v else cumV[1] + v;
def vwap = if cumV > 0 then cumPV / cumV else c;
# OBV (simple)
def obv = TotalSum(Sign(c - c[1]) * v);
# Relative Strength vs benchmark
def rs = c / close(rsSymbol);
def rsMA = Average(rs, rsLen);
def rsMA_slope = rsMA - rsMA[1];
# Helpers
def trange = h - l;
def body = AbsValue(c - o);
def upperWick = if c >= o then h - c else h - o;
def lowerWick = if c >= o then o - l else c - l;
# Opening Drive window (first N minutes from 09:30)
def inOD = SecondsFromTime(0930) >= 0 and SecondsFromTime(0930) < odMinutes * 60;
#-------------------------
# -- Hidden Intent Logic -
#-------------------------
# (1) Volume Pressure vs Price Direction
def rawVP = if trange > 0 then ((c - o) / trange) * v else 0;
def vpEMA = ExpAverage(rawVP, smoothEMA);
def priceDir = c - c[1];
def vpSignal = if useVolumePressure then
if vpEMA > 0 and priceDir >= 0 then 1 else
if vpEMA < 0 and priceDir <= 0 then -1 else 0
else 0;
# (4) VWAP Rejections (within 0.1*ATR and wick-dominant rejection)
def nearVWAP = AbsValue(c - vwap) <= (atr * 0.1);
def rejectUp = nearVWAP and c > vwap and lowerWick > body;
def rejectDn = nearVWAP and c < vwap and upperWick > body;
def vwapRejSignal = if useVWAPRejection then
if rejectUp then 1 else
if rejectDn then -1 else 0
else 0;
# (5) Stop-run traps (liquidity hunts)
input swingLen = 10;
def swingHigh = Highest(h[1], swingLen);
def swingLow = Lowest(l[1], swingLen);
def stopRunUp = h > swingHigh and c < swingHigh;
def stopRunDn = l < swingLow and c > swingLow;
def stopHuntSignal = if useStopHuntReversal then
if stopRunUp then -1 else
if stopRunDn then 1 else 0
else 0;
# (10) Momentum divergence (price HH/LL vs MACD Diff)
def hh = h > Highest(h[1], 5);
def ll = l < Lowest(l[1], 5);
def macdLowerHigh = macdDiff < macdDiff[1] and macdDiff[1] > macdDiff[2];
def macdHigherLow = macdDiff > macdDiff[1] and macdDiff[1] < macdDiff[2];
def momDivSignal = if useMomentumVolumeDiv then
if hh and macdLowerHigh then -1 else
if ll and macdHigherLow then 1 else 0
else 0;
# (11) Relative Strength slope
def rsSignal = if useRelativeStrength then
if rsMA_slope > 0 then 1 else
if rsMA_slope < 0 then -1 else 0
else 0;
# (12) Opening Drive Failure (simple ORB logic)
rec orh = if inOD then Max(if IsNaN(orh[1]) then h else orh[1], h) else orh[1];
rec orl = if inOD then Min(if IsNaN(orl[1]) then l else orl[1], l) else orl[1];
def brokeUpOD = !inOD and c[1] > orh and orh != 0;
def failedUp = brokeUpOD and c < orh;
def brokeDnOD = !inOD and c[1] < orl and orl != 0;
def failedDn = brokeDnOD and c > orl;
def odFailSignal = if useOpeningDriveFailure then
if failedUp then -1 else
if failedDn then 1 else 0
else 0;
# (7) POC Shift Proxy (lightweight): use rolling VWAP vs rolling mean price
input pocLookback = 50;
def meanPrice = Average(c, pocLookback);
def pocSignal = if usePOCShiftProxy then
if vwap > meanPrice and vwap[1] <= meanPrice[1] then 1 else
if vwap < meanPrice and vwap[1] >= meanPrice[1] then -1 else 0
else 0;
# (9) Range/Volume regime
def trueRange = TrueRange(h, c, l);
def rangeExp = trueRange > Average(trueRange, 14);
def volExp = v > Average(v, 20);
def regimeSignal = if useRangeVolRegime then
if rangeExp and !volExp then -1 else
if rangeExp and volExp then 1 else 0
else 0;
# (3) OBV divergence proxy
def priceUp2 = c > c[1] and c[1] > c[2];
def priceDn2 = c < c[1] and c[1] < c[2];
def obvDown = obv < obv[1];
def obvUp = obv > obv[1];
def obvDivSignal = if useOBVDivergence then
if priceUp2 and obvDown then -1 else
if priceDn2 and obvUp then 1 else 0
else 0;
# VWAP slope shift
def vwapSlope = vwap - vwap[1];
def vwapSlopeSignal = if useVWAPSlopeShift then
if vwapSlope > 0 then 1 else
if vwapSlope < 0 then -1 else 0
else 0;
# EMA8 intent (3-vote if both O & C align)
def ema8Signal = if useEMA8Intent then
if c > ema then 1 else
if c < ema then -1 else 0
else 0;
# ATR trend filter
def atrSlope = atrPct - atrPct[1];
def atrSignal = if useATRTrendFilter then
if atrSlope > 0 then 1 else
if atrSlope < 0 then -1 else 0
else 0;
#-------------------------
# ---- Scoring & Plots ---
#-------------------------
def scoreRaw =
vpSignal * wVolumePressure +
vwapRejSignal * wVWAPRejection +
stopHuntSignal * wStopHuntReversal +
momDivSignal * wMomentumVolumeDiv +
rsSignal * wRelativeStrength +
odFailSignal * wOpeningDriveFailure +
pocSignal * wPOCShiftProxy +
regimeSignal * wRangeVolRegime +
obvDivSignal * wOBVDivergence +
vwapSlopeSignal * wVWAPSlopeShift +
ema8Signal * wEMA8Intent +
atrSignal * wATRTrendFilter;
def safeScoreRaw = if IsNaN(scoreRaw) then 0 else scoreRaw;
def scoreEMA = ExpAverage(safeScoreRaw, smoothEMA);
plot Composite = scoreEMA;
Composite.SetLineWeight(2);
Composite.AssignValueColor(
if scoreEMA > 0 then Color.GREEN
else if scoreEMA < 0 then Color.RED
else Color.GRAY
);
plot ZeroLine = 0;
ZeroLine.SetDefaultColor(Color.GRAY);
ZeroLine.SetStyle(Curve.SHORT_DASH);
plot Thrust = scoreRaw;
Thrust.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
Thrust.SetLineWeight(2);
Thrust.AssignValueColor(
if scoreRaw > 0 then Color.GREEN
else if scoreRaw < 0 then Color.RED
else Color.DARK_GRAY
);
# Optional components (thin debug lines)
def showC = showComponents;
plot pVP = if showC then vpSignal else na;
plot pVWAP = if showC then vwapRejSignal else na;
plot pStop = if showC then stopHuntSignal else na;
plot pDiv = if showC then momDivSignal else na;
plot pRS = if showC then rsSignal else na;
plot pOD = if showC then odFailSignal else na;
plot pPOC = if showC then pocSignal else na;
plot pReg = if showC then regimeSignal else na;
plot pOBV = if showC then obvDivSignal else na;
plot pVSlp = if showC then vwapSlopeSignal else na;
plot pE8 = if showC then ema8Signal else na;
plot pATR = if showC then atrSignal else na;
pVP.SetDefaultColor(Color.CYAN);
pVWAP.SetDefaultColor(Color.YELLOW);
pStop.SetDefaultColor(Color.LIGHT_RED);
pDiv.SetDefaultColor(Color.WHITE);
pRS.SetDefaultColor(Color.LIGHT_GREEN);
pOD.SetDefaultColor(Color.MAGENTA);
pPOC.SetDefaultColor(Color.ORANGE);
pReg.SetDefaultColor(Color.LIGHT_GRAY);
pOBV.SetDefaultColor(Color.PINK);
pVSlp.SetDefaultColor(Color.LIGHT_ORANGE);
pE8.SetDefaultColor(Color.CYAN);
pATR.SetDefaultColor(Color.LIGHT_GRAY);
pVP.SetLineWeight(1);
pVWAP.SetLineWeight(1);
pStop.SetLineWeight(1);
pDiv.SetLineWeight(1);
pRS.SetLineWeight(1);
pOD.SetLineWeight(1);
pPOC.SetLineWeight(1);
pReg.SetLineWeight(1);
pOBV.SetLineWeight(1);
pVSlp.SetLineWeight(1);
pE8.SetLineWeight(1);
pATR.SetLineWeight(1);
#-------------------------
# ---- Visual Cues -------
#-------------------------
AddChartBubble(showBubbles and rejectUp, scoreRaw, "VWAP↑Reject", Color.GREEN, yes);
AddChartBubble(showBubbles and rejectDn, scoreRaw, "VWAP↓Reject", Color.RED, no);
AddChartBubble(showBubbles and (hh and macdLowerHigh), scoreRaw, "Mom Div (Bear)", Color.RED, no);
AddChartBubble(showBubbles and (ll and macdHigherLow), scoreRaw, "Mom Div (Bull)", Color.GREEN, yes);
#-------------------------
# ---- Price Bar Paint ---
#-------------------------
AssignPriceColor(
if paintBars then
if scoreEMA > 0 then Color.Cyan
else if scoreEMA < 0 then Color.Red
else Color.GRAY
else Color.CURRENT
);
#-------------------------
# ------ Label -----------
#-------------------------
def bullCount =
Max(0, if IsNaN(vpSignal) then 0 else vpSignal) + Max(0, vwapRejSignal) + Max(0, stopHuntSignal) + Max(0, momDivSignal) +
Max(0, rsSignal) + Max(0, odFailSignal) + Max(0, pocSignal) + Max(0, regimeSignal) +
Max(0, obvDivSignal) + Max(0, vwapSlopeSignal) + Max(0, ema8Signal) + Max(0, atrSignal);
def bearCount =
Max(0, if IsNaN(vpSignal) then 0 else -vpSignal) + Max(0, -vwapRejSignal) + Max(0, -stopHuntSignal) + Max(0, -momDivSignal) +
Max(0, -rsSignal) + Max(0, -odFailSignal) + Max(0, -pocSignal) + Max(0, -regimeSignal) +
Max(0, -obvDivSignal) + Max(0, -vwapSlopeSignal) + Max(0, -ema8Signal) + Max(0, -atrSignal);
AddLabel(showScoreLabel,
"Intent " + AsText(Round(scoreEMA, 1)) +
" | Bull " + bullCount + " vs Bear " + bearCount +
" | MACDdiff " + AsText(Round(macdDiff, 2)) +
" | RSI " + AsText(Round(rsi, 1)) +
" | ATR% " + AsText(Round(atrPct, 2)) + "%",
if scoreEMA > 0 then Color.GREEN else if scoreEMA < 0 then Color.RED else Color.GRAY);
Last edited by a moderator: