
Case Study: Alright guys, money is showing signs of possibly rolling out of defensive plays and back into growth. Its still early stages so watch for confirmation but its promising. Lower/Falling vix environments help trend following and momentum trades. Currently the money seems to be flowing into Semi's and the recently beaten down Solars. Check SMH and TAN to confirm. That said I have chosen SHLS for our case study because I believe its a good break out candidate with possible rebound fundamentals and probably not on a lot of radars right now. If you notice the chart it appears that there was some front loading starting back on April 7th. Then when the announced earnings on 5/6 they had a small earnings beat and improved forward guidance. The market showed its appreciation by crowding in and we have what I believe is the first leg of a potential breakout. The scoring indicator I built rewards momentum plays backed by volume that have runways.
*There are options to turn the labels off or make them compact. I have them on verbose so you see whats going on

Most momentum indicators are just variations of the same tired formula: price goes up fast = good. The problem? They ignore the road you're driving on. They don’t care if price is slipping, stalling, or ripping on fumes.
This script was built for momentum traders who know that speed alone doesn’t mean strength. It's designed to answer one simple question:
Is this move legit, or is it just noise on a bad road?
Here’s how it works:






You can flip a switch to use adaptive thresholds (based on standard deviation from recent behavior) or stick with fixed classic values. Momentum means different things on a 5-min chart vs a daily. Now you don’t have to choose — you can let the market set the bar or set it yourself.

Traders who like clean entries on momentum continuation — but hate chasing hollow moves. This is especially useful when the market favors momentum trading environments — trend days, breakouts, or post-consolidation extensions. If you're still trading RSI oversold in those conditions, you're playing the wrong game.
This isn’t a signal generator. It’s a credibility check.
It tells you when the gas is pressed, the tires are gripping, and the road’s open enough to floor it.
My setup: https://tos.mx/!kuI0xa7G
Code:
declare lower;
# === 🧭 Display Mode ===
input labelMode = {default "Verbose", "Compact", "Off"};
def showVerbose = labelMode == labelMode."Verbose";
def showCompact = labelMode == labelMode."Compact";
def showAnyLabel = labelMode != labelMode."Off";
# === ⚙️ Configurable Scoring Weights ===
input cmfWeight = 1.5;
input rsiSlopeWeight = 1.25;
input cmfSlopeWeight = 1.0;
# === 🧪 Toggle Adaptive Thresholds ===
input useAdaptiveThresholds = yes;
# === 📐 Adaptive Threshold Settings ===
input cmfDevMult = 1.5;
input cmfDevLookback = 20;
input cmfSlopeDevLookback = 20;
input rsiSlopeDevLookback = 20;
input strongDevMult = 2.0;
input mediumDevMult = 1.0;
# === 🛣️ BB Bandwidth (Volatility Filter) ===
input bbLength = 20;
input bbMult = 2.0;
def basis = Average(close, bbLength);
def dev = bbMult * stdev(close, bbLength);
def upperBB = basis + dev;
def lowerBB = basis - dev;
def bbw = (upperBB - lowerBB) / basis;
AddLabel(showAnyLabel,
if showCompact then "BB%: " + AsPercent(bbw)
else "BB%: " + AsPercent(bbw) + " | " +
(if bbw > 0.7 then "Very High – Requires strong conviction and momentum to continue without losing traction."
else if bbw > 0.4 then "High – Trend expanding. Needs supporting momentum and volume to sustain."
else if bbw > 0.25 then "Moderate – Transition zone. Watch for confirmation or rejection."
else if bbw > 0.15 then "Low – Tightening range. Early breakout signals may emerge."
else "Very Low – Compression building. High breakout potential; watch closely."),
if bbw > 0.7 then Color.RED
else if bbw > 0.4 then Color.ORANGE
else if bbw > 0.25 then Color.YELLOW
else if bbw > 0.15 then Color.LIGHT_GREEN
else Color.GREEN
);
def bbwMultiplier =
if bbw > 0.7 then 0.6
else if bbw > 0.4 then 0.75
else if bbw > 0.25 then 0.9
else 1.0;
# === 💰 CMF Score ===
input cmfLength = 20;
def highLowRange = high - low;
def mfMultiplier = if highLowRange == 0 then 0 else ((close - low) - (high - close)) / highLowRange;
def mfVolume = mfMultiplier * volume;
def cmf = Sum(mfVolume, cmfLength) / Sum(volume, cmfLength);
def cmfMean = Average(cmf, cmfDevLookback);
def cmfDev = StDev(cmf, cmfDevLookback);
def fixedCmfScore =
if cmf > 0.1 then 2
else if cmf > 0 then 1
else if cmf > -0.1 then 0
else -1;
def cmfScore =
if useAdaptiveThresholds then
if cmf > cmfMean + cmfDevMult * cmfDev then 2
else if cmf > cmfMean then 1
else if cmf > cmfMean - cmfDev then 0
else -1
else
fixedCmfScore;
AddLabel(showAnyLabel,
if showCompact then "CMF: " + AsPercent(cmf)
else "CMF: " + AsPercent(cmf) + " | " +
(if cmfScore == 2 then "Strong buying pressure – well above normal volume conviction."
else if cmfScore == 1 then "Moderate support – above recent average volume strength."
else if cmfScore == 0 then "Flat to weak – near typical CMF range."
else "Selling pressure – below average volume conviction."),
if cmfScore == 2 then Color.GREEN
else if cmfScore == 1 then Color.LIGHT_GREEN
else if cmfScore == 0 then Color.YELLOW
else Color.RED
);
# === 📈 CMF Slope Score ===
input slopeLength = 5;
def cmfSlope = cmf - cmf[slopeLength];
def cmfSlopeDev = StDev(cmfSlope, cmfSlopeDevLookback);
def fixedCmfSlopeScore =
if cmfSlope > 0.2 then 2
else if cmfSlope > 0.05 then 1
else if cmfSlope > -0.05 then 0
else -1;
def cmfSlopeScore =
if useAdaptiveThresholds then
if cmfSlope > strongDevMult * cmfSlopeDev then 2
else if cmfSlope > mediumDevMult * cmfSlopeDev then 1
else if cmfSlope > -mediumDevMult * cmfSlopeDev then 0
else -1
else
fixedCmfSlopeScore;
AddLabel(showAnyLabel,
if showCompact then "CMF Slope: " + AsPercent(cmfSlope)
else "CMF Slope: " + AsPercent(cmfSlope) + " | " +
(if cmfSlopeScore == 2 then "Conviction surging – sharply improving vs baseline."
else if cmfSlopeScore == 1 then "Conviction building – better than normal trend."
else if cmfSlopeScore == 0 then "Flat to fading – average transition."
else "Declining conviction – worse than usual weakening."),
if cmfSlopeScore == 2 then Color.GREEN
else if cmfSlopeScore == 1 then Color.LIGHT_GREEN
else if cmfSlopeScore == 0 then Color.ORANGE
else Color.RED
);
# === 🚀 RSI Slope Score ===
input rsiLength = 14;
def rsi = RSI(rsiLength);
def rsiSlope = rsi - rsi[1];
def rsiSlopeDev = StDev(rsiSlope, rsiSlopeDevLookback);
def fixedRsiSlopeScore =
if rsiSlope > 1.5 then 2
else if rsiSlope > 0.5 then 1
else if rsiSlope > -0.5 then 0
else -1;
def rsiSlopeScore =
if useAdaptiveThresholds then
if rsiSlope > strongDevMult * rsiSlopeDev then 2
else if rsiSlope > mediumDevMult * rsiSlopeDev then 1
else if rsiSlope > -mediumDevMult * rsiSlopeDev then 0
else -1
else
fixedRsiSlopeScore;
AddLabel(showAnyLabel,
if showCompact then "RSI Slope: " + Round(rsiSlope, 2)
else "RSI Slope: " + Round(rsiSlope, 2) + " | " +
(if rsiSlopeScore == 2 then "Strong upward momentum – well above normal pressure."
else if rsiSlopeScore == 1 then "Moderate acceleration – stronger than recent trend."
else if rsiSlopeScore == 0 then "Neutral or slowing – momentum within recent range."
else "Momentum dropping – weaker than typical swings."),
if rsiSlopeScore == 2 then Color.GREEN
else if rsiSlopeScore == 1 then Color.LIGHT_GREEN
else if rsiSlopeScore == 0 then Color.YELLOW
else Color.RED
);
# === 🧮 Weighted Total Score ===
def baseScore =
(cmfScore * cmfWeight) +
(rsiSlopeScore * rsiSlopeWeight) +
(cmfSlopeScore * cmfSlopeWeight);
def finalScore = baseScore * bbwMultiplier;
# === 📊 Histogram Plot ===
plot ScoreHistogram = finalScore;
ScoreHistogram.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
ScoreHistogram.SetLineWeight(3);
ScoreHistogram.AssignValueColor(
if finalScore >= 6 then Color.GREEN
else if finalScore >= 4 then Color.CYAN
else if finalScore <= 1 then Color.RED
else Color.GRAY
);
# === 🏁 Composite Score Label ===
AddLabel(showAnyLabel,
if showCompact then "Score: " + Round(finalScore, 2)
else "Composite Score: " + Round(finalScore, 2) + " | " +
(if finalScore >= 6 then "High-Quality Momentum Zone"
else if finalScore >= 4 then "Strong Setup Building"
else if finalScore <= 1 then "Weak or Contradictory"
else "Neutral / In Transition"),
if finalScore >= 6 then Color.GREEN
else if finalScore >= 4 then Color.CYAN
else if finalScore <= 1 then Color.RED
else Color.GRAY
);
Last edited: