The Ultimate Oscillator For ThinkOrSwim

SethW446

New member
VIP
Distinct from Larry Williams version, to TOS from TradingView. It is found in Technical Analysis of Stocks and Commodities for March 2025 on p. 45.
The author states: This script implements an alternative, refined version of the Ultimate Oscillator (UO) designed to reduce lag and enhance responsiveness in momentum indicators.

Ehlers states that indicators are essentially filters that remove unwanted noise (i.e., unnecessary information) from market data. Simply put, they process a series of data to place focus on specific information, providing a different perspective on price dynamics.

Ehlers explains that the key to removing indicator lag is to combine filters of different types in such a way that the result preserves necessary, useful signals while minimizing delay (lag).

S5s7eVI.png


Here is the original Tradingview code:
https://www.tradingview.com/script/sVP0SZo5-TASC-2025-04-The-Ultimate-Oscillator/


For the new ThinkOrSwim code, you must scroll down to the next post
 
Last edited by a moderator:

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

Please convert John Ehler's Ultimate Oscillator
https://www.tradingview.com/script/sVP0SZo5-TASC-2025-04-The-Ultimate-Oscillator/
, distinct from Larry Williams version, to TOS from TradingView. It is found in Technical Analysis of Stocks and Commodities for March 2025 on p. 45. Thanks
Code:
// TASC Issue: April 2025
// Article: Less Lag In Momentum Indicators
// The Ultimate Oscillator
// Article By: John F. Ehlers
// Language: TradingView's Pine Script® v6
// Provided By: PineCoders, for TradingView.com
//@version=6
title ="TASC 2025.04 Less Lag In Momentum Indicators" +
"The Ultimate Oscillator"
stitle = "UO"
indicator(title, stitle, false)
// import library for RMS function
import TradingView/ta/9 as ta
// @function High Pass Filter.
HP (float src, int Period) =>
float a0 = math.pi * math.sqrt(2.0) / Period
float a1 = math.exp(-a0)
float c2 = 2.0 * a1 * math.cos(a0)
float c3 = -a1 * a1
float c1 = (1.0 + c2 - c3) * 0.25
float hp = 0.0
if bar_index >= 4
hp := c1 * (src - 2.0 * src[1] + src[2]) +
c2 * nz(hp[1]) + c3 * nz(hp[2])
hp
UO (float src, int Bandwidth=2, int BandEdge=20) =>
float HP1 = HP(src, Bandwidth * BandEdge)
float HP2 = HP(src, BandEdge)
float Signal = HP1 - HP2
float RMS = ta.rms(Signal, 100)
float UO = RMS == 0 ? 0 : Signal / RMS
UO
float src = input.source(close, 'Source:')
int Bandwidth = input.int(2, 'Bandwidth:')
int BandEdge = input.int(20, 'BandEdge:')
UO = UO (src, Bandwidth, BandEdge)
plot(UO , 'Ultimate Oscillator', color.red, 2)
hline(0)
check the below:

CSS:
#// Indicator for TOS
#// © PineCodersTASC
#//  TASC Issue: April 2025
#//     Article: Less Lag In Momentum Indicators
#//              The Ultimate Oscillator
#//  Article By: John F. Ehlers
#//    Language: TradingView's Pine Script® v6
#// Provided By: PineCoders, for tradingview.com
# title ="TASC 2025.04 The Ultimate Oscillator", title = "UO"
# Converted by Sam4Cok@Samer800    - 03/2025
Declare lower;

input timeframe = AggregationPeriod.MIN;
input colorBars = yes;
input Source = FundamentalType.CLOSE; #, "Source:")
input BandWidth = 2.0; # "Bandwidth:", 1.4, step = 0.1)
input BandEdge = 20; #, "BandEdge:", 3)
input cloudType = {"Bandwidth", "BandEdge", "Bandwidth + BandEdge", default "None"}; # "Cloud: ", options = )

def na = Double.NaN;
def last = IsNaN(close);
def GAP = GetAggregationPeriod();
def tf = MAX(GAP, timeframe);
def src = Fundamental(Source, Period = tf);
##// ~~ Gradient Coloring {
Script gradient_color {
input src = close;
input minVal = 10;
input maxVal = 400;
input loR = 173;
input loG = 216;
input loB = 230;
input hiR = 41;
input hiG = 98;
input hiB = 255;
    def value = if isNaN(src) then 0 else src;
    def clamped_value = max(min(value, maxVal), minVal);
    def normalized_value = (clamped_value - minVal) / (maxVal - minVal);
    def re = floor(loR + (hiR - loR) * normalized_value);
    def gr = floor(loG + (hiG - loG) * normalized_value);
    def bl = floor(loB + (hiB - loB) * normalized_value);
    plot r = re;
    plot g = gr;
    plot b = bl;
}
#// @function      Calculates a second-order highpass filter.
script HP {
    input src = close;
    input period = 20;
    def bar = bar[1] + 1;
    def pi = Double.Pi;
    def sq2 = sqrt(2.0);
    def a1 = exp(-sq2 * pi / period);
    def c2 =  2.0 * a1 * cos(sq2 * pi / period);
    def c3 = - power(a1, 2);
    def c1 = (1 + c2 - c3) * 0.25;
    def hp1 = c1 * (src - 2 * src[1] + src[2]) + c2 * hp1[1] + c3 * hp1[2];
    def hp = if bar >= 4 then c1 * (src - 2 * src[1] + src[2]) + c2 * hp[1] + c3 * hp[2] else hp1;
    plot out = hp;
}
#// @function   Calculates the Ultimate Oscillator.
Script UO {
input src = close;
input bw = 2;
input be = 20;
    def hp1 = HP(src, bw * be);
    def hp2 = HP(src,      be);
    def signal = hp1 - hp2;
    def rms  = sqrt(sum(power(signal, 2), 100) / 100);
    def UO = if rms == 0 then 0 else signal / rms;
    plot out = UO;
}
#// @function  Calculates 10 UO series with varying Bandwidth and BandEdge values.
def both = cloudType==cloudType."Bandwidth + BandEdge";
def modBW = cloudType==cloudType."Bandwidth" or both;
def modBE = cloudType==cloudType."BandEdge" or both;
def minBW = if modBW then max(Bandwidth * 0.5, 1.4) else Bandwidth;
def minBE = if modBE then max(BandEdge * 0.5, 3) else BandEdge;
def bwStep = (Bandwidth - minBW) / 5;
def beStep = (BandEdge - minBE) / 5;
def result0 = UO(src, minBW, minBE);
def result1 = UO(src, minBW + 1 * bwStep, minBE + 1 * beStep);
def result2 = UO(src, minBW + 2 * bwStep, minBE + 2 * beStep);
def result3 = UO(src, minBW + 3 * bwStep, minBE + 3 * beStep);
def result4 = UO(src, minBW + 4 * bwStep, minBE + 4 * beStep);
def result5 = UO(src, minBW + 5 * bwStep, minBE + 5 * beStep);
def result6 = UO(src, minBW + 6 * bwStep, minBE + 6 * beStep);
def result7 = UO(src, minBW + 7 * bwStep, minBE + 7 * beStep);
def result8 = UO(src, minBW + 8 * bwStep, minBE + 8 * beStep);
def result9 = UO(src, minBW + 9 * bwStep, minBE + 9 * beStep);

def max1 = Max(result0, Max(result1, Max(result2, Max(result3, result4))));
def max2 = Max(result5, Max(result6, Max(result7, Max(result8, result9))));
def min1 = Min(result0, Min(result1, Min(result2, Min(result3, result4))));
def min2 = Min(result5, Min(result6, Min(result7, Min(result8, result9))));
def cloudValuesMax = Max(max1, max2);
def cloudValuesMin = Min(min1, min2);
#// @variable The UO of the `src` series based on the input settings.
def UO = UO(src, Bandwidth, BandEdge);
#// Calculate the maximum and minimum UO values for the cloud display.
def cloudMax = max(cloudValuesMax, UO);
def cloudMin = min(cloudValuesMin, UO);
#// @variable The sum of each oscillator's polarity.
def sgnCountU = sign(UO);
def sgnCount0 = sign(result0);
def sgnCount1 = sign(result1);
def sgnCount2 = sign(result2);
def sgnCount3 = sign(result3);
def sgnCount4 = sign(result4);
def sgnCount5 = sign(result5);
def sgnCount6 = sign(result6);
def sgnCount7 = sign(result7);
def sgnCount8 = sign(result8);
def sgnCount9 = sign(result9);

def sgnCount = sgnCountU + sgnCount0 + sgnCount1 + sgnCount2 + sgnCount3 + sgnCount4 +
               sgnCount5 + sgnCount6 + sgnCount7 + sgnCount8 + sgnCount9;

def colR = gradient_color(sgnCount, -11, 11, 158, 12, 12, 12, 158, 12).r;
def colG = gradient_color(sgnCount, -11, 11, 158, 12, 12, 12, 158, 12).g;
def colB = gradient_color(sgnCount, -11, 11, 158, 12, 12, 12, 158, 12).b;

#// Plot the `UO`.
plot UltimateOsc = if !last then UO else na; # "Ultimate Oscillator"
#// Plot the `cloudMax` and `cloudMin` and fill their space with the `fillColor`.
plot maxCloud = if !last then cloudMax else na; # "Cloud max"
plot minCloud = if !last then cloudMin else na; # "Cloud min"
#-- zero Line
plot zero = if !last then 0 else na;

UltimateOsc.SetLineWeight(3);
zero.SetStyle(Curve.SHORT_DASH);
UltimateOsc.AssignValueColor(CreateColor(colR, colG, colB));
zero.SetDefaultColor(Color.DARK_GRAY);
maxCloud.SetDefaultColor(Color.GRAY);
minCloud.SetDefaultColor(Color.GRAY);

#-- Cloud

AddCloud(if (sgnCount > 0 or sgnCount[-1] > 0) then maxCloud else na, minCloud, Color.DARK_GREEN);
AddCloud(if sgnCount > 6 then maxCloud else na, minCloud, Color.DARK_GREEN);
AddCloud(if (sgnCount < 0 or sgnCount[-1] < 0) then maxCloud else na, minCloud, Color.DARK_RED);
AddCloud(if sgnCount < -6 then maxCloud else na, minCloud, Color.DARK_RED);

AddCloud(if sgnCount > 0 and last[-2] then maxCloud else na, minCloud, Color.DARK_GREEN);
AddCloud(if sgnCount < 0 and last[-2] then maxCloud else na, minCloud, Color.DARK_RED);
#-- Bar Color

AssignPriceColor(if !colorBars then Color.CURRENT else CreateColor(colR, colG, colB));

#--END of CODE
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
814 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