Candlestick Channels return channels whose extremities converge towards the price when a corresponding candlestick pattern is detected. This allows for us to obtain more reactive extremities in the presence of a cluster of candlestick patterns.
The detected candlestick patterns are also highlighted with labels on your chart automatically.
Settings
- Trend Length: Period of the stochastic oscillator used to determine trend sentiment; this sentiment is used to detect certain candlestick patterns.(RSI, OBV and CCI Options added as well).
- Convergence: Convergence percentage of the channel extremities used during the occurrence of a candlestick pattern. A lower value will return extremities converging more slowly toward the price.
- Smooth: Determines the degree of smoothness of the channel extremities.
- Option to switch between channel mode to SuperTrend mode.
Code:
CSS:
#indicator("Candlestick Channels [LUX]", overlay = true, max_labels_count = 500)
#indicator("SuperTrend+", overlay = true, format=format.price, precision=2)
# combined candlestick channel and supertrend+
# Created by Sam4Cok@Samer800 - 09/2022
#//------------------------------------------------------------------------------
#//Settings
#//-----------------------------------------------------------------------------{
input Mode = {SuperTrend,Default Channel};
#//Patterns
input enable_hammer = yes; #'Hammer'
input enable_ihammer = yes; #'Inverted Hammer'
input enable_shooting = yes; #'Shooting Star'
input enable_hanging = yes; #'Hanging Man'
input enable_bulleng = no; #'Bullish Engulfing'
input enable_beareng = no; #'Bearish Engulfing'
input enable_wm = yes; #'White Marubozu'
input enable_bm = yes; #'Black Marubozu'
input maType = {"VAWMA", "eVWMA",default "SMMA", "EMA", "TEMA", "WMA", "VWMA", "SMA", "HMA", "McGinley"};
input atrPeriod = 20; # Period use in calculating the ATR value.
input maxDeviation = 0; # The max deviation of true range before being considered and outlier
input closeBars = 2; # Closed bars that have to exceed the ST value before the trend reversal is confirmed
input Wicks = yes;
input showsignals = no; # Show Buy/Sell Bubble
input showBand = yes;
input showCloud = yes;
input CandlestickBubble = yes;
input TrendFilter = {Default Stochastic, RSI, OBV, CCI};
input TrendLength = 14; # 'Trend Length'
input alpha = 50; # 'Convergence'
input smooth = 7; # 'Smooth'
def na = Double.NaN;
DefineGlobalColor("green", CreateColor(76, 175, 80));
DefineGlobalColor("red", CreateColor(255, 82, 82));
#//-----------------------------------------------------------------------------}
#//Variables/Functions
#//-----------------------------------------------------------------------------{
def n = BarNumber();
def o = open;
def h = if Wicks then high else max(close, open);
def l = if Wicks then low else min(close, open);
def c = close;
def v = volume;
# stoch(source, high, low, length) =>
script stoch {
input src = close;
input h = high;
input l = low;
input len = 0;
def stoch = 100 * (src - Lowest(l, len)) / (Highest(h, len) - Lowest(l, len));
plot return = stoch;
}
#----- Scripts----
script nz {
input data = close;
input repl = 0;
def ret_val = if IsNaN(data) then repl else data;
plot return = ret_val;
}
#naOutliers( src, len, maxDeviation = 4)=>
script naOutliers {
input src = close;
input len = 120;
input maxDeviation = 0;
def prev = src[1];# // ignore current in measurment as it could throw off result.
def avg = SimpleMovingAvg(prev, len);
def dev = StDev(prev, len) * maxDeviation;
def upper = avg + dev;
def lower = avg - dev;
def newUpper;
def newLower;
newUpper = if IsNaN(newUpper[1]) then upper else
if prev >= newUpper[1]
then upper else if(isNaN(newUpper[1]), upper,newUpper[1]);
newLower = if isNaN(newLower[1]) then lower else
if prev <= newLower[1]
then lower else if(isNaN(newLower[1]),lower,newLower[1]);
def newSrcUp = newUpper;
def newStcDn = newLower;
def naOutliers = if src > upper then newSrcUp else
if src < lower then newStcDn else src;
plot return = naOutliers;
}
#------------scripts-----------
# vawma(src, len) =>
script vawma {
input src = hlc3;
input len = 50;
def sum; def vol; def v;
def s = fold i = 0 to len with p do
src[i];
def volm = if IsNaN(volm[1]) then 0 else
fold j = 0 to len with u do
volume[j];
def ma = if !IsNaN(s) and !IsNaN(volm) then
fold k = 0 to len with w do
len - k else 0;
v = fold l=1 to len with q do
if IsNaN(v[1]) then volm else
volume * ma;
vol = fold m = 0 to len with r do
r + v[m];
sum = fold n = 0 to len with t do
t + src[n] * v[n];
plot vawma = sum/vol;
}
#vwma(source, length)
script VWMA {
input x = close;
input y = 15;
def VWMA = SimpleMovingAvg(x * volume, y) / SimpleMovingAvg(volume, y);
plot result = VWMA;
}
#ma(mode, len, src) =>
script ma {
input type = "EMA";
input src = close;
input len = 100;
def volumeSum = Sum(volume, len);
def evwma = ((volumeSum - volume) * nz(evwma[1]) + volume * src) / volumeSum;
def e = ExpAverage(src, len);
def Mcg = if IsNaN(Mcg[1]) then Average(src, len) else
CompoundValue(1, Mcg[1] + ((src - Mcg[1]) / (0.6 * len * Power(src / Mcg[1], 4))), src);
def ma;
ma = if type == "SMA" then SimpleMovingAvg(src, len) else
if type == "VAWMA" then vawma(src, len) else
if type == "EMA" then ExpAverage(src, len) else
if type == "TEMA" then 3 * (e - ExpAverage(e, len)) + ExpAverage(ExpAverage(e, len), len) else
if type == "WMA" then WMA(src, len) else
if type == "VWMA" then vwma(src, len) else
if type == "SMMA" then WildersSmoothing(src, len) else
if type == "HMA" then WMA(2 * WMA(src, len / 2) - WMA(src, len), Round(Sqrt(len), 0)) else
if type == "eVWMA" then evwma else
if type == "McGinley" then Mcg else Double.NaN;
plot result = ma;
}
#----- Trend
def tr = if IsNaN(close[1]) then high - low else TrueRange(high, close, low);
def trCleaned = if maxDeviation == 0 then tr else naOutliers(tr, atrPeriod, maxDeviation);
def atATR = ma(maType , trCleaned, atrPeriod);
def getATR = atATR;
def change = c-c[1];
def obv = if TotalSum(change) > 0 then v else if change < 0 then -v else 0*v;
def obvFast = ExpAverage(obv, 2);
def obvSlow = ExpAverage(obv, 14);
def obvlong = obvFast > obvSlow;
def obvshort = obvFast < obvSlow;
def nATR = getATR / 2;
def nRSI = RSI(length=Trendlength);
def nCCI = CCI(length=Trendlength);
def Stoc = stoch(c, c, c, Trendlength);
def downtrend = if TrendFilter == TrendFilter.Stochastic then Stoc < 50 else
if TrendFilter == TrendFilter.RSI then nRSI < 50 else
if TrendFilter == TrendFilter.CCI then nCCI < 0 else obvshort;
def uptrendd = if TrendFilter == TrendFilter.Stochastic then Stoc > 50 else
if TrendFilter == TrendFilter.RSI then nRSI > 50 else
if TrendFilter == TrendFilter.CCI then nCCI > 0 else obvlong;
def d = AbsValue(c - o);
#-----------------------------------------------------------------------------}
#Pattern Rules
#-----------------------------------------------------------------------------{
def hammer = downtrend and Min(o, c) - l > 2 * d and h - Max(c, o) < d / 4;
def ihammer = downtrend and h - Max(o, c) > 2 * d and Min(c, o) - l < d / 4;
def bulleng = downtrend and c > o and c[1] < o[1] and c > o[1] and d > nATR;
def wm = downtrend[1] and c > o and h - Max(o, c) + Min(o, c) - l < d / 10 and d > nATR;
#---------------------------------------------------------------------------
def shooting = uptrendd and h - Max(o, c) > 2 * d and Min(c, o) - l < d / 4;
def hanging = uptrendd and Min(o, c) - l > 2 * d and h - Max(c, o) < d / 4;
def beareng = uptrendd and c < o and c[1] > o[1] and c < o[1] and d > nATR;
def bm = uptrendd[1] and c < o and h - Max(o, c) + Min(o, c) - l < d / 10 and d > nATR;
#-----------------------------------------------------------------------------}
# Channel
# ----------------------------------------------------------------------------{
def max;
def min;
def lbl;
#//Bullish Patterns-----------------------
if hammer and enable_hammer {
max = max[1] + alpha / 100 * (c - max[1]);
min = min[1];
lbl = 1;
} else {
if ihammer and enable_ihammer {
max = max[1] + alpha / 100 * (c - max[1]);
min = min[1];
lbl = 2;
} else {
if bulleng and enable_bulleng {
max = max[1] + alpha / 100 * (c - max[1]);
min = min[1];
lbl = 3;
} else {
if wm and enable_wm {
max = max[1] + alpha / 100 * (c - max[1]);
min = min[1];
lbl = 4;
} else {
#//Bearish Patterns-------------------------------------------------------------------
if shooting and enable_shooting {
min = min[1] + alpha / 100 * (c - min[1]);
max = max[1];
lbl = 5;
} else {
if hanging and enable_hanging {
min = min[1] + alpha / 100 * (c - min[1]);
max = max[1];
lbl = 6;
} else {
if beareng and enable_beareng {
min = min[1] + alpha / 100 * (c - min[1]);
max = max[1];
lbl = 7;
} else {
if bm and enable_bm {
min = min[1] + alpha / 100 * (c - min[1]);
max = max[1];
lbl = 8;
} else {
#//-----------------------------------------------------------------------------------
max = if n < 1 then h else Max(c, max[1]);
min = if n < 1 then l else Min(c, min[1]);
lbl = 0;
}
}
}
}
}
}
}
}
def smooth_max = ExpAverage(max, smooth);
def smooth_min = ExpAverage(min, smooth);
def avg = (smooth_max + smooth_min) / 2;
#//---------------------------------------------------------------------------}
#//Plots
#//--------------------------------------------------------------------------{
def os;
os = if c > smooth_max then 1 else if c < smooth_min then 0 else os[1];
def fade_max;
fade_max = if os == 0 then fade_max[1] + 1 else 0;
def fade_min;
fade_min = if os == 1 then fade_min[1] + 1 else 0;
plot Upper = if mode == mode.Channel then smooth_max else na;
Upper.SetHiding(!showBand);
plot Middle = if mode == mode.Channel then avg else na;
plot Lower = if mode == mode.Channel then smooth_min else na;
Lower.SetHiding(!showBand);
Upper.AssignValueColor(if fade_max < fade_min then Color.GREEN else
if fade_max > fade_min then Color.RED else Color.GRAY);
Middle.AssignValueColor(if fade_max < fade_min then GlobalColor("green") else
if fade_max > fade_min then GlobalColor("red") else Color.GRAY);
Lower.AssignValueColor(if fade_max < fade_min then Color.GREEN else
if fade_max > fade_min then Color.RED else Color.GRAY);
#----cloud---
AddCloud(if showCloud then Upper else na, Middle, Color.DARK_GREEN);
AddCloud(if showCloud then Middle else na, Lower, Color.DARK_RED);
#---Bubbles
AddChartBubble(CandlestickBubble and lbl == 1, low, "H", Color.DARK_GREEN, no);
AddChartBubble(CandlestickBubble and lbl == 2, low, "iH", Color.DARK_GREEN, no);
AddChartBubble(CandlestickBubble and lbl == 3, low, "BE", Color.DARK_GREEN, no);
AddChartBubble(CandlestickBubble and lbl == 4, low, "WM", Color.DARK_GREEN, no);
AddChartBubble(CandlestickBubble and lbl == 5, high, "SS", Color.DARK_RED, yes);
AddChartBubble(CandlestickBubble and lbl == 6, high, "HM", Color.DARK_RED, yes);
AddChartBubble(CandlestickBubble and lbl == 7, high, "BE", Color.DARK_RED, yes);
AddChartBubble(CandlestickBubble and lbl == 8, high, "BM", Color.DARK_RED, yes);
#------------SuperTrend-----------
def dn = max;
def up = min;
def up1 = if (up > up1[1]) or (h[1] < up1[1]) then if l[1] > up1[1] then Max(up1[1], up) else up else up1[1];
def dn1 = if (dn < dn1[1]) or (l[1] > dn1[1]) then if h[1] < dn1[1] then Min(dn1[1], dn) else dn else dn1[1];
def lastU = up1[1];
def lastD = dn1[1];
def lastUp;
def lastDn;
def state = {default init, long, short};
def trend;
def confirm;
def unconfirm;
switch (state[1]) {
case init:
state = state.short;
trend = 0;
confirm = if isNaN(confirm[1]) then 0 else confirm[1];
unconfirm = if isNaN(unconfirm[1]) then 0 else unconfirm[1];
case long:
if (trend[1] != 1 and l > lastDn[1])
then {
state = state.short;
trend = 1;
confirm = confirm[1];
unconfirm = unconfirm[1];
} else {
state = state.long;
trend = trend[1];
confirm = If((trend != +1 and h > lastDn) and (confirm[1] < closeBars and close[1] > lastDn)
or (trend != -1 and l < lastUp) and (confirm[1] < closeBars and close[1] < lastUp), confirm[1] + 1,
If(trend[1] != trend or lastUp[1] != lastUp or lastDn[1] != lastDn, 0, confirm[1]));
unconfirm = If((trend != +1 and h > lastD) or (trend != -1 and l < lastU), unconfirm[1] + 1,
If(trend[1] != trend or lastUp[1] != lastUp or lastDn[1] != lastDn, 0, unconfirm[1]));
}
case short:
if (trend[1] != -1 and h < lastUp[1])
then {
state = state.long;
trend = -1;
confirm = confirm[1];
unconfirm = unconfirm[1];
} else {
state = state.short;
if (trend[1] != +1 and h > lastDn[1])
then {
unconfirm = If((trend[1] != trend), 0, unconfirm[1] + 1);
confirm = If(confirm[1] < closeBars and close[1] > lastUp[1], confirm[1] + 1, confirm[1]);
trend = If(confirm[1] >= closeBars, +1, trend[1]);
} else {
if (trend[1] != -1 and l < lastUp[1])
then {
unconfirm = If(trend[1] != trend , 0, unconfirm[1] + 1);
confirm = If(confirm[1] < closeBars and close[1] < lastUp[1], confirm[1] + 1, confirm[1]);
trend = If(confirm[1] >= closeBars, -1, trend[1]);
} else {
trend = trend[1];
confirm = If(trend[1] != trend or lastUp[1] != lastUp or lastDn[1] != lastDn, 0, confirm[1]);
unconfirm = If(trend[1] != trend or lastUp[1] != lastUp or lastDn[1] != lastDn, 0, unconfirm[1]);
}
}
}
}
if (trend[1] != trend)
then {
lastUp = lastU;
lastDn = lastD;
} else {
lastUp = if trend == +1 then Max(lastUp[1], up1) else up1;
lastDn = if trend == -1 then Min(lastDn[1], dn1) else dn1;
}
#----- Calculations -------
def upTrend = if trend == 1 then lastUp else na;
def buySignal = trend == 1 and trend[1] == -1;
def upPoint = if buySignal then lastUp else na;
def dnTrend = if trend == 1 then na else lastDn;
def sellSignal = trend == -1 and trend[1] == 1;
def dnPoint = if sellSignal then lastDn else na;
#------ plot ----------------
plot upPlot = if mode == mode.SuperTrend then upTrend else na; # "Up Trend"
upPlot.AssignValueColor(if unconfirm == 0 then GlobalColor("green") else Color.YELLOW);
plot pointUp = if mode == mode.SuperTrend then upPoint else na; # "UpTrend Begins"
pointUp.SetDefaultColor(GlobalColor("green"));
pointUp.SetStyle(Curve.POINTS);
pointUp.SetLineWeight(3);
plot dnPlot = if mode == mode.SuperTrend then dnTrend else na; # "Down Trend"
dnPlot.AssignValueColor(if unconfirm == 0 then GlobalColor("red") else Color.YELLOW);
plot pointDn = if mode == mode.SuperTrend then dnPoint else na; # "DownTrend Begins"
pointDn.SetDefaultColor(GlobalColor("red"));
pointDn.SetStyle(Curve.POINTS);
pointDn.SetLineWeight(3);
#------- Cloud -------
AddCloud(ohlc4, if ShowCloud then upPlot else na, Color.DARK_GREEN, Color.WHITE);
AddCloud(if ShowCloud then dnPlot else na, ohlc4, Color.DARK_RED, Color.WHITE);
#------- Bubble ------
AddChartBubble(buySignal and showsignals, lastUp, "Buy", Color.GREEN, no);
AddChartBubble(sellSignal and showsignals, lastDn, "Sell", Color.RED, yes);
### END
Last edited by a moderator: