Range Oscillator Conversion for Thinkorswim

chewie76

Well-known member
VIP
VIP Enthusiast
1762536498226.png

Range Oscillator (Zeiierman) is a dynamic market oscillator designed to visualize how far the price is trading relative to its equilibrium range.

This is a conversion where I added a histogram to indicate the candle's strength or weakness. Over or under 200, are extreme levels.

Instead of relying on traditional overbought/oversold thresholds, it uses adaptive range detection and heatmap coloring to reveal where price is trading within a volatility-adjusted band.

The oscillator maps market movement as a heat zone, highlighting when the price approaches the upper or lower range boundaries and signaling potential breakout or mean-reversion conditions.

Highlights
  • Adaptive range detection based on ATR and weighted price movement.
  • Heatmap-driven coloring that visualizes volatility pressure and directional bias.
  • Clear transition zones for detecting trend shifts and equilibrium points.
How It Works

⚪ Range Detection
The indicator identifies a dynamic price range using two main parameters:
  • Minimum Range Length: The number of bars required to confirm that a valid range exists.
  • Range Width Multiplier: Expands or contracts the detected range proportionally to the ATR (Average True Range).
This approach ensures that the oscillator automatically adapts to both trending and ranging markets without manual recalibration.

⚪ Weighted Mean Calculation
Instead of a simple moving average, the script calculates a weighted equilibrium mean based on the size of consecutive candle movements:
  • Larger price changes are given greater weight, emphasizing recent volatility.
The Range Oscillator source code can be found here. https://www.tradingview.com/script/mlL8CpJq-Range-Oscillator-Zeiierman/


Code:
# Range Oscillator (Zeiierman) - ThinkScript Conversion
# Assembled by Chewie
declare lower;

#---- Inputs ----#
input length = 50;
input mult = 2.0;
input atrLength = 200;
input fillOpacity = 60;          # 0–100 visual strength of shaded fill
input backgroundIsDark = yes;    # set to 'no' for white/light chart backgrounds

# Base RGB color settings
input strongBull_R = 0;
input strongBull_G = 180;
input strongBull_B = 0;

input strongBear_R = 180;
input strongBear_G = 0;
input strongBear_B = 0;

input weakBull_R = 0;
input weakBull_G = 128;
input weakBull_B = 0;

input weakBear_R = 128;
input weakBear_G = 0;
input weakBear_B = 0;

input transition_R = 0;
input transition_G = 0;
input transition_B = 255;

#---- Core Calculations ----#
def ATR = MovingAverage(AverageType.WILDERS, TrueRange(high, close, low), atrLength);
def rangeATR = ATR * mult;

# Weighted moving average using GetValue()
def sumWeightedClose = fold idx1 = 0 to length - 1
    with acc = 0
    do acc + (AbsValue(GetValue(close, idx1) - GetValue(close, idx1 + 1)) / GetValue(close, idx1 + 1)) * GetValue(close, idx1);

def sumWeights = fold idx2 = 0 to length - 1
    with acc2 = 0
    do acc2 + AbsValue(GetValue(close, idx2) - GetValue(close, idx2 + 1)) / GetValue(close, idx2 + 1);

def ma = if sumWeights != 0 then sumWeightedClose / sumWeights else Double.NaN;

# Max distance over the lookback
def maxDist = fold idx3 = 0 to length - 1
    with m = 0
    do Max(m, AbsValue(GetValue(close, idx3) - ma));

def inRange = maxDist <= rangeATR;

# Trend direction
def trendDir = if close > ma then 1 else if close < ma then -1 else trendDir[1];

# Oscillator
def osc1 = if rangeATR != 0 then 100 * (close - ma) / rangeATR else Double.NaN;

def breakUp = close > ma + rangeATR;
def breakDn = close < ma - rangeATR;

#---- Simulated Opacity Blend ----#
def w = Max(0, Min(1, fillOpacity / 100));
def bgR = if backgroundIsDark then 0 else 255;
def bgG = if backgroundIsDark then 0 else 255;
def bgB = if backgroundIsDark then 0 else 255;

def bullFillR = Round(strongBull_R * w + bgR * (1 - w), 0);
def bullFillG = Round(strongBull_G * w + bgG * (1 - w), 0);
def bullFillB = Round(strongBull_B * w + bgB * (1 - w), 0);

def bearFillR = Round(strongBear_R * w + bgR * (1 - w), 0);
def bearFillG = Round(strongBear_G * w + bgG * (1 - w), 0);
def bearFillB = Round(strongBear_B * w + bgB * (1 - w), 0);

#---- Plot and Color Logic ----#
plot Osc = osc1;
Osc.SetLineWeight(2);
Osc.AssignValueColor(
    if breakUp then CreateColor(strongBull_R, strongBull_G, strongBull_B)
    else if breakDn then CreateColor(strongBear_R, strongBear_G, strongBear_B)
    else if trendDir > 0 then CreateColor(weakBull_R, weakBull_G, weakBull_B)
    else if trendDir < 0 then CreateColor(weakBear_R, weakBear_G, weakBear_B)
    else CreateColor(transition_R, transition_G, transition_B)
);

plot OSC2 = osc1;
osc2.SetPaintingStrategy( PaintingStrategy.HISTOGRAM ); #else if osc2 > 0 and osc2 < 100 then color.dark_green else if osc2 < -100 then color.red else if osc2 > -100 and < 0 then color.dark_red else color.current
osc2.assignvalueColor(if osc2 > 200 then color.cyan else if osc2 < -200 then color.magenta else if osc2 > 100 and osc2 < 200 then color.green else if osc2 > 0 and osc2 < 100 then color.dark_green else if osc2 < -100 and osc2 > -200 then color.red else if osc2 > -100 and osc2 < 0 then color.dark_red else color.current);
# Reference Lines
plot Upper = 100;
plot Lower = -100;
plot ZeroLine = 0;
Upper.SetDefaultColor(Color.GRAY);
Lower.SetDefaultColor(Color.GRAY);
ZeroLine.SetDefaultColor(Color.gray);


#---- Shaded Fills ----#
# Bullish fill above zero
AddCloud(
    if osc >= 0 then osc else Double.NaN,
    0,
    CreateColor(bullFillR, bullFillG, bullFillB),
    CreateColor(bullFillR, bullFillG, bullFillB)
);

# Bearish fill below zero
AddCloud(
    if osc <= 0 then osc else Double.NaN,
    0,
    CreateColor(bearFillR, bearFillG, bearFillB),
    CreateColor(bearFillR, bearFillG, bearFillB)
);

# Optional highlight clouds for extreme zones
AddCloud(
    if osc > 100 then osc else Double.NaN,
    100,
    CreateColor(strongBull_R, strongBull_G, strongBull_B),
    CreateColor(strongBull_R, strongBull_G, strongBull_B)
);
AddCloud(
    if osc < -100 then osc else Double.NaN,
    -100,
    CreateColor(strongBear_R, strongBear_G, strongBear_B),
    CreateColor(strongBear_R, strongBear_G, strongBear_B)
);
 
Last edited:

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

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
724 Online
Create Post

Similar threads

Similar threads

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