Repaints Mean Reversion Channel MTF for ThinkOrSwim

Repaints

samer800

Moderator - Expert
VIP
Lifetime
jzOijUB.png


Author Message:
Description :
Mean Reversion Channel objective, based on Mean Reversion theory ( everything has a tendency to revert back to its mean), is to help visualizing:
Inner Channel -> Dynamic Support and Resistance
Outer Channel -> Overbought/Oversold Zone which may signal consolidation phase or potential reversal due to unsustainable move

Details on some of the filtering type used for mean calculation can be read in Ehlers Technical Papers: "Swiss Army Knife Indicator" and/or his book "Cybernetics Analysis for Stock and Futures"

CODE:

CSS:
#// Author: ©fareidzulkifli
#https://www.tradingview.com/v/5uaoczeP/
#// Description :
#// Mean Reversion Channel objective, based on Mean Reversion theory (everything has a tendency to revert back to its mean), is to help visualizing:
#// Inner Channel -> Dynamic Support and Resistance
#// Outer Channel -> Overbought/Oversold Zone which may signal consolidation phase or potential reversal due to unsustainable move
#// The concept of this indicator oriiginally derived from Keltner Channel (The Keltner Channel was first introduced by Chester Keltner in the 1960s. The original formula used simple moving averages (SMA) and the high-low price range to calculate the bands. In the 1980s, a new formula was introduced that used ATR.)
#// Instead if using SMA/EMA, this indicator used SuperSmoother MA as it's mean with longer lookback period (default to 200) to get more stable channel line. i also added second level so the indicator will have inner and outer channel
#// Details of each filtering type used for mean calculation can be read in Ehlers Technical Papers: "Swiss Army Knife Indicator" and/or his book "Cybernetics Analysis for Stock and Futures"
#study("Mean Reversion Channel - MRI Variant", shorttitle="MRC", overlay=true, format=format.inherit)
#//****************************************
# Converted and mod by Sam4Cok@Samer800 - 02/2023
#//***************************************
input ShowLabel = yes;
input BarColor  = yes;
input source      = hlc3;#,               "Price Source"
input type        = {default "SuperSmoother", "Ehlers EMA", "Gaussian", "ButterWorth", "BandStop", "SMA", "EMA", "RMA"};    # "Filter Type"
input length      = 200;#                 "Lookback Period"
input innermult   = 1.0;#                 "Inner Channel Size Multiplier"
input outermult   = 2.415;#               "Outer Channel Size Multiplier"
input drawChannel = yes;#                 "Draw Channel"
input displayZone = yes;#                 "Draw Zone (With Channel)"
input ExtendLine = yes;#                 "Display Line Extension"
input UseChartTimeframe  = yes;#          "Enable Multiple TimeFrame Analysis"
input mtf_typ     = {default "Auto", "Custom"};  # "Multiple TimeFrame Type"
input CustomMTF   = AggregationPeriod.FIFTEEN_MIN; # "Custom MTF Level"

def na = Double.NaN;
def last = isNaN(close);
def Super = type == type."SuperSmoother";
def aggAuto = mtf_typ==mtf_typ."Auto";
def Current = GetAggregationPeriod();
def agg;
if aggAuto {
   agg = if Current < AggregationPeriod.FIVE_MIN then AggregationPeriod.FIVE_MIN else
         if Current < AggregationPeriod.FIFTEEN_MIN then AggregationPeriod.FIFTEEN_MIN else
         if Current < AggregationPeriod.HOUR then AggregationPeriod.HOUR else
         if Current < AggregationPeriod.FOUR_HOURS then AggregationPeriod.FOUR_HOURS else
         if Current < AggregationPeriod.DAY then AggregationPeriod.DAY else
         if Current < AggregationPeriod.FOUR_DAYS then AggregationPeriod.FOUR_DAYS else
         if Current < AggregationPeriod.WEEK then AggregationPeriod.WEEK else  
         if Current < AggregationPeriod.MONTH then AggregationPeriod.MONTH else Current;
    } else {
    agg = CustomMTF;
}
def tf = agg;
def src;
def c;
def h;
def l;
if UseChartTimeframe {
    src = source;
    c = close;
    h = high;
    l = low;
    } else {
    src = hlc3(Period=tf);
    c = hlc3(Period=tf);
    h = high(Period=tf);
    l = low(Period=tf);
}

#// Functions Start {
def pi          = Double.Pi;
def mult        = pi * innermult;
def mult2       = pi * outermult;
def gradsize    = 0.5;
#def gradtransp  = zonetransp;

#--- color
DefineGlobalColor("color1" , CreateColor(255,0,0));
DefineGlobalColor("color2" , CreateColor(255,66,0));
DefineGlobalColor("color3" , CreateColor(255,93,0));
DefineGlobalColor("color4" , CreateColor(255,116,0));
DefineGlobalColor("color5" , CreateColor(255,151,0));
DefineGlobalColor("color6" , CreateColor(255,174,0));
DefineGlobalColor("color7" , CreateColor(255,197,0));
DefineGlobalColor("color8" , CreateColor(255,205,0));
DefineGlobalColor("yellow" , CreateColor(255,205,0));
DefineGlobalColor("green" , CreateColor(76,175,80));
DefineGlobalColor("red"   , CreateColor(255,82,82));
#----
DefineGlobalColor("Green1" , CreateColor(1,255,0));
DefineGlobalColor("Green2" , CreateColor(5,217,4));
DefineGlobalColor("Green3" , CreateColor(4,181,4));
DefineGlobalColor("Green4" , CreateColor(3,145,3));
DefineGlobalColor("Green5" , CreateColor(2,117,2));
DefineGlobalColor("Red1" , CreateColor(255,5,5));
DefineGlobalColor("Red2" , CreateColor(214,6,6));
DefineGlobalColor("Red3" , CreateColor(184,6,6));
DefineGlobalColor("Red4" , CreateColor(145,3,3));
DefineGlobalColor("Red5" , CreateColor(117,2,2));

#// Ehler SwissArmyKnife Function
#SAK_smoothing(_type, _src, _length) =>
script SAK_smoothing {
    input _type = "SuperSmoother";
    input _Input = hlc3;
    input _length = 200;
    def sma = Average(_Input, _length);
    def ema = ExpAverage(_input, _length);
    def rma = WildersAverage(_input, _length);
    def pi  = Double.Pi;
    def c0;#          = 1.0
    def c1;#          = 0.0
    def b0;#          = 1.0
    def b1;#          = 0.0
    def b2;#          = 0.0
    def a1;#          = 0.0
    def a2;#          = 0.0
    def alpha;#       = 0.0
    def beta;#        = 0.0
    def gamma;#       = 0.0
    def cycle       = 2 * pi / _length;
    if _type == "Ehlers EMA" {
        alpha   = (Cos(cycle) + Sin(cycle) - 1) / Cos(cycle);
        b0      = alpha;
        a1      = 1 - alpha;
        c0      = 1.0;
        c1      = 0.0;
        b1      = 0.0;
        b2      = 0.0;
        a2      = 0.0;
        beta    = 0.0;
        gamma   = 0.0;
    } else
    if _type == "Gaussian" {
        beta    = 2.415 * (1 - Cos(cycle));
        alpha   = -beta + Sqrt((beta * beta) + (2 * beta));
        c0      = alpha * alpha;
        a1      = 2 * (1 - alpha);
        a2      = -(1 - alpha) * (1 - alpha);
        c1      = 0.0;
        b0      = 1.0;
        b1      = 0.0;
        b2      = 0.0;
        gamma   = 0.0;
    } else
    if _type == "ButterWorth" {
        beta    = 2.415 * (1 - Cos(cycle));
        alpha   = -beta + Sqrt((beta * beta) + (2 * beta));
        c0      = alpha * alpha / 4;
        b1      = 2;
        b2      = 1;
        a1      = 2 * (1 - alpha);
        a2      = -(1 - alpha) * (1 - alpha);
        c1      = 0.0;
        b0      = 1.0;
        gamma   = 0.0;
    } else
    if _type == "BandStop" {
        beta    = Cos(cycle);
        gamma   = 1 / Cos(cycle * 2 * 0.1);# // delta default to 0.1. Acceptable delta -- 0.05<d<0.5
        alpha   = gamma - Sqrt((gamma * gamma) - 1);
        c0      = (1 + alpha) / 2;
        b1      = -2 * beta;
        b2      = 1;
        a1      = beta * (1 + alpha);
        a2      = -alpha;
        c1      = 0.0;
        b0      = 1.0;
    } else {
        alpha   = 0.0;
        b0      = 1.0;
        a1      = 0.0;
        c0      = 1.0;
        c1      = 0.0;
        b1      = 0.0;
        b2      = 0.0;
        a2      = 0.0;
        beta    = 0.0;
        gamma   = 0.0;
    }
    def _Output;#      = 0.0
    _Output = (c0*((b0 * _Input) + (b1*_Input[1]) + (b2*_Input[2]))) + (a1*_Output[1]) + (a2*_Output[2]) - (c1*_Input[_length]);

    plot out = if _type == "SMA" then sma else
               if _type == "EMA" then ema else
               if _type == "RMA" then rma else _Output;
}
#/ SuperSmoother Function
#//-----------------------
script supersmoother {
    input _src = hlc3;
    input _length = 200;
def filt;
def a1 = Exp(-Double.Pi * Sqrt(2) /  _length);
def coeff2 = 2 * a1 * Cos(Sqrt(2) * Double.Pi / _length);
def coeff3 = - Sqr(a1);
def coeff1 = 1 - coeff2 - coeff3;
def filt1 = if isNaN(filt[1]) or filt[1]==0 then Average(_src[1], 14) else filt[1];
def filt2 = if isNaN(filt[2]) or filt[2]==0 then Average(_src[2], 14) else filt[2];
    filt = if IsNaN(_src+_src[1]) then filt1 else coeff1 * (_src + _src[1]) / 2 + coeff2 * filt1 + coeff3 * filt2;
    plot out = filt;
}
def v_condition;#
def v_upband2_1;
def v_upband2_9;
def v_loband2_1;
def v_loband2_9;
def v_meanline;# = source;
def tr1 = TrueRange(h, c, l);
def tr = if isNaN(c[1]) then h - l else tr1;
def v_meanrange   = supersmoother(tr, length);
def SuperSmoother = supersmoother(src, length);
def SAKsmoother = SAK_smoothing(type, src, length);
#    //-- Get Line value
    v_meanline = if Super then SuperSmoother else
                 if !Super then SAKsmoother else src;
#    v_meanline    = supersmoother(src, length);
#    } else {
#     v_meanline = SAK_smoothing(type, src, length);
#}
def v_upband1 = v_meanline + (v_meanrange * mult);
def v_loband1 = v_meanline - (v_meanrange * mult);
def v_upband2 = v_meanline + (v_meanrange * mult2);
def v_loband2 = v_meanline - (v_meanrange * mult2);
#    //-- Check Condition
if (c > v_meanline) {
    v_upband2_1 = v_upband2  + (v_meanrange * gradsize * 4);
    v_upband2_9 = v_upband2  + (v_meanrange * gradsize *-4);
    v_condition  = if (h >= v_upband2_9 and h < v_upband2) then 1 else
                       if (h >= v_upband2 and h < v_upband2_1) then 2 else
                       if (h >= v_upband2_1) then 3 else
                       if (c <= v_meanline + v_meanrange) then 4 else 5;
    v_loband2_1 = v_loband2_1[1];
    v_loband2_9 = v_loband2_9[1];
} else
    if (c < v_meanline) {
    v_loband2_1 = v_loband2  - (v_meanrange * gradsize * 4);
    v_loband2_9 = v_loband2  - (v_meanrange * gradsize * -4);
    v_condition = if (l <= v_loband2_9 and l > v_loband2) then -1 else
                      if (l <= v_loband2 and l > v_loband2_1) then -2 else
                      if (l <= v_loband2_1) then -3 else
                      if (c >= v_meanline + v_meanrange) then -4 else -5;
    v_upband2_1 = v_upband2_1[1];
    v_upband2_9 = v_upband2_9[1];
} else {
    v_upband2_1 = v_upband2_1[1];
    v_upband2_9 = v_upband2_9[1];
    v_loband2_1 = v_loband2_1[1];
    v_loband2_9 = v_loband2_9[1];
    v_condition = v_condition[1];
}
def meanrange = v_meanrange;
def meanline = if if(ExtendLine, 0, last) then na else v_meanline;
def upband1  = if if(ExtendLine, 0, last) then na else if if(drawChannel,1,last) then v_upband1 else na;
def loband1  = if if(ExtendLine, 0, last) then na else if if(drawChannel,1,last) then v_loband1 else na;
def upband2  = if if(ExtendLine, 0, last) then na else if if(drawChannel,1,last) then v_upband2 else na;
def loband2  = if if(ExtendLine, 0, last) then na else if if(drawChannel,1,last) then v_loband2 else na;
def _cond    = v_condition;
#// Drawing Start {
def p_meanline  = meanline;#if drawchannel then meanline   else na;
def p_upband1   = upband1;#if drawchannel then upband1    else na;
def p_loband1   = loband1;#if drawchannel then loband1    else na;
def p_upband2   = upband2;#if drawchannel then upband2    else na;
def p_loband2   = loband2;#if drawchannel then loband2    else na;

plot Mean  = p_meanline;#, color=#FFCD00,     style=plot.style_line,    title=" Mean", linewidth=2)
plot R1 = p_upband1;#,  color=color.green, style=plot.style_circles, title=" R1", linewidth=1, transp=50)
plot S1 = p_loband1;#,  color=color.green, style=plot.style_circles, title=" S1", linewidth=1, transp=50)
plot R2 = p_upband2;#,  color=color.red,   style=plot.style_line,    title=" R2", linewidth=1, transp=50)
plot S2 = p_loband2;#,  color=color.red,   style=plot.style_line,    title=" S2", linewidth=1, transp=50)
mean.SetDefaultColor(GlobalColor("yellow"));
R1.SetDefaultColor(GlobalColor("green"));
S1.SetDefaultColor(GlobalColor("green"));
R2.SetDefaultColor(GlobalColor("red"));
S2.SetDefaultColor(GlobalColor("red"));
def cond = drawchannel and displayzone and !last;

def upband2_1 = if cond then upband2 + (meanrange * gradsize * 4)  else na;
def loband2_1 = if cond then loband2 - (meanrange * gradsize * 4)  else na;
def upband2_2 = if cond then upband2 + (meanrange * gradsize * 3)  else na;
def loband2_2 = if cond then loband2 - (meanrange * gradsize * 3)  else na;
def upband2_3 = if cond then upband2 + (meanrange * gradsize * 2)  else na;
def loband2_3 = if cond then loband2 - (meanrange * gradsize * 2)  else na;
def upband2_4 = if cond then upband2 + (meanrange * gradsize * 1)  else na;
def loband2_4 = if cond then loband2 - (meanrange * gradsize * 1)  else na;
def upband2_5 = if cond then upband2 + (meanrange * gradsize * 0)  else na;
def loband2_5 = if cond then loband2 - (meanrange * gradsize * 0)  else na;
def upband2_6 = if cond then upband2 + (meanrange * gradsize * -1) else na;
def loband2_6 = if cond then loband2 - (meanrange * gradsize * -1) else na;
def upband2_7 = if cond then upband2 + (meanrange * gradsize * -2) else na;
def loband2_7 = if cond then loband2 - (meanrange * gradsize * -2) else na;
def upband2_8 = if cond then upband2 + (meanrange * gradsize * -3) else na;
def loband2_8 = if cond then loband2 - (meanrange * gradsize * -3) else na;
def upband2_9 = if cond then upband2 + (meanrange * gradsize * -4) else na;
def loband2_9 = if cond then loband2 - (meanrange * gradsize * -4) else na;

#//--- fill
AddCloud(upband2_1,upband2_2, GlobalColor("color1"), GlobalColor("color1"));
AddCloud(loband2_1,loband2_2, GlobalColor("color1"), GlobalColor("color1"));
AddCloud(upband2_2,upband2_3, GlobalColor("color2"), GlobalColor("color2"));
AddCloud(loband2_2,loband2_3, GlobalColor("color2"), GlobalColor("color2"));
AddCloud(upband2_3,upband2_4, GlobalColor("color3"), GlobalColor("color3"));
AddCloud(loband2_3,loband2_4, GlobalColor("color3"), GlobalColor("color3"));
AddCloud(upband2_4,upband2_5, GlobalColor("color4"), GlobalColor("color4"));
AddCloud(loband2_4,loband2_5, GlobalColor("color4"), GlobalColor("color4"));
AddCloud(upband2_5,upband2_6, GlobalColor("color5"), GlobalColor("color5"));
AddCloud(loband2_5,loband2_6, GlobalColor("color5"), GlobalColor("color5"));
AddCloud(upband2_6,upband2_7, GlobalColor("color6"), GlobalColor("color6"));
AddCloud(loband2_6,loband2_7, GlobalColor("color6"), GlobalColor("color6"));
AddCloud(upband2_7,upband2_8, GlobalColor("color7"), GlobalColor("color7"));
AddCloud(loband2_7,loband2_8, GlobalColor("color7"), GlobalColor("color7"));
AddCloud(upband2_8,upband2_9, GlobalColor("color8"), GlobalColor("color8"));
AddCloud(loband2_8,loband2_9, GlobalColor("color8"), GlobalColor("color8"));

#-- Label
AddLabel(ShowLabel,
     if (_cond == 1) then "Overbought (Weak)" else
     if (_cond == 2) then "Overbought" else
     if (_cond == 3) then "Overbought (Strong)" else
     if (_cond == 4) then "Price Near Mean" else
     if (_cond == 5) then "Price Above Mean" else
     if (_cond == -1) then "Oversold (Weak)" else
     if (_cond == -2) then "Oversold" else
     if (_cond == -3) then "Oversold (Strong)" else
     if (_cond == -4) then "Price Near Mean" else
     if (_cond == -5) then "Price Below Mean" else "Price at Mean Line", Color.WHITE);
#-- BarColor
AssignPriceColor(if !BarColor then Color.CURRENT else
     if (_cond == 1) then GlobalColor("green3") else
     if (_cond == 2) then GlobalColor("green2") else
     if (_cond == 3) then GlobalColor("green1") else
     if (_cond == 4) then GlobalColor("green5") else
     if (_cond == 5) then GlobalColor("green4") else
     if (_cond == -1) then GlobalColor("red3") else
     if (_cond == -2) then GlobalColor("red2") else
     if (_cond == -3) then GlobalColor("red1") else
     if (_cond == -4) then GlobalColor("red5") else
     if (_cond == -5) then GlobalColor("red4") else Color.GRAY);

#--- END Code
 
Last edited by a moderator:
@BenTen Hello. Can you please create a scanner for the Mean Reversion Channel above? I would like to scan for price below S2 and crossing above.
 
Last edited by a moderator:
@BenTen Hello. Can you please create a scanner for the Mean Reversion Channel above? I would like to scan for price below S2 and crossing above.
No, you cannot scan with this script.

This is an MTF indicator.
MTF scripts are not allowed in the scanner, watchlists, or conditional orders
It is because of the fundamental way that all ToS widgets works.
In the scan hacker, before you start to create the condition filters, you choose the aggregation period.
It is locked in.

After that, the scanner executes all filter conditions solely within the SINGLE aggregation chosen.
If the scanner encounters an aggregation period within the filter script that doesn't match what has already been chosen; it produces the error message: "secondary aggregations not allowed".

FYI, even if this was not an MTF indicator. It still could not be used in the scan hacker. It is too complex.
The scanner cannot handle complex scripts.
If you see a script and it is several hundred lines long, there is a good chance that it won't work in scanner, watchlists, or conditional orders. It can only be used to plot on a chart.
 
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
352 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