#// 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