Momentum Conviction Scoring System For ThinkOrSwim

justAnotherTrader

Active member
VIP
VIP Enthusiast
8YWJ8hr.png


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

🚗 DriveReady Momentum Meter – For Traders Who Want Conviction, Not Just Motion


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:


🔋 RSI Slope – This is your throttle. It tells you whether traders are pressing the gas. Fast acceleration means we’re coming out of a base or pushing through a level. If it’s strong, you want to know. If it’s weak, you want to wait.


📉 CMF (Chaikin Money Flow) – This is your traction. Momentum without volume support is like spinning tires on ice. CMF gives you the conviction — price backed by real money.


📈 CMF Slope – This tells you if traction is getting better or worse. It’s a trend-of-conviction component, which helps you stick with a move that’s gaining volume interest or avoid one that’s peaking.


🛣️ BB Bandwidth – This is your road condition. Narrow roads (low BBW) suggest breakouts are near. Wide roads (high BBW) mean the vehicle needs serious horsepower to keep climbing. We use BBW as a multiplier to cap overly optimistic momentum scores when volatility is too high.


📊 Scoring Engine – Each of the three components gets scored (2, 1, 0, -1), then weighted. CMF gets the most weight, RSI slope slightly less, and CMF slope fills in the rest. The total score is dampened by BB bandwidth so you don’t get faked out by unstable terrain.


🧠 Adaptive or Static — Your Call
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.


🎯 Who This Is For
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:

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
262 Online
Create Post

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top