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: