The RSI is awesome, but the Chande Momentum Oscillator is awesomer!!! The Chande Momentum Oscillator (CMO) is a technical analysis indicator created by Tushar Chande that measures pure momentum in a security’s price, oscillating between +100 and -100.
It’s similar in spirit to RSI, but instead of comparing average gains and losses, it adds up all price changes (up and down) over a period and divides the net change by the total absolute changes — giving a percentage measure of net momentum.
In the chart below of TSLA, I have marked areas in the dashed lines of an aggressive entry/exit and solid lines a more conservative entry/exit examples using the supply and demand zones as final criterias
shared chart link: https://tos.mx/!CadtYHzG
Script for this indicator can found below
mod note:
Oscillator Formula
For a chosen period n:
CMO=100×Sum of Gains over n−Sum of Losses
Where the formula calculates the Sum of Gains = sum of all positive price changes during n and divides by the Sum of Losses = sum of absolute values of all negative price changes during n.
Key Characteristics
-100 = extreme downward momentum (all periods were down)
0 = equal gains and losses over the period
Below -50 → strong bearish momentum
Crosses above 0 → momentum turning bullish
Crosses below 0 → momentum turning bearish
-50 to -100 can be oversold
But thresholds can be adjusted depending on volatility.
How I use it to trade:
It’s similar in spirit to RSI, but instead of comparing average gains and losses, it adds up all price changes (up and down) over a period and divides the net change by the total absolute changes — giving a percentage measure of net momentum.
In the chart below of TSLA, I have marked areas in the dashed lines of an aggressive entry/exit and solid lines a more conservative entry/exit examples using the supply and demand zones as final criterias
shared chart link: https://tos.mx/!CadtYHzG
Script for this indicator can found below
mod note:
Oscillator Formula
For a chosen period n:
CMO=100×Sum of Gains over n−Sum of Losses
Where the formula calculates the Sum of Gains = sum of all positive price changes during n and divides by the Sum of Losses = sum of absolute values of all negative price changes during n.
Key Characteristics
- Bounded Range:
-100 = extreme downward momentum (all periods were down)
0 = equal gains and losses over the period
- Faster than RSI:
- Interpretation Zones:
Below -50 → strong bearish momentum
Crosses above 0 → momentum turning bullish
Crosses below 0 → momentum turning bearish
- Overbought/Oversold:
-50 to -100 can be oversold
But thresholds can be adjusted depending on volatility.
How I use it to trade:
- Trend Confirmation: If CMO is above zero during an uptrend, momentum is aligned.
- Overbought/Oversold Reversals: Look for extreme readings followed by a cross back toward zero.
- Divergence: When price makes new highs/lows but CMO fails to confirm.
Code:
# ------------------------------------------------
# adapted from Charles Schwab TOS
# Enhanced Chande Momentum Oscillator with Bias & Slope Alerts
# v.1 08/12/2025 enhanced by antwerks
# ------------------------------------------------
declare lower;
input length = 20;
input neutralZone = 5; # Near zero tolerance
def inc = Max(close - close[1], 0);
def dec = Max(close[1] - close, 0);
def sumInc = Sum(inc, length);
def sumDec = Sum(dec, length);
def CMOvalue = if (sumInc + sumDec) == 0 then 0 else (sumInc - sumDec) / (sumInc + sumDec) * 100;
plot CMO = CMOvalue;
CMO.SetLineWeight(2);
CMO.AssignValueColor(
if CMOvalue > neutralZone then Color.GREEN
else if CMOvalue < -neutralZone then Color.RED
else Color.YELLOW
);
plot ZeroLine = 0; ZeroLine.SetDefaultColor(Color.GRAY);
plot UpperLevel = 50; UpperLevel.SetDefaultColor(Color.GRAY);
plot LowerLevel = -50; LowerLevel.SetDefaultColor(Color.GRAY);
# --- Trend slope detection ---
def slopeUp = CMOvalue > CMOvalue[1];
def slopeDown = CMOvalue < CMOvalue[1];
# --- Labels based on momentum + slope ---
AddLabel(
yes,
if CMOvalue >= 50 then "VERY BULLISH"
else if CMOvalue > 0 and slopeUp then "BULLISH"
else if CMOvalue > 0 and slopeDown then "BULLISH BUT TRENDING DOWN"
else if CMOvalue <= -50 then "STRONGLY BEARISH"
else if CMOvalue < 0 and slopeDown then "BEARISH"
else if CMOvalue < 0 and slopeUp then "BEARISH BUT TRENDING UP"
else "NEUTRAL",
if CMOvalue >= 50 then Color.DARK_GREEN
else if CMOvalue > 0 and slopeUp then Color.GREEN
else if CMOvalue > 0 and slopeDown then Color.ORANGE
else if CMOvalue <= -50 then Color.RED
else if CMOvalue < 0 and slopeDown then Color.RED
else if CMOvalue < 0 and slopeUp then Color.CYAN
else Color.YELLOW
);
# --- Alerts ---
Alert(CMOvalue > 0 and slopeDown, "Bullish but trending down", Alert.BAR, Sound.Chimes);
Alert(CMOvalue < 0 and slopeUp, "Bearish but trending up", Alert.BAR, Sound.Bell);
Last edited by a moderator: