RealizeTrades
New member
Trend Flow Algo
Adaptive momentum oscillator for Thinkorswim
mod note:
ADAPTIVE MOMENTUM FUSION & KNN NEURAL ENGINE
An advanced multi-layer lower study oscillator that fuses adaptive rate-of-change, volume flow, machine learning bias (KNN kernel vote), and higher-timeframe trend context into a single $0$ to $100$ normalized confluence engine.
How Day Traders Use It
https://tos.mx/!4DiEIrWo
Adaptive momentum oscillator for Thinkorswim
mod note:
ADAPTIVE MOMENTUM FUSION & KNN NEURAL ENGINE
An advanced multi-layer lower study oscillator that fuses adaptive rate-of-change, volume flow, machine learning bias (KNN kernel vote), and higher-timeframe trend context into a single $0$ to $100$ normalized confluence engine.
How Day Traders Use It
- Multi-Engine Confluence: Synthesizes 6 distinct market votes (Oscillator, Signal cross, Volume Flow, Regime, Machine Learning KNN, and HTF trend) into a real-time Confluence Meter to filter out low-probability setups.
- Kernel Machine Learning (KNN) Bias: Evaluates current market state against a rolling historical training window using an inverse-distance kernel vote, outputting a clear statistical bias percentage.
- Dynamic Divergence & Fatigue: Plots divergence chart bubbles alongside momentum fatigue alerts to signal pending trend reversals.
https://tos.mx/!4DiEIrWo
Code:
# ==========================================================================
# PLATFORM-DIFFERENCE NOTES (read before use):
# 1. KNN Bias: Pine used a true k-nearest-neighbor vote with dynamic
# arrays. ThinkScript has no push/pop arrays or nested loops with
# top-K selection, so this is approximated with an inverse-distance
# KERNEL-WEIGHTED vote over the whole training window (a smooth
# analogue of KNN, not a literal top-K vote).
# 2. HTF Bias: Pine used request.security() to run the FULL oscillator
# engine on a higher timeframe. Re-running the whole multi-stage
# engine on an aggregated feed isn't practical in ThinkScript, so
# this is approximated with a smoothed rate-of-change computed
# directly on the higher-timeframe close.
# 3. Dashboard / KNN panel: Pine's multi-row tables are replaced with
# AddLabel() chips along the top of the chart (ThinkScript has no
# freeform table widget).
# 4. Divergence labels: bubbles are drawn at the confirming (current)
# bar rather than visually anchored back at the pivot bar itself,
# since ThinkScript can't place a bubble in the past from a
# present-bar calculation.
# 5. Max Pivot Age is a fixed input here (maxPivotAgeBars) instead of
# part of a larger structural-filter panel; the optional structural
# filter (min osc swing / min price swing / volume confirmation)
# from Pine was left out for brevity — ask if you want it added.
# ==========================================================================
declare lower;
# ---------------- Inputs: Main ----------------
input engineLength = 14;
input smoothMethod = {default DEMA, EMA, SMA, TEMA, WMA, VWMA};
input presetType = {default Standard, Scalping, Swing, Position};
input signalLength = 7;
input signalSmoothMethod = {default EMA, SMA, DEMA, WMA};
input showCrossDots = yes;
# ---------------- Inputs: Zones ----------------
input overboughtLevel = 80.0;
input oversoldLevel = 20.0;
# ---------------- Inputs: Volume Flow ----------------
input showVolumeFlow = yes;
# ---------------- Inputs: Regime ----------------
input showRegimeState = yes;
# ---------------- Inputs: Momentum Fatigue ----------------
input showFatigueLabels = yes;
input fatigueConfirmBars = 3;
# ---------------- Inputs: Divergence ----------------
input showRegularDivergence = yes;
input showHiddenDivergence = yes;
input maxPivotAgeBars = 100;
# ---------------- Inputs: KNN Bias (approximated, see notes) ----------------
input showKnnPanel = yes;
input knnTrainingWindow = 120;
# ---------------- Inputs: HTF Bias (approximated, see notes) ----------------
input showHtfBias = yes;
input higherTimeframe = AggregationPeriod.HOUR;
# ---------------- Inputs: Confluence ----------------
input showConfluenceMeter = yes;
input confluenceHigh = 70.0;
input confluenceLow = 30.0;
# ---------------- Inputs: Dashboard ----------------
input showDashboard = yes;
# ==========================================================================
# PRESET RESOLUTION
# ==========================================================================
def effLen =
if presetType == presetType.Scalping then 8
else if presetType == presetType.Swing then 21
else if presetType == presetType.Position then 34
else engineLength;
def effOB =
if presetType == presetType.Scalping then 75.0
else if presetType == presetType.Swing then 80.0
else if presetType == presetType.Position then 85.0
else overboughtLevel;
def effOS =
if presetType == presetType.Scalping then 25.0
else if presetType == presetType.Swing then 20.0
else if presetType == presetType.Position then 15.0
else oversoldLevel;
def src = close;
# ==========================================================================
# ENGINE — Adaptive Momentum Fusion (AMF)
# ==========================================================================
# --- Component 1: Normalized Rate of Change ---
def roc = if src[effLen] != 0 then (src - src[effLen]) / src[effLen] * 100 else 0;
def rocE1 = ExpAverage(roc, effLen);
def rocE2 = ExpAverage(rocE1, effLen);
def rocE3 = ExpAverage(rocE2, effLen);
def rocSmoothed =
if smoothMethod == smoothMethod.EMA then rocE1
else if smoothMethod == smoothMethod.SMA then Average(roc, effLen)
else if smoothMethod == smoothMethod.DEMA then 2 * rocE1 - rocE2
else if smoothMethod == smoothMethod.TEMA then 3 * rocE1 - 3 * rocE2 + rocE3
else if smoothMethod == smoothMethod.WMA then WMA(roc, effLen)
else Average(roc * volume, effLen) / Average(volume, effLen); # VWMA
def rocHigh = Highest(rocSmoothed, effLen * 3);
def rocLow = Lowest(rocSmoothed, effLen * 3);
def nroc = if rocHigh - rocLow != 0 then (rocSmoothed - rocLow) / (rocHigh - rocLow) * 100 else 50;
# --- Component 2: Efficiency-Weighted Impulse ---
def erDirection = AbsValue(src - src[effLen]);
def erVolatility = Sum(AbsValue(src - src[1]), effLen);
def er = if erVolatility != 0 then erDirection / erVolatility else 0;
def prevClose = close[1];
def trueRangeVal = Max(high - low, Max(AbsValue(high - prevClose), AbsValue(low - prevClose)));
def atrEff = WildersAverage(trueRangeVal, effLen);
def impulseRaw = src - src[1];
def impulseAbs = if atrEff != 0 then atrEff else AbsValue(impulseRaw) + 0.0001;
def normalizedImpulse = (if impulseAbs != 0 then impulseRaw / impulseAbs else 0) * er;
def ewiE1 = ExpAverage(normalizedImpulse, effLen);
def ewiE2 = ExpAverage(ewiE1, effLen);
def ewiE3 = ExpAverage(ewiE2, effLen);
def ewiSmoothed =
if smoothMethod == smoothMethod.EMA then ewiE1
else if smoothMethod == smoothMethod.SMA then Average(normalizedImpulse, effLen)
else if smoothMethod == smoothMethod.DEMA then 2 * ewiE1 - ewiE2
else if smoothMethod == smoothMethod.TEMA then 3 * ewiE1 - 3 * ewiE2 + ewiE3
else if smoothMethod == smoothMethod.WMA then WMA(normalizedImpulse, effLen)
else Average(normalizedImpulse * volume, effLen) / Average(volume, effLen);
def ewiHigh = Highest(ewiSmoothed, effLen * 4);
def ewiLow = Lowest(ewiSmoothed, effLen * 4);
def ewi = if ewiHigh - ewiLow != 0 then (ewiSmoothed - ewiLow) / (ewiHigh - ewiLow) * 100 else 50;
# --- Component 3: Stochastic Momentum Position ---
def stochHigh = Highest(src, effLen);
def stochLow = Lowest(src, effLen);
def stochRaw = if stochHigh - stochLow != 0 then (src - stochLow) / (stochHigh - stochLow) * 100 else 50;
def smpLen = Max(Round(effLen / 2, 0), 2);
def smp = ExpAverage(stochRaw, smpLen);
# --- Adaptive Blend ---
def erSmoothed = ExpAverage(er, effLen);
def trendWeight = Min(erSmoothed * 1.5, 0.75);
def rangeWeight = 1 - trendWeight;
def oscSmoothLen = Max(Round(effLen / 3, 0), 2);
def oscRaw = trendWeight * (nroc * 0.55 + ewi * 0.45) + rangeWeight * smp;
def oscE1 = ExpAverage(oscRaw, oscSmoothLen);
def oscE2 = ExpAverage(oscE1, oscSmoothLen);
def oscE3 = ExpAverage(oscE2, oscSmoothLen);
def oscSmoothed =
if smoothMethod == smoothMethod.EMA then oscE1
else if smoothMethod == smoothMethod.SMA then Average(oscRaw, oscSmoothLen)
else if smoothMethod == smoothMethod.DEMA then 2 * oscE1 - oscE2
else if smoothMethod == smoothMethod.TEMA then 3 * oscE1 - 3 * oscE2 + oscE3
else if smoothMethod == smoothMethod.WMA then WMA(oscRaw, oscSmoothLen)
else Average(oscRaw * volume, oscSmoothLen) / Average(volume, oscSmoothLen);
def oscVal = Min(100, Max(0, oscSmoothed));
# --- Signal Line ---
def sigE1 = ExpAverage(oscVal, signalLength);
def sigE2 = ExpAverage(sigE1, signalLength);
def sigVal =
if signalSmoothMethod == signalSmoothMethod.EMA then sigE1
else if signalSmoothMethod == signalSmoothMethod.SMA then Average(oscVal, signalLength)
else if signalSmoothMethod == signalSmoothMethod.DEMA then 2 * sigE1 - sigE2
else WMA(oscVal, signalLength); # WMA
# ==========================================================================
# VOLUME FLOW — Volatility-Normalized Volume Flow (VNVF)
# ==========================================================================
def candleRange = high - low;
def bodySize = AbsValue(close - open);
def bodyRatio = if candleRange != 0 then bodySize / candleRange else 0;
def upperWick = high - Max(close, open);
def lowerWick = Min(close, open) - low;
def wickBias = if candleRange != 0 then (lowerWick - upperWick) / candleRange else 0;
def bodyDir = if close > open then 1 else if close < open then -1 else 0;
def candleScore = bodyDir * bodyRatio * 0.7 + wickBias * 0.3;
def hasVolume = volume > 0;
def signedVol = if hasVolume then candleScore * volume else 0;
def atrNorm = if atrEff != 0 then atrEff else 1;
def avgVol = Average(volume, effLen * 2);
def vnvfRaw = if hasVolume and atrNorm * avgVol != 0 then signedVol / (atrNorm * avgVol) else 0;
def vnvfFastLen = Max(Round(effLen * 0.6, 0), 2);
def vnvfSlowLen = Max(Round(effLen * 1.4, 0), 3);
def vnvfFast = ExpAverage(vnvfRaw, vnvfFastLen);
def vnvfSlow = ExpAverage(vnvfRaw, vnvfSlowLen);
def vnvfBlend = vnvfFast * 0.6 + vnvfSlow * 0.4;
def vnvfPeak = Highest(AbsValue(vnvfBlend), effLen * 4);
def vnvfPeakSafe = Max(vnvfPeak, 0.0001);
def vfVal = Min(100, Max(0, (vnvfBlend / vnvfPeakSafe) * 50 + 50));
# ==========================================================================
# REGIME DETECTION
# ==========================================================================
def erTrending = erSmoothed > 0.3;
def regimeScore =
(if oscVal > sigVal then 1 else 0) +
(if oscVal > 50 then 1 else 0) +
(if vfVal > 50 then 1 else 0) +
(if erTrending then 1 else 0);
# ==========================================================================
# HIGHER TIMEFRAME BIAS (approximated — see notes at top)
# ==========================================================================
def htfClose = close(period = higherTimeframe);
def htfRoc = if htfClose[effLen] != 0 then (htfClose - htfClose[effLen]) / htfClose[effLen] * 100 else 0;
def htfOscProxy = Min(100, Max(0, ExpAverage(htfRoc, effLen) * 5 + 50));
def htfBullish = showHtfBias and htfOscProxy > 55;
def htfBearish = showHtfBias and htfOscProxy < 45;
# ==========================================================================
# OSCILLATOR MOMENTUM (acceleration)
# ==========================================================================
def oscMom = oscVal - oscVal[3];
def momAccel = oscMom > 2;
def momDecel = oscMom < -2;
# ==========================================================================
# MOMENTUM FATIGUE
# ==========================================================================
def fatigueObWeak = oscVal >= effOB and oscVal < oscVal[1];
def fatigueOsStr = oscVal <= effOS and oscVal > oscVal[1];
def fatObCount = CompoundValue(1, if fatigueObWeak then fatObCount[1] + 1 else 0, 0);
def fatOsCount = CompoundValue(1, if fatigueOsStr then fatOsCount[1] + 1 else 0, 0);
def fatObSignal = showFatigueLabels and fatObCount == fatigueConfirmBars;
def fatOsSignal = showFatigueLabels and fatOsCount == fatigueConfirmBars;
# ==========================================================================
# KNN BIAS — inverse-distance kernel-weighted vote (approximation, see notes)
# ==========================================================================
def f1 = oscVal / 100;
def f2 = vfVal / 100;
def f3 = Min(1, Max(0, (oscVal - sigVal + 50) / 100));
def f4 = Min(1, Max(0, erSmoothed));
def knnWin = knnTrainingWindow;
def sumW = fold i1 = 1 to knnWin + 1 with sw = 0 do
sw + 1 / (1 + AbsValue(f1 - GetValue(f1, i1)) + AbsValue(f2 - GetValue(f2, i1)) +
AbsValue(f3 - GetValue(f3, i1)) + AbsValue(f4 - GetValue(f4, i1)));
def sumBW = fold i2 = 1 to knnWin + 1 with sbw = 0 do
sbw + (if GetValue(close, i2 - 1) > GetValue(close, i2) then 1 else 0) *
(1 / (1 + AbsValue(f1 - GetValue(f1, i2)) + AbsValue(f2 - GetValue(f2, i2)) +
AbsValue(f3 - GetValue(f3, i2)) + AbsValue(f4 - GetValue(f4, i2))));
def knnVal = if sumW > 0 then sumBW / sumW * 100 else 50;
def knnIsBull = knnVal >= 58;
def knnIsBear = knnVal <= 42;
def knnConf = Round(
if knnIsBull then knnVal
else if knnIsBear then 100 - knnVal
else AbsValue(knnVal - 50) * 2, 0);
# ==========================================================================
# CONFLUENCE METER
# ==========================================================================
def confBullVotes =
(if oscVal > 55 then 1 else 0) +
(if oscVal > sigVal then 1 else 0) +
(if vfVal > 55 then 1 else 0) +
(if erTrending and oscVal > 50 then 1 else 0) +
(if knnIsBull then 1 else 0) +
(if htfBullish then 1 else 0);
def confBearVotes =
(if oscVal < 45 then 1 else 0) +
(if oscVal < sigVal then 1 else 0) +
(if vfVal < 45 then 1 else 0) +
(if erTrending and oscVal < 50 then 1 else 0) +
(if knnIsBear then 1 else 0) +
(if htfBearish then 1 else 0);
def confNet = confBullVotes - confBearVotes;
def confRaw = (confNet + 6) / 12 * 100;
def confVal = Min(100, Max(0, ExpAverage(confRaw, 3)));
# ==========================================================================
# DIVERGENCE DETECTION
# ==========================================================================
def pivSpan = Max(Round(effLen / 2, 0), 2);
def windowHigh = Highest(high, pivSpan * 2 + 1);
def isPivotHigh = high[pivSpan] == windowHigh;
def windowLow = Lowest(low, pivSpan * 2 + 1);
def isPivotLow = low[pivSpan] == windowLow;
def curHHPrice = if isPivotHigh then high[pivSpan] else Double.NaN;
def curHHOsc = if isPivotHigh then oscVal[pivSpan] else Double.NaN;
def curLLPrice = if isPivotLow then low[pivSpan] else Double.NaN;
def curLLOsc = if isPivotLow then oscVal[pivSpan] else Double.NaN;
def pivHHPrice = CompoundValue(1, if isPivotHigh then curHHPrice else pivHHPrice[1], Double.NaN);
def pivHHOsc = CompoundValue(1, if isPivotHigh then curHHOsc else pivHHOsc[1], Double.NaN);
def pivHHBar = CompoundValue(1, if isPivotHigh then BarNumber() - pivSpan else pivHHBar[1], Double.NaN);
def prevHHPrice = CompoundValue(1, if isPivotHigh then pivHHPrice[1] else prevHHPrice[1], Double.NaN);
def prevHHOsc = CompoundValue(1, if isPivotHigh then pivHHOsc[1] else prevHHOsc[1], Double.NaN);
def prevHHBar = CompoundValue(1, if isPivotHigh then pivHHBar[1] else prevHHBar[1], Double.NaN);
def pivLLPrice = CompoundValue(1, if isPivotLow then curLLPrice else pivLLPrice[1], Double.NaN);
def pivLLOsc = CompoundValue(1, if isPivotLow then curLLOsc else pivLLOsc[1], Double.NaN);
def pivLLBar = CompoundValue(1, if isPivotLow then BarNumber() - pivSpan else pivLLBar[1], Double.NaN);
def prevLLPrice = CompoundValue(1, if isPivotLow then pivLLPrice[1] else prevLLPrice[1], Double.NaN);
def prevLLOsc = CompoundValue(1, if isPivotLow then pivLLOsc[1] else prevLLOsc[1], Double.NaN);
def prevLLBar = CompoundValue(1, if isPivotLow then pivLLBar[1] else prevLLBar[1], Double.NaN);
def hhFresh = !IsNaN(prevHHBar) and (BarNumber() - pivSpan - prevHHBar) <= maxPivotAgeBars;
def llFresh = !IsNaN(prevLLBar) and (BarNumber() - pivSpan - prevLLBar) <= maxPivotAgeBars;
def dRegBear = showRegularDivergence and isPivotHigh and !IsNaN(prevHHPrice) and curHHPrice > prevHHPrice and curHHOsc < prevHHOsc and hhFresh;
def dHidBear = showHiddenDivergence and isPivotHigh and !IsNaN(prevHHPrice) and curHHPrice < prevHHPrice and curHHOsc > prevHHOsc and hhFresh;
def dRegBull = showRegularDivergence and isPivotLow and !IsNaN(prevLLPrice) and curLLPrice < prevLLPrice and curLLOsc > prevLLOsc and llFresh;
def dHidBull = showHiddenDivergence and isPivotLow and !IsNaN(prevLLPrice) and curLLPrice > prevLLPrice and curLLOsc < prevLLOsc and llFresh;
AddChartBubble(dRegBull, oscVal - 6, "D▲", CreateColor(0, 230, 118), no);
AddChartBubble(dRegBear, oscVal + 6, "D▼", CreateColor(255, 82, 82), yes);
AddChartBubble(dHidBull, oscVal - 6, "H▲", CreateColor(0, 230, 118), no);
AddChartBubble(dHidBear, oscVal + 6, "H▼", CreateColor(255, 82, 82), yes);
# ==========================================================================
# PLOTS
# ==========================================================================
plot Oscillator = oscVal;
Oscillator.SetLineWeight(3);
Oscillator.AssignValueColor(
if oscVal >= effOB then CreateColor(0, 230, 118)
else if oscVal <= effOS then CreateColor(255, 82, 82)
else if oscVal >= 50 then CreateColor(0, 150, 90)
else CreateColor(160, 60, 60));
plot Signal = sigVal;
Signal.SetDefaultColor(Color.GRAY);
Signal.SetLineWeight(1);
plot OBLevel = effOB;
OBLevel.SetDefaultColor(Color.DARK_GREEN);
OBLevel.SetStyle(Curve.POINTS);
plot MidLine = 50;
MidLine.SetDefaultColor(Color.GRAY);
MidLine.SetStyle(Curve.POINTS);
plot OSLevel = effOS;
OSLevel.SetDefaultColor(Color.DARK_RED);
OSLevel.SetStyle(Curve.POINTS);
AddCloud(if oscVal >= effOB then Oscillator else Double.NaN, OBLevel, CreateColor(0, 230, 118));
AddCloud(OSLevel, if oscVal <= effOS then Oscillator else Double.NaN, CreateColor(255, 82, 82));
AddCloud(if showRegimeState and regimeScore >= 3 then 100 else Double.NaN, OBLevel, CreateColor(0, 230, 118));
AddCloud(OSLevel, if showRegimeState and regimeScore <= 1 then 0 else Double.NaN, CreateColor(255, 82, 82));
plot VFBull = if showVolumeFlow then Max(vfVal, 50) else Double.NaN;
VFBull.SetDefaultColor(CreateColor(0, 230, 118));
plot VFBear = if showVolumeFlow then Min(vfVal, 50) else Double.NaN;
VFBear.SetDefaultColor(CreateColor(255, 82, 82));
plot VFBase = if showVolumeFlow then 50 else Double.NaN;
VFBase.SetDefaultColor(Color.GRAY);
VFBase.Hide();
AddCloud(VFBull, VFBase, CreateColor(0, 230, 118));
AddCloud(VFBase, VFBear, CreateColor(255, 82, 82));
plot ConfluenceLine = if showConfluenceMeter then confVal else Double.NaN;
ConfluenceLine.SetPaintingStrategy(PaintingStrategy.LINE);
ConfluenceLine.SetLineWeight(1);
ConfluenceLine.AssignValueColor(
if confVal >= confluenceHigh then CreateColor(0, 230, 118)
else if confVal <= confluenceLow then CreateColor(255, 82, 82)
else Color.LIGHT_GRAY);
plot CrossUp = if showCrossDots and Crosses(oscVal, sigVal, CrossingDirection.ABOVE) then sigVal else Double.NaN;
CrossUp.SetPaintingStrategy(PaintingStrategy.POINTS);
CrossUp.SetLineWeight(3);
CrossUp.SetDefaultColor(CreateColor(0, 230, 118));
plot CrossDown = if showCrossDots and Crosses(oscVal, sigVal, CrossingDirection.BELOW) then sigVal else Double.NaN;
CrossDown.SetPaintingStrategy(PaintingStrategy.POINTS);
CrossDown.SetLineWeight(3);
CrossDown.SetDefaultColor(CreateColor(255, 82, 82));
# ==========================================================================
# DASHBOARD (label chips — ThinkScript has no free-form table widget)
# ==========================================================================
AddLabel(showDashboard, "Trend: " + (if oscVal > 60 then "Bullish" else if oscVal < 40 then "Bearish" else "Neutral"),
if oscVal > 60 then CreateColor(0, 230, 118) else if oscVal < 40 then CreateColor(255, 82, 82) else Color.YELLOW);
AddLabel(showDashboard, "Osc: " + AsText(Round(oscVal, 1)), Color.WHITE);
AddLabel(showDashboard,
"Signal: " + (if Crosses(oscVal, sigVal, CrossingDirection.ABOVE) then "Bull Cross"
else if Crosses(oscVal, sigVal, CrossingDirection.BELOW) then "Bear Cross"
else if oscVal >= effOB then "Overbought"
else if oscVal <= effOS then "Oversold"
else "--"),
Color.WHITE);
AddLabel(showDashboard, "Momentum: " + (if momAccel then "Accel Up" else if momDecel then "Decel Dn" else "Steady"),
if momAccel then CreateColor(0, 230, 118) else if momDecel then CreateColor(255, 82, 82) else Color.YELLOW);
AddLabel(showHtfBias, "HTF: " + (if htfBullish then "Bullish" else if htfBearish then "Bearish" else "Neutral"),
if htfBullish then CreateColor(0, 230, 118) else if htfBearish then CreateColor(255, 82, 82) else Color.GRAY);
AddLabel(showVolumeFlow, "VolFlow: " + (if vfVal > 60 then "Inflow" else if vfVal < 40 then "Outflow" else "Neutral"),
if vfVal > 60 then CreateColor(0, 230, 118) else if vfVal < 40 then CreateColor(255, 82, 82) else Color.YELLOW);
AddLabel(showRegimeState, "Regime: " + (if erTrending then "Trending" else "Ranging") + " (" + AsText(regimeScore) + "/4)",
if erTrending then CreateColor(0, 230, 118) else Color.YELLOW);
AddLabel(showKnnPanel, "KNN: " + (if knnIsBull then "Bull " else if knnIsBear then "Bear " else "Neutral ") + AsText(knnConf) + "%",
if knnIsBull then CreateColor(0, 230, 118) else if knnIsBear then CreateColor(255, 82, 82) else Color.GRAY);
AddLabel(showConfluenceMeter,
"Confluence: " + AsText(Round(confVal, 1)) + " (" +
(if confVal >= confluenceHigh then "Strong Bull"
else if confVal <= confluenceLow then "Strong Bear"
else if confVal > 55 then "Lean Bull"
else if confVal < 45 then "Lean Bear"
else "Mixed") + ")",
if confVal >= confluenceHigh then CreateColor(0, 230, 118) else if confVal <= confluenceLow then CreateColor(255, 82, 82) else Color.YELLOW);
AddLabel(yes, "Votes: " + AsText(confBullVotes) + "B / " + AsText(confBearVotes) + "S", Color.LIGHT_GRAY);
# ==========================================================================
# ALERTS
# ==========================================================================
Alert(Crosses(oscVal, sigVal, CrossingDirection.ABOVE) and oscVal < 50, "NFE Bull Cross", Alert.BAR, Sound.Ding);
Alert(Crosses(oscVal, sigVal, CrossingDirection.BELOW) and oscVal > 50, "NFE Bear Cross", Alert.BAR, Sound.Ding);
Alert(Crosses(oscVal, effOS, CrossingDirection.ABOVE), "NFE Exit Oversold", Alert.BAR, Sound.Ding);
Alert(Crosses(oscVal, effOB, CrossingDirection.BELOW), "NFE Exit Overbought", Alert.BAR, Sound.Ding);
Alert(dRegBull, "NFE Regular Bullish Divergence", Alert.BAR, Sound.Ding);
Alert(dRegBear, "NFE Regular Bearish Divergence", Alert.BAR, Sound.Ding);
Alert(dHidBull, "NFE Hidden Bullish Divergence", Alert.BAR, Sound.Ding);
Alert(dHidBear, "NFE Hidden Bearish Divergence", Alert.BAR, Sound.Ding);
Alert(Crosses(vfVal, 50, CrossingDirection.ABOVE), "NFE Volume Inflow", Alert.BAR, Sound.Ding);
Alert(Crosses(vfVal, 50, CrossingDirection.BELOW), "NFE Volume Outflow", Alert.BAR, Sound.Ding);
Alert(fatObSignal, "NFE Overbought Fatigue", Alert.BAR, Sound.Ding);
Alert(fatOsSignal, "NFE Oversold Fatigue", Alert.BAR, Sound.Ding);
Last edited by a moderator: