Adaptive Aroon, MACD, Schaff Trend Cycle, and Williams %R Indicators for ThinkOrSwim

Sesqui

Member
VIP
Screenshot from 2025-08-29 09-10-23.png


The indicators provided below use the dominant cycle period obtained from Dr Ehlers AutoCorrelationPeriodogram to make them adaptive to the market cycle. The screenshot above shows what they look like on the lower portion of the chart.

Here is the script code for each.

Adaptive Aroon Indicator:

CSS:
# Adaptive Aroon Indicator script by Sesqui 29AUG2025

declare lower;
input Beta = 1.0;
input showUpDownLines = no;
#===========================================================================================================================
script GetCycle {
    # Returns the dominant market cycle for use in adaptive indicators

    #------------------------------------------
    # Charles Schwab & Co. (c) 2016-2025
    #
    def lag = 48;
    def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
    def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) +  GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
    def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) +  GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
    def sqSum = Sqr(cosinePart) + Sqr(sinePart);

    plot Cycle = ExpAverage(sqSum, 9);
    #------------------------------------------
}# end Script GetCycle{}

script getOffsetToRecentMax {
    input CycleLength = 25;
    def Length = if IsNaN(Floor(CycleLength)) then Length[1] else Floor(CycleLength);
    def OffsetToRecentMax = fold i = 0 to Length with index = 0 do if GetValue(high, i) > GetValue(high, index) then index + 1 else index;
    plot BarsToMaxHigh = OffsetToRecentMax;
    BarsToMaxHigh.HideBubble();
}# end script getOffsetToRecentMax

#------------------------------------------------------

script getOffsetToRecentMin {
    input CycleLength = 25;
    def Length = if IsNaN(Floor(CycleLength)) then Length[1] else Floor(CycleLength);
    def OffsetToRecentMin = fold i = 0 to Length with index = 0 do if GetValue(low, i) < GetValue(low, index) then index + 1 else index;
    plot BarsToMaxLow = OffsetToRecentMin;
    BarsToMaxLow.HideBubble();
}# end script getOffsetToRecentMin

#==============================================================================================

def DCLength= GetCycle().Cycle;
def CycleLength = if IsNaN(Floor(DCLength)) then CycleLength[1] else Floor(DCLength);

def Up_ = (Floor(Beta*(CycleLength/2)) - 1 - getOffsetToRecentMax(Floor(Beta*(CycleLength/2)))) * 100.0 / (Floor(Beta*0.5*CycleLength) - 1);
def Down_ = (Floor(Beta*(CycleLength/2)) - 1 - getOffsetToRecentMin(Floor(Beta*(CycleLength/2)))) * 100.0 / (Floor(Beta*0.5*CycleLength) - 1);
plot Trend = Up_ - Down_;

Trend.AssignvalueColor(Color.PLUM);
Trend.SetLineWeight(2);

plot Up = if showUpDownLines then Up_ else Double.NaN;
plot Down = if showUpDownLines then Down_ else Double.NaN;

plot OverBought = 50;
plot OverSold = -50;

Up.SetDefaultColor(GetColor(1));
Down.SetDefaultColor(GetColor(5));
OverBought.SetDefaultColor(GetColor(8));
OverSold.SetDefaultColor(GetColor(8));


Adaptive MACD indicator:

CSS:
# Adaptive MACD (AMACD) script by Sesqui
# 5AUG2025

declare lower;
declare real_size;

input ShowHIST = yes;
input ShowZeroLine = yes;

#===========================================================================================================================
script GetCycle {
    # Returns the dominant market cycle for use in adaptive indicators

    #------------------------------------------
    # Charles Schwab & Co. (c) 2016-2025
    #

    def lag = 48;
    def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
    def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) +  GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
    def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) +  GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
    def sqSum = Sqr(cosinePart) + Sqr(sinePart);

    plot Cycle = ExpAverage(sqSum, 9);
    #----------------------------------------------
}# end Script GetCycle{}
#------------------------------------------------
script AdaptiveEMA {
    input src = close;
    input Cycle = 10;
    input numCycles = 1;

    def length = if IsNaN(Floor(numCycles * Cycle)) then length[1] else Floor(numCycles*Cycle);
    def ExpMovAvg = src*(1/(1+length))+ExpMovAvg[1]*(1-(1/(1+length)));
    plot EMA = ExpMovAvg;
    EMA.HideBubble();

}# endScript AdaptiveEMA{}

#------------------------------------------------
script AdaptiveMACD {
    # Computes the Adaptive MACD
    input fastLength = 3;
    input Cycle = 10; # pass Cycle into this parameter for adaptive MACD
    input SmoothLength = 16;
    input averageType = AverageType.EXPONENTIAL;

    def CycleLength = if IsNaN(Floor(Cycle)) then CycleLength[1] else Floor(Cycle);
    plot Value = MovingAverage(averageType, close, fastLength) - AdaptiveEMA(close, CycleLength).EMA;
 
    plot Avg = MovingAverage(averageType, Value, SmoothLength);

}# end AdaptiveMACD{}
#==============================================================================================

def CycleLength = GetCycle().Cycle;

plot val = AdaptiveMACD(3, CycleLength).Value;
plot ave = AdaptiveMACD(3, CycleLength).Avg;
plot Diff = if ShowHIST == 1 then val - ave else Double. NaN;
plot ZeroLine = if ShowZeroLine == 1 then 0 else Double.NaN;
ZeroLine.SetDefaultColor(GetColor(0));

val.SetDefaultColor(GetColor(1));
ave.SetDefaultColor(GetColor(8));
Diff.SetDefaultColor(GetColor(5));
Diff.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
Diff.SetLineWeight(3);
Diff.DefineColor("Positive and Up", Color.GREEN);
Diff.DefineColor("Positive and Down", Color.DARK_GREEN);
Diff.DefineColor("Negative and Down", Color.RED);
Diff.DefineColor("Negative and Up", Color.DARK_RED);
Diff.AssignValueColor(if Diff >= 0 then if Diff > Diff[1] then Diff.Color("Positive and Up") else Diff.Color("Positive and Down") else if Diff < Diff[1] then Diff.Color("Negative and Down") else Diff.Color("Negative and Up"));

AddCloud(val, ave, Color.GREEN, Color.RED);



Adaptive Williams % R indicator:

CSS:
# Adaptive Williams % R indicator script by Sesqui 29AUG2025
declare lower;

input length = 10;
input overBought = -20;
input overSold = -80;

#===========================================================================================================================
script GetCycle {
    # Returns the dominant market cycle for use in adaptive indicators

    #------------------------------------------
    # Charles Schwab & Co. (c) 2016-2025
    #
    def lag = 48;
    def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
    def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) +  GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
    def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) +  GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
    def sqSum = Sqr(cosinePart) + Sqr(sinePart);

    plot Cycle = ExpAverage(sqSum, 9);
    #-------------------------------------------
}# end Script GetCycle{}
#--------------
script get_Highest {
    input CycleLength = 10;
    input source = high;
    def length = if IsNaN(Floor(CycleLength)) then length[1] else Floor(CycleLength);
    def cur = source[0];
    def val = fold i = 0 to Length with max = cur do if max >= GetValue(source, i + 1) then max else GetValue(source, i+1);
    plot Highest = val;
    Highest.HideBubble();
}# end Script getHighest{}

#--------------
script get_Lowest {
    input CycleLength = 10;
    input source = low;
    def length = if IsNaN(Floor(CycleLength)) then length[1] else Floor(CycleLength);
    def cur = source[0];
    def val = fold i = 0 to Length with min = cur do if min <= GetValue(source, i + 1) then min else GetValue(source, i+1);
    plot Lowest = val;
    Lowest.HideBubble();
}# end Script getLowest{}

#==============================================================================================

def CycleLength = GetCycle().Cycle;

def hh = get_Highest(CycleLength, high);
def ll = get_Lowest(CycleLength, low);
def result = if hh == ll then -100 else (hh - close) / (hh - ll) * (-100);

plot WR = if result > 0 then 0 else result;
WR.SetDefaultColor(GetColor(1));

plot Over_Sold = overSold;
Over_Sold.SetDefaultColor(GetColor(8));

plot Over_Bought = overBought;
Over_Bought.SetDefaultColor(GetColor(8));


Adaptive Schaff Trend Cycle (ASTC) indicator:

CSS:
# Adaptive Schaff Trend Cycle script by Sesqui
# 25AUG2025

declare lower;

#===========================================================================================================================
script GetCycle {
    # Returns the dominant market cycle for use in adaptive indicators

    #------------------------------------------
    # Charles Schwab & Co. (c) 2016-2025
    #
    def lag = 48;
    def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
    def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) +  GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
    def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) +  GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
    def sqSum = Sqr(cosinePart) + Sqr(sinePart);

    plot Cycle = ExpAverage(sqSum, 9);
    #-------------------------------------------
}# end Script GetCycle{}
#------------------------------------------------
script AdaptiveEMA {
    input src = close;
    input Cycle = 10;
    input numCycles = 1;

    def length = if IsNaN(Floor(numCycles * Cycle)) then length[1] else Floor(numCycles*Cycle);
    def ExpMovAvg = src*(2/(1+length))+ExpMovAvg[1]*(1-(2/(1+length)));
    plot EMA = ExpMovAvg;
    EMA.HideBubble();

}# endScript AdaptiveEMA{}

#------------------------------------------------
script AdaptiveMACD {
    # Computes the Adaptive MACD
    input source = close;
    input fastLength = 3;
    input Cycle = 10; # pass Cycle into this parameter for adaptive MACD
    input SmoothLength = 16;
    input averageType = AverageType.EXPONENTIAL;

    def CycleLength = if IsNaN(Floor(Cycle)) then CycleLength[1] else Floor(Cycle);
    plot Value = MovingAverage(averageType, source, fastLength) - AdaptiveEMA(source, CycleLength).EMA;
 
    plot Avg = MovingAverage(averageType, Value, SmoothLength);

}# end AdaptiveMACD{}
#==============================================================================================

def CycleLength = GetCycle().Cycle;

input fastLength = 3;

input KPeriod = 5;
input DPeriod = 3;
input over_bought = 80;
input over_sold = 20;
input averageType = AverageType.EXPONENTIAL;

def STC_SOURCE = close;
def macd = AdaptiveMACD(STC_SOURCE, fastLength, CycleLength).Value;

def fastK1 = FastKCustom(macd, KPeriod);
def fastD1 = MovingAverage(averageType, fastK1, DPeriod);
def fastK2 = FastKCustom(fastD1, KPeriod);

plot STC = MovingAverage(averageType, fastK2, DPeriod);
STC.HideBubble();

plot CenterLine = 50;
CenterLine.HideBubble();
CenterLine.AssignValueColor(Color.GRAY);
CenterLine.SetPaintingStrategy(PaintingStrategy.DASHES);

plot OverBought = over_bought;
OverBought.HideBubble();

plot OverSold = over_sold;
OverSold.HideBubble();

STC.SetDefaultColor(GetColor(8));
OverBought.SetDefaultColor(GetColor(7));
OverSold.SetDefaultColor(GetColor(7));

def Diff = STC - STC[1];
STC.SetLineWeight(3);

STC.DefineColor("Positive and Up", Color.GREEN);
STC.DefineColor("Positive and Down", Color.DARK_GREEN);
STC.DefineColor("Negative and Down", Color.RED);
STC.DefineColor("Negative and Up", Color.DARK_RED);
STC.AssignValueColor(if Diff >= 0 then if Diff > Diff[1] then STC.color("Positive and Up") else STC.color("Positive and Down") else if Diff < Diff[1] then STC.color("Negative and Down") else STC.color("Negative and Up"));

AddCloud(OverSold,0,Color.LIGHT_GREEN);
AddCloud(100,OverBought,Color.LIGHT_RED);


Note: Articles from Dr Ehlers use arrays to normalize the periodogram data and then a center of gravity method to pin point the dominant cycle. However, thinkscript does not support arrays as needed to do the drill down further from the periodogram to the precise dominant cycle, per se. However, the cycle value provided by the periodogram in TOS appears to be capable of finding more trading opportunities than found with static fixed length values. Be sure to test it out before using it.
 
Last edited:

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

That indicator is the " Support and Resistance Levels with Breaks [LuxAlgo]" converted and mod by Sam4Cok@Samer800 - 01/2023 Update Added Fibo LEvel - 09/2023; with some minor modifications to make the red and green lines into zones.

Here is the script as-is displayed in the screenshot you are referring to:

CSS:
#// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
#// © LuxAlgo
#study(title=" Support and Resistance Levels with Breaks",shorttitle = " Support and Resistance Levels with Breaks [LuxAlgo]", overlay = true ,  max_bars_back=1000)
# Converted and mod by Sam4Cok@Samer800   - 01/2023
# Update Added Fibo LEvel - 09/2023

input TimeFrame = 1; # Use 1 = LTF, 2 = MTF and 3= HTF
input SupplyDemandAggro = AggregationPeriod.MIN;
input zoneThickness = 0.05;
input ShowLabels = no;
input PlotSupplyDemandZones = yes;
input ShowHhLlDOTS = yes;
input RepaintingType   = {default "Off: High & Low", "On", "Off: Candle Confirmation"};# 'Repainting'
input rightBars  = 1;#, title = "Right Bars")
input leftBars  = 1;#(15, title = "Left Bars ")


###------------------------------------------------------------------------------------------
input OpenTime = 900;   #hint OpenTime: Time you want backtesting to start the session at
input CloseTime = 1600;  #hint CloseTime: Time you want backtesting to stop the session at

def Begin = SecondsFromTime(OpenTime) + 60; #Note that then +60 limits this to using 1min candles
def End = SecondsTillTime(CloseTime);
# Only use market hours when using intraday timeframe
def isIntraDay = if GetAggregationPeriod() > 14400000 or GetAggregationPeriod() == 0 then 0 else 1;
def MarketOpen = if !isIntraDay then 1 else if isIntraDay and  Begin > 0 and End > 0 then 1 else 0;
###--------------------------------------------------------------------------------------------------

script fixnan {
    input source = close;
    def fix = if !IsNaN(source) then source else fix[1];
    plot result = fix;
}
#drawBox(condition, y1, y2, color) =>
script drawBox {
    input TimeFrame = 1;
    input aggro = AggregationPeriod.MIN;
    input condition = yes;
    input y1        = high;
    input y2        = low;
    def boxHi = if condition then y1 else boxHi[1];
    def boxLo = if condition then y2 else boxLo[1];
    def extension = if TimeFrame == 1 then 5 else if TimeFrame == 2 then 1 else if TimeFrame == 3 then 1 else 1;
    plot ph = if !IsNaN(close(period = aggro)[extension]) then if !boxHi then high(period = aggro) else boxHi else Double.NaN;
    plot pl = if !IsNaN(close(period = aggro)[extension]) then if !boxLo then low(period = aggro) else boxLo else Double.NaN;

}

#repaint(c1, c2, c3) =>
script repaint {
    input type = "On";
    input c1 = no;
    input c2 = no;
    input c3 = no;
    def rTon = type == "On";
    def rTcc = type == "Off: Candle Confirmation";
    def rThv = type == "Off: High & Low";
    def repaint = if rTon then c1 else if rThv then c2 else if rTcc then c3 else Double.NaN;
    plot out = repaint;
}
script FindPivots {
    input dat = close; # default data or study being evaluated
    input HL  = 0;    # default high or low pivot designation, -1 low, +1 high
    input lbL = 5;    # default Pivot Lookback Left
    input lbR = 1;    # default Pivot Lookback Right
    ##############
    def _nan;    # used for non-number returns
    def _BN;     # the current barnumber
    def _VStop;  # confirms that the lookforward period continues the pivot trend
    def _V;      # the Value at the actual pivot point
    ##############
    _BN  = BarNumber();
    _nan = Double.NaN;
    _VStop = if !IsNaN(dat) and lbR > 0 and lbL > 0 then
                fold a = 1 to lbR + 1 with b=1 while b do
                    if HL > 0 then dat > GetValue(dat, -a) else dat < GetValue(dat, -a) else _nan;
    if (HL > 0) {
        _V = if _BN > lbL and dat == Highest(dat, lbL + 1) and _VStop
            then dat else _nan;
    } else {
        _V = if _BN > lbL and dat == Lowest(dat, lbL + 1) and _VStop
            then dat else _nan;
    }
    plot result = if !IsNaN(_V) and _VStop then _V else _nan;
}# end script FindPivots{}

#===========================================================================
# Main Supply Demand Zones Computation is In This Section

def src = close(period = SupplyDemandAggro);
def na = Double.NaN;
def last = IsNaN(src);

def ph = FindPivots(high(period =  SupplyDemandAggro), 1 , leftBars, rightBars);
def pl = FindPivots(low(period =  SupplyDemandAggro), -1, leftBars, rightBars);
def highUsePivot = fixnan(ph);
def lowUsePivot  = fixnan(pl);
#// Box Height
def s_yLoc = if low(period =  SupplyDemandAggro)[1]  > low(period =  SupplyDemandAggro)[-1]  then low(period =  SupplyDemandAggro)[-1] else low(period =  SupplyDemandAggro)[1];
def r_yLoc = if high(period =  SupplyDemandAggro)[1] > high(period =  SupplyDemandAggro)[-1] then high(period =  SupplyDemandAggro)[1] else high(period =  SupplyDemandAggro)[-1];

def r1 = if MarketOpen and PlotSupplyDemandZones then drawBox(TimeFrame,  SupplyDemandAggro, (highUsePivot - highUsePivot[1]), highUsePivot, r_yLoc).ph else na;
#def r2 = if MarketOpen then drawBox2(TimeFrame, aggro, (highUsePivot - highUsePivot[1]), highUsePivot, r_yLoc).pl else na;
def r2 = if MarketOpen and PlotSupplyDemandZones then r1 - zoneThickness else na;

AddCloud(r1, r2, if TimeFrame == 3 then Color.YELLOW else if TimeFrame == 2 then Color.DARK_RED else if TimeFrame == 1 then CreateColor(255, 51, 51) else Color.RED);

#def s1 = if MarketOpen then drawBox(aggro, (lowUsePivot - lowUsePivot[1]), s_yLoc, lowUsePivot).ph else na;

def s2 = if MarketOpen and PlotSupplyDemandZones then drawBox(TimeFrame,  SupplyDemandAggro, (lowUsePivot - lowUsePivot[1]), s_yLoc, lowUsePivot).pl else na;
def s1 = if MarketOpen and PlotSupplyDemandZones then s2 + zoneThickness else na;

AddCloud(s1, s2, if TimeFrame == 3 then Color.PLUM else if TimeFrame == 2 then Color.DARK_GREEN else if TimeFrame == 1 then CreateColor(153, 255, 153) else Color.PLUM);

#=====================================================================================
# Dots are plotted in this section to indicate Demand Zones with Red Dots Above Bars
# And Supply Zones with Green Dots Below Bars

def hh = if MarketOpen and highUsePivot > highUsePivot[1] then highUsePivot else na;
def ll = if MarketOpen and lowUsePivot  < lowUsePivot[1]  then lowUsePivot else na;
def hl = if MarketOpen and lowUsePivot  > lowUsePivot[1]  then lowUsePivot else na;
def lh = if MarketOpen and highUsePivot < highUsePivot[1] then highUsePivot else na;

plot my_LL = if MarketOpen and ShowHhLlDOTS and ll then ll else Double.NaN;
my_LL.SetPaintingStrategy(PaintingStrategy.POINTS);
my_LL.AssignValueColor(Color.GREEN);
my_LL.SetLineWeight(5);
my_LL.HideBubble();

plot my_HL = if MarketOpen and ShowHhLlDOTS and hl then hl else Double.NaN;
my_HL.SetPaintingStrategy(PaintingStrategy.POINTS);
my_HL.AssignValueColor(Color.DARK_GREEN);
my_HL.SetLineWeight(5);
my_HL.HideBubble();

plot my_HH = if MarketOpen and ShowHhLlDOTS and hh then hh else Double.NaN;
my_HH.SetPaintingStrategy(PaintingStrategy.POINTS);
my_HH.AssignValueColor(Color.RED);
my_HH.SetLineWeight(5);
my_HH.HideBubble();

plot my_LH = if MarketOpen and ShowHhLlDOTS and lh then lh else Double.NaN;
my_LH.SetPaintingStrategy(PaintingStrategy.POINTS);
my_LH.AssignValueColor(Color.DARK_RED);
my_LH.SetLineWeight(5);
my_LH.HideBubble();


#-- END of Code
 
@Sesqui

Static lengths are an indicator killer, so your Adaptive Cycle script could be a game changer.

But I am struggling, to understand the implementation throughout your various scripts.
For example:
If you are going to create an AdaptiveEMA subscript;
Why only use it for one of the EMA calculations?
And then create an additional MACD subscript to calculate the other moving averages.

Rich (BB code):
# Is this subscript necessary?
script AdaptiveMACD {
    # Computes the Adaptive MACD
    input fastLength = 3;
    input Cycle = 10; # pass Cycle into this parameter for adaptive MACD
    input SmoothLength = 16;
    input averageType = AverageType.EXPONENTIAL;

    def CycleLength = if IsNaN(Floor(Cycle)) then CycleLength[1] else Floor(Cycle);

    plot Value = MovingAverage(averageType, close, fastLength) #AdaptiveEMA NOT used here
-AdaptiveEMA(close, CycleLength).EMA;  #AdaptiveEMA used here
  
    plot Avg = MovingAverage(averageType, Value, SmoothLength); #AdaptiveEMA NOT used here

}# end AdaptiveMACD{}

The ToS inability to define variables with constants has been a barrier to creating dynamic lagging indicators.
I am hoping you can explain how you chose to implement your subscript; to provide better understanding.


Thank you for walking me through this exciting development.
 
Last edited:
MerryDay, Good catch pointing out that the adaptive MACD script only used one adaptive EMA in its formula. The script was biased in favor of my own preferences having been trading much prior with a static MACD(3,10,16). As a result, when I made this adaptive MACD I kept the fastLength set at 3 because that worked for my purposes. Thus only the MACD's slowLength was adaptively set to the CycleLength.
With respect to the last line in the script which also uses a non-adaptive moving average, my rationale was that moving average is simply a smoothing function to smooth out the MACD signal before plotting it. I liked 16 so kept it that way.

However, for those who would prefer an adaptive MACD that connects the slowLength, fastLength and smoothing Length of the MACD to a function of the Cycle Length, here is a script that helps to do that. Hope this helps!


CSS:
# FULLY Adaptive MACD (AMACD) script by Sesqui
# 1SEP2025

declare lower;
declare real_size;

input FastMACDLengthCycleFactor = 0.333;
input MACDSmoothingLengthFactor = 0.50;

input ShowHIST = yes;
input ShowZeroLine = yes;

#===========================================================================================================================
script GetCycle {
    # Returns the dominant market cycle for use in adaptive indicators

    #------------------------------------------
    # Charles Schwab & Co. (c) 2016-2025
    #

    def lag = 48;
    def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
    def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) +  GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
    def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) +  GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
    def sqSum = Sqr(cosinePart) + Sqr(sinePart);

    plot Cycle = ExpAverage(sqSum, 9);
    #----------------------------------------------
}# end Script GetCycle{}
#------------------------------------------------
script AdaptiveEMA {
    input src = close;
    input Cycle = 10;
    input numCycles = 1;

    def length = if IsNaN(Floor(numCycles * Cycle)) then length[1] else Floor(numCycles*Cycle);
    def ExpMovAvg = src*(2/(1+length))+ExpMovAvg[1]*(1-(2/(1+length)));
    plot EMA = ExpMovAvg;
    EMA.HideBubble();

}# endScript AdaptiveEMA{}

#------------------------------------------------
script AdaptiveMACD {
    # Computes the Adaptive MACD
    input fastLength = 3;
    input Cycle = 10; # pass Cycle into this parameter for adaptive MACD
    input SmoothLength = 16;
    input averageType = AverageType.EXPONENTIAL;

    def CycleLength = if IsNaN(Floor(Cycle)) then CycleLength[1] else Floor(Cycle);
    #plot Value = MovingAverage(averageType, close, fastLength) - AdaptiveEMA(close, CycleLength).EMA;
    plot Value = AdaptiveEMA(close,fastLength).EMA - AdaptiveEMA(close, CycleLength).EMA;
    
    #plot Avg = MovingAverage(averageType, Value, SmoothLength);
    plot Avg = AdaptiveEMA(value,SmoothLength).EMA;

}# end AdaptiveMACD{}
#==============================================================================================

def Cycle = GetCycle().Cycle;

def CycleLength = if IsNaN(Floor(Cycle)) then CycleLength[1] else Floor(Cycle);

plot val = AdaptiveMACD( CycleLength*FastMACDLengthCycleFactor , CycleLength, CycleLength*MACDSmoothingLengthFactor).Value;
plot ave = AdaptiveMACD(CycleLength*FastMACDLengthCycleFactor , CycleLength, CycleLength*MACDSmoothingLengthFactor).Avg;
plot Diff = if ShowHIST == 1 then val - ave else Double. NaN;
plot ZeroLine = if ShowZeroLine == 1 then 0 else Double.NaN;
ZeroLine.SetDefaultColor(GetColor(0));

val.SetDefaultColor(GetColor(1));
ave.SetDefaultColor(GetColor(8));
Diff.SetDefaultColor(GetColor(5));
Diff.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
Diff.SetLineWeight(3);
Diff.DefineColor("Positive and Up", Color.GREEN);
Diff.DefineColor("Positive and Down", Color.DARK_GREEN);
Diff.DefineColor("Negative and Down", Color.RED);
Diff.DefineColor("Negative and Up", Color.DARK_RED);
Diff.AssignValueColor(if Diff >= 0 then if Diff > Diff[1] then Diff.Color("Positive and Up") else Diff.Color("Positive and Down") else if Diff < Diff[1] then Diff.Color("Negative and Down") else Diff.Color("Negative and Up"));

AddCloud(val, ave, Color.GREEN, Color.RED);
 
@Sesqui Thank you for the quick response. I wanted to make sure that there was not a computational reason for the multi-prong approach.

I agree, the dynamic cycle subscript would not be appropriate for smoothing, which should be a fixed length.

Over on the VIP forum, you will notice almost all indicators use Ehlers Smoother
Check it out:
https://usethinkscript.com/threads/smoothing-calculation.21513/

I have used Gaussian and other smoothers and have found the above to provide the least lag and most efficient solution
 
That indicator is the " Support and Resistance Levels with Breaks [LuxAlgo]" converted and mod by Sam4Cok@Samer800 - 01/2023 Update Added Fibo LEvel - 09/2023; with some minor modifications to make the red and green lines into zones.

Here is the script as-is displayed in the screenshot you are referring to:

CSS:
#// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
#// © LuxAlgo
#study(title=" Support and Resistance Levels with Breaks",shorttitle = " Support and Resistance Levels with Breaks [LuxAlgo]", overlay = true ,  max_bars_back=1000)
# Converted and mod by Sam4Cok@Samer800   - 01/2023
# Update Added Fibo LEvel - 09/2023

input TimeFrame = 1; # Use 1 = LTF, 2 = MTF and 3= HTF
input SupplyDemandAggro = AggregationPeriod.MIN;
input zoneThickness = 0.05;
input ShowLabels = no;
input PlotSupplyDemandZones = yes;
input ShowHhLlDOTS = yes;
input RepaintingType   = {default "Off: High & Low", "On", "Off: Candle Confirmation"};# 'Repainting'
input rightBars  = 1;#, title = "Right Bars")
input leftBars  = 1;#(15, title = "Left Bars ")


###------------------------------------------------------------------------------------------
input OpenTime = 900;   #hint OpenTime: Time you want backtesting to start the session at
input CloseTime = 1600;  #hint CloseTime: Time you want backtesting to stop the session at

def Begin = SecondsFromTime(OpenTime) + 60; #Note that then +60 limits this to using 1min candles
def End = SecondsTillTime(CloseTime);
# Only use market hours when using intraday timeframe
def isIntraDay = if GetAggregationPeriod() > 14400000 or GetAggregationPeriod() == 0 then 0 else 1;
def MarketOpen = if !isIntraDay then 1 else if isIntraDay and  Begin > 0 and End > 0 then 1 else 0;
###--------------------------------------------------------------------------------------------------

script fixnan {
    input source = close;
    def fix = if !IsNaN(source) then source else fix[1];
    plot result = fix;
}
#drawBox(condition, y1, y2, color) =>
script drawBox {
    input TimeFrame = 1;
    input aggro = AggregationPeriod.MIN;
    input condition = yes;
    input y1        = high;
    input y2        = low;
    def boxHi = if condition then y1 else boxHi[1];
    def boxLo = if condition then y2 else boxLo[1];
    def extension = if TimeFrame == 1 then 5 else if TimeFrame == 2 then 1 else if TimeFrame == 3 then 1 else 1;
    plot ph = if !IsNaN(close(period = aggro)[extension]) then if !boxHi then high(period = aggro) else boxHi else Double.NaN;
    plot pl = if !IsNaN(close(period = aggro)[extension]) then if !boxLo then low(period = aggro) else boxLo else Double.NaN;

}

#repaint(c1, c2, c3) =>
script repaint {
    input type = "On";
    input c1 = no;
    input c2 = no;
    input c3 = no;
    def rTon = type == "On";
    def rTcc = type == "Off: Candle Confirmation";
    def rThv = type == "Off: High & Low";
    def repaint = if rTon then c1 else if rThv then c2 else if rTcc then c3 else Double.NaN;
    plot out = repaint;
}
script FindPivots {
    input dat = close; # default data or study being evaluated
    input HL  = 0;    # default high or low pivot designation, -1 low, +1 high
    input lbL = 5;    # default Pivot Lookback Left
    input lbR = 1;    # default Pivot Lookback Right
    ##############
    def _nan;    # used for non-number returns
    def _BN;     # the current barnumber
    def _VStop;  # confirms that the lookforward period continues the pivot trend
    def _V;      # the Value at the actual pivot point
    ##############
    _BN  = BarNumber();
    _nan = Double.NaN;
    _VStop = if !IsNaN(dat) and lbR > 0 and lbL > 0 then
                fold a = 1 to lbR + 1 with b=1 while b do
                    if HL > 0 then dat > GetValue(dat, -a) else dat < GetValue(dat, -a) else _nan;
    if (HL > 0) {
        _V = if _BN > lbL and dat == Highest(dat, lbL + 1) and _VStop
            then dat else _nan;
    } else {
        _V = if _BN > lbL and dat == Lowest(dat, lbL + 1) and _VStop
            then dat else _nan;
    }
    plot result = if !IsNaN(_V) and _VStop then _V else _nan;
}# end script FindPivots{}

#===========================================================================
# Main Supply Demand Zones Computation is In This Section

def src = close(period = SupplyDemandAggro);
def na = Double.NaN;
def last = IsNaN(src);

def ph = FindPivots(high(period =  SupplyDemandAggro), 1 , leftBars, rightBars);
def pl = FindPivots(low(period =  SupplyDemandAggro), -1, leftBars, rightBars);
def highUsePivot = fixnan(ph);
def lowUsePivot  = fixnan(pl);
#// Box Height
def s_yLoc = if low(period =  SupplyDemandAggro)[1]  > low(period =  SupplyDemandAggro)[-1]  then low(period =  SupplyDemandAggro)[-1] else low(period =  SupplyDemandAggro)[1];
def r_yLoc = if high(period =  SupplyDemandAggro)[1] > high(period =  SupplyDemandAggro)[-1] then high(period =  SupplyDemandAggro)[1] else high(period =  SupplyDemandAggro)[-1];

def r1 = if MarketOpen and PlotSupplyDemandZones then drawBox(TimeFrame,  SupplyDemandAggro, (highUsePivot - highUsePivot[1]), highUsePivot, r_yLoc).ph else na;
#def r2 = if MarketOpen then drawBox2(TimeFrame, aggro, (highUsePivot - highUsePivot[1]), highUsePivot, r_yLoc).pl else na;
def r2 = if MarketOpen and PlotSupplyDemandZones then r1 - zoneThickness else na;

AddCloud(r1, r2, if TimeFrame == 3 then Color.YELLOW else if TimeFrame == 2 then Color.DARK_RED else if TimeFrame == 1 then CreateColor(255, 51, 51) else Color.RED);

#def s1 = if MarketOpen then drawBox(aggro, (lowUsePivot - lowUsePivot[1]), s_yLoc, lowUsePivot).ph else na;

def s2 = if MarketOpen and PlotSupplyDemandZones then drawBox(TimeFrame,  SupplyDemandAggro, (lowUsePivot - lowUsePivot[1]), s_yLoc, lowUsePivot).pl else na;
def s1 = if MarketOpen and PlotSupplyDemandZones then s2 + zoneThickness else na;

AddCloud(s1, s2, if TimeFrame == 3 then Color.PLUM else if TimeFrame == 2 then Color.DARK_GREEN else if TimeFrame == 1 then CreateColor(153, 255, 153) else Color.PLUM);

#=====================================================================================
# Dots are plotted in this section to indicate Demand Zones with Red Dots Above Bars
# And Supply Zones with Green Dots Below Bars

def hh = if MarketOpen and highUsePivot > highUsePivot[1] then highUsePivot else na;
def ll = if MarketOpen and lowUsePivot  < lowUsePivot[1]  then lowUsePivot else na;
def hl = if MarketOpen and lowUsePivot  > lowUsePivot[1]  then lowUsePivot else na;
def lh = if MarketOpen and highUsePivot < highUsePivot[1] then highUsePivot else na;

plot my_LL = if MarketOpen and ShowHhLlDOTS and ll then ll else Double.NaN;
my_LL.SetPaintingStrategy(PaintingStrategy.POINTS);
my_LL.AssignValueColor(Color.GREEN);
my_LL.SetLineWeight(5);
my_LL.HideBubble();

plot my_HL = if MarketOpen and ShowHhLlDOTS and hl then hl else Double.NaN;
my_HL.SetPaintingStrategy(PaintingStrategy.POINTS);
my_HL.AssignValueColor(Color.DARK_GREEN);
my_HL.SetLineWeight(5);
my_HL.HideBubble();

plot my_HH = if MarketOpen and ShowHhLlDOTS and hh then hh else Double.NaN;
my_HH.SetPaintingStrategy(PaintingStrategy.POINTS);
my_HH.AssignValueColor(Color.RED);
my_HH.SetLineWeight(5);
my_HH.HideBubble();

plot my_LH = if MarketOpen and ShowHhLlDOTS and lh then lh else Double.NaN;
my_LH.SetPaintingStrategy(PaintingStrategy.POINTS);
my_LH.AssignValueColor(Color.DARK_RED);
my_LH.SetLineWeight(5);
my_LH.HideBubble();


#-- END of Code
Thank you for the code. For some reason, my chart doesn't show them.
Also, would you have a code for the lower indicator, Volume Price Analysis?
Thank you.
 
@Sesqui can you share the upper part of the script for the chart please.

View attachment 25588

The indicators provided below use the dominant cycle period obtained from Dr Ehlers AutoCorrelationPeriodogram to make them adaptive to the market cycle. The screenshot above shows what they look like on the lower portion of the chart.

Here is the script code for each.

Adaptive Aroon Indicator:

CSS:
# Adaptive Aroon Indicator script by Sesqui 29AUG2025

declare lower;
input Beta = 1.0;
input showUpDownLines = no;
#===========================================================================================================================
script GetCycle {
    # Returns the dominant market cycle for use in adaptive indicators

    #------------------------------------------
    # Charles Schwab & Co. (c) 2016-2025
    #
    def lag = 48;
    def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
    def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) +  GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
    def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) +  GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
    def sqSum = Sqr(cosinePart) + Sqr(sinePart);

    plot Cycle = ExpAverage(sqSum, 9);
    #------------------------------------------
}# end Script GetCycle{}

script getOffsetToRecentMax {
    input CycleLength = 25;
    def Length = if IsNaN(Floor(CycleLength)) then Length[1] else Floor(CycleLength);
    def OffsetToRecentMax = fold i = 0 to Length with index = 0 do if GetValue(high, i) > GetValue(high, index) then index + 1 else index;
    plot BarsToMaxHigh = OffsetToRecentMax;
    BarsToMaxHigh.HideBubble();
}# end script getOffsetToRecentMax

#------------------------------------------------------

script getOffsetToRecentMin {
    input CycleLength = 25;
    def Length = if IsNaN(Floor(CycleLength)) then Length[1] else Floor(CycleLength);
    def OffsetToRecentMin = fold i = 0 to Length with index = 0 do if GetValue(low, i) < GetValue(low, index) then index + 1 else index;
    plot BarsToMaxLow = OffsetToRecentMin;
    BarsToMaxLow.HideBubble();
}# end script getOffsetToRecentMin

#==============================================================================================

def DCLength= GetCycle().Cycle;
def CycleLength = if IsNaN(Floor(DCLength)) then CycleLength[1] else Floor(DCLength);

def Up_ = (Floor(Beta*(CycleLength/2)) - 1 - getOffsetToRecentMax(Floor(Beta*(CycleLength/2)))) * 100.0 / (Floor(Beta*0.5*CycleLength) - 1);
def Down_ = (Floor(Beta*(CycleLength/2)) - 1 - getOffsetToRecentMin(Floor(Beta*(CycleLength/2)))) * 100.0 / (Floor(Beta*0.5*CycleLength) - 1);
plot Trend = Up_ - Down_;

Trend.AssignvalueColor(Color.PLUM);
Trend.SetLineWeight(2);

plot Up = if showUpDownLines then Up_ else Double.NaN;
plot Down = if showUpDownLines then Down_ else Double.NaN;

plot OverBought = 50;
plot OverSold = -50;

Up.SetDefaultColor(GetColor(1));
Down.SetDefaultColor(GetColor(5));
OverBought.SetDefaultColor(GetColor(8));
OverSold.SetDefaultColor(GetColor(8));


Adaptive MACD indicator:

CSS:
# Adaptive MACD (AMACD) script by Sesqui
# 5AUG2025

declare lower;
declare real_size;

input ShowHIST = yes;
input ShowZeroLine = yes;

#===========================================================================================================================
script GetCycle {
    # Returns the dominant market cycle for use in adaptive indicators

    #------------------------------------------
    # Charles Schwab & Co. (c) 2016-2025
    #

    def lag = 48;
    def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
    def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) +  GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
    def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) +  GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
    def sqSum = Sqr(cosinePart) + Sqr(sinePart);

    plot Cycle = ExpAverage(sqSum, 9);
    #----------------------------------------------
}# end Script GetCycle{}
#------------------------------------------------
script AdaptiveEMA {
    input src = close;
    input Cycle = 10;
    input numCycles = 1;

    def length = if IsNaN(Floor(numCycles * Cycle)) then length[1] else Floor(numCycles*Cycle);
    def ExpMovAvg = src*(2/(1+length))+ExpMovAvg[1]*(1-(2/(1+length)));
    plot EMA = ExpMovAvg;
    EMA.HideBubble();

}# endScript AdaptiveEMA{}

#------------------------------------------------
script AdaptiveMACD {
    # Computes the Adaptive MACD
    input fastLength = 3;
    input Cycle = 10; # pass Cycle into this parameter for adaptive MACD
    input SmoothLength = 16;
    input averageType = AverageType.EXPONENTIAL;

    def CycleLength = if IsNaN(Floor(Cycle)) then CycleLength[1] else Floor(Cycle);
    plot Value = MovingAverage(averageType, close, fastLength) - AdaptiveEMA(close, CycleLength).EMA;
   
    plot Avg = MovingAverage(averageType, Value, SmoothLength);

}# end AdaptiveMACD{}
#==============================================================================================

def CycleLength = GetCycle().Cycle;

plot val = AdaptiveMACD(3, CycleLength).Value;
plot ave = AdaptiveMACD(3, CycleLength).Avg;
plot Diff = if ShowHIST == 1 then val - ave else Double. NaN;
plot ZeroLine = if ShowZeroLine == 1 then 0 else Double.NaN;
ZeroLine.SetDefaultColor(GetColor(0));

val.SetDefaultColor(GetColor(1));
ave.SetDefaultColor(GetColor(8));
Diff.SetDefaultColor(GetColor(5));
Diff.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
Diff.SetLineWeight(3);
Diff.DefineColor("Positive and Up", Color.GREEN);
Diff.DefineColor("Positive and Down", Color.DARK_GREEN);
Diff.DefineColor("Negative and Down", Color.RED);
Diff.DefineColor("Negative and Up", Color.DARK_RED);
Diff.AssignValueColor(if Diff >= 0 then if Diff > Diff[1] then Diff.Color("Positive and Up") else Diff.Color("Positive and Down") else if Diff < Diff[1] then Diff.Color("Negative and Down") else Diff.Color("Negative and Up"));

AddCloud(val, ave, Color.GREEN, Color.RED);



Adaptive Williams % R indicator:

CSS:
# Adpative Aroon Indicator script by Sesqui 29AUG2025
declare lower;

input length = 10;
input overBought = -20;
input overSold = -80;

#===========================================================================================================================
script GetCycle {
    # Returns the dominant market cycle for use in adaptive indicators

    #------------------------------------------
    # Charles Schwab & Co. (c) 2016-2025
    #
    def lag = 48;
    def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
    def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) +  GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
    def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) +  GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
    def sqSum = Sqr(cosinePart) + Sqr(sinePart);

    plot Cycle = ExpAverage(sqSum, 9);
    #-------------------------------------------
}# end Script GetCycle{}
#--------------
script get_Highest {
    input CycleLength = 10;
    input source = high;
    def length = if IsNaN(Floor(CycleLength)) then length[1] else Floor(CycleLength);
    def cur = source[0];
    def val = fold i = 0 to Length with max = cur do if max >= GetValue(source, i + 1) then max else GetValue(source, i+1);
    plot Highest = val;
    Highest.HideBubble();
}# end Script getHighest{}

#--------------
script get_Lowest {
    input CycleLength = 10;
    input source = low;
    def length = if IsNaN(Floor(CycleLength)) then length[1] else Floor(CycleLength);
    def cur = source[0];
    def val = fold i = 0 to Length with min = cur do if min <= GetValue(source, i + 1) then min else GetValue(source, i+1);
    plot Lowest = val;
    Lowest.HideBubble();
}# end Script getLowest{}

#==============================================================================================

def CycleLength = GetCycle().Cycle;

def hh = get_Highest(CycleLength, high);
def ll = get_Lowest(CycleLength, low);
def result = if hh == ll then -100 else (hh - close) / (hh - ll) * (-100);

plot WR = if result > 0 then 0 else result;
WR.SetDefaultColor(GetColor(1));

plot Over_Sold = overSold;
Over_Sold.SetDefaultColor(GetColor(8));

plot Over_Bought = overBought;
Over_Bought.SetDefaultColor(GetColor(8));


Adaptive Schaff Trend Cycle (ASTC) indicator:

CSS:
# Adaptive Schaff Trend Cycle script by Sesqui
# 25AUG2025

declare lower;

#===========================================================================================================================
script GetCycle {
    # Returns the dominant market cycle for use in adaptive indicators

    #------------------------------------------
    # Charles Schwab & Co. (c) 2016-2025
    #
    def lag = 48;
    def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
    def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) +  GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
    def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) +  GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
    def sqSum = Sqr(cosinePart) + Sqr(sinePart);

    plot Cycle = ExpAverage(sqSum, 9);
    #-------------------------------------------
}# end Script GetCycle{}
#------------------------------------------------
script AdaptiveEMA {
    input src = close;
    input Cycle = 10;
    input numCycles = 1;

    def length = if IsNaN(Floor(numCycles * Cycle)) then length[1] else Floor(numCycles*Cycle);
    def ExpMovAvg = src*(2/(1+length))+ExpMovAvg[1]*(1-(2/(1+length)));
    plot EMA = ExpMovAvg;
    EMA.HideBubble();

}# endScript AdaptiveEMA{}

#------------------------------------------------
script AdaptiveMACD {
    # Computes the Adaptive MACD
    input source = close;
    input fastLength = 3;
    input Cycle = 10; # pass Cycle into this parameter for adaptive MACD
    input SmoothLength = 16;
    input averageType = AverageType.EXPONENTIAL;

    def CycleLength = if IsNaN(Floor(Cycle)) then CycleLength[1] else Floor(Cycle);
    plot Value = MovingAverage(averageType, source, fastLength) - AdaptiveEMA(source, CycleLength).EMA;
   
    plot Avg = MovingAverage(averageType, Value, SmoothLength);

}# end AdaptiveMACD{}
#==============================================================================================

def CycleLength = GetCycle().Cycle;

input fastLength = 3;

input KPeriod = 5;
input DPeriod = 3;
input over_bought = 80;
input over_sold = 20;
input averageType = AverageType.EXPONENTIAL;

def STC_SOURCE = close;
def macd = AdaptiveMACD(STC_SOURCE, fastLength, CycleLength).Value;

def fastK1 = FastKCustom(macd, KPeriod);
def fastD1 = MovingAverage(averageType, fastK1, DPeriod);
def fastK2 = FastKCustom(fastD1, KPeriod);

plot STC = MovingAverage(averageType, fastK2, DPeriod);
STC.HideBubble();

plot CenterLine = 50;
CenterLine.HideBubble();
CenterLine.AssignValueColor(Color.GRAY);
CenterLine.SetPaintingStrategy(PaintingStrategy.DASHES);

plot OverBought = over_bought;
OverBought.HideBubble();

plot OverSold = over_sold;
OverSold.HideBubble();

STC.SetDefaultColor(GetColor(8));
OverBought.SetDefaultColor(GetColor(7));
OverSold.SetDefaultColor(GetColor(7));

def Diff = STC - STC[1];
STC.SetLineWeight(3);

STC.DefineColor("Positive and Up", Color.GREEN);
STC.DefineColor("Positive and Down", Color.DARK_GREEN);
STC.DefineColor("Negative and Down", Color.RED);
STC.DefineColor("Negative and Up", Color.DARK_RED);
STC.AssignValueColor(if Diff >= 0 then if Diff > Diff[1] then STC.color("Positive and Up") else STC.color("Positive and Down") else if Diff < Diff[1] then STC.color("Negative and Down") else STC.color("Negative and Up"));

AddCloud(OverSold,0,Color.LIGHT_GREEN);
AddCloud(100,OverBought,Color.LIGHT_RED);
can you share upper part of the chart
 
@Sesqui - Can you share the TOS chart link that we can import in TOS so that all the studies get in. Appreciate your help and I am looking forward to testing this.

 
@Sesqui:

Adaptive Williams % R indicator:

CSS:Copy to clipboard
# Adpative Aroon Indicator script by Sesqui 29AUG2025
declare lower;

Ok- The script says %R, but the code is fo Adaptive Aroon indicator- am I missing something??
 
@Sesqui:

Adaptive Williams % R indicator:

CSS:Copy to clipboard
# Adpative Aroon Indicator script by Sesqui 29AUG2025
declare lower;

Ok- The script says %R, but the code is fo Adaptive Aroon indicator- am I missing something??

It is true that the header in the %R indicator is mislabeled. Understandable given that @Sesqui mass-produced so many excellent indicators.

It does appear to be a Williams %R study. Were you expecting it to behave differently?
Scroll 3/4 down the beginning post and re-copy and paste...
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

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