Author Message:
The Curved Price Channels (Zeiierman) is designed to plot dynamic channels around price movements, much like the traditional Donchian Channels, but with a key difference: the channels are curved instead of straight. This curvature allows the channels to adapt more fluidly to price action, providing a smoother representation of the highest high and lowest low levels.
Just like Donchian Channels, the Curved Price Channels help identify potential breakout points and areas of trend reversal. However, the curvature offers a more refined approach to visualizing price boundaries, making it potentially more effective in capturing price trends and reversals in markets that exhibit significant volatility or price swings.
The included trend strength calculation further enhances the indicator by offering insight into the strength of the current trend.
CODE:
CSS:
#// Indicator for TOS
#// © Zeiierman {
#indicator("Curved Price Channels (Zeiierman)",overlay=true, max_bars_back =
#// ~~ Tooltips {
#Hint trendLength: Trend Length defines the number of bars (or candles) used to calculate the core trendline. A longer length, such as 200, smooths out the trend, making it more stable but slower to react to price changes. This is useful in identifying long-term trends. Conversely, a shorter length, such as 20, makes the trendline more responsive to recent price action, capturing short-term movements.
#Hint multiplier: Multiplier adjusts the width of the curved price channels by scaling the impact of the adaptive size. A higher multiplier tightens the channels, making them more sensitive to price movements and capturing smaller fluctuations. This setting is useful for detecting minor changes in trends or during low-volatility periods. Conversely, a lower multiplier widens the channels, making them more forgiving and focusing on larger price moves.
#Hint trendStrengthLookback: Trend Strength Length defines the period over which the maximum and minimum ranges are calculated to normalize the trend strength. A longer length, such as 200, smooths the strength readings, making them more reliable for long-term analysis. A shorter length, like 50, makes the strength readings more sensitive to recent changes.
# Converted by Sam4Cok@Samer800 - 09/2024
#// ~~ Inputs {
input timeframe = AggregationPeriod.MIN;
input trendLength = 100;
input multiplier = 6.0;
input showTrendline = yes;
input showCurvedChannel = yes;
input showTrendStrengthCandle = yes;
input candleOffset = 3;
input showTrendStrength = {Default "As Label", "As Bubbles", "Don't Show"};
input trendStrengthLookback = 200;
def na = Double.NaN;
def last = IsNaN(close);
def current = GetAggregationPeriod();
def tf = Max(current, timeframe);
def lab; def bub;
Switch(showTrendStrength) {
Case "As Bubbles" :
lab = no;
bub = yes;
Case "Don't Show" :
lab = no;
bub = no;
Default :
lab = yes;
bub = no;
}
#/ ~~ Curved Price Channels {
#// Curved Price Channels Calculation Function
Script calcCurvedPriceChannels {
input length = 100;
input multi = 6;
input tf = 60000;
def upperBand;
def lowerBand;
def tr = TrueRange(high(period = tf), close(period = tf), low(period = tf));
def adaptiveSize = WildersAverage(tr, length);
def lengthSquared = power(length, 2);
def maxcloseUpper = Max(high(period = tf), if !upperBand[1] then close(period = tf) else upperBand[1]);
def barsSinceUpperIncrease = if close(period = tf) > upperBand[1] then 0 else barsSinceUpperIncrease[1] + 1;
def upperAdjustmentFactor = adaptiveSize / lengthSquared * (barsSinceUpperIncrease + 1) * multi;
upperBand = maxcloseUpper - upperAdjustmentFactor;
def mincloseLower = Min(low(period = tf), if !lowerBand[1] then close(period = tf) else lowerBand[1]);
def barsSinceLowerDecrease = if close(period = tf) < lowerBand[1] then 0 else barsSinceLowerDecrease[1] + 1;
def lowerAdjustmentFactor = adaptiveSize / lengthSquared * (barsSinceLowerDecrease + 1) * multi;
lowerBand = mincloseLower + lowerAdjustmentFactor;
def pvtHi = highest(upperBand, 1);
def pvtLo = lowest(lowerBand, 1);
def Up = if !pvtHi then upperBand else pvtHi;
def Dn = if !pvtLo then lowerBand else pvtLo;
def trendline = (Up + Dn) / 2;
plot u = if isNaN(close) then Double.NaN else Up;
plot d = if isNaN(close) then Double.NaN else Dn;
plot T = Trendline;
}
def Up = calcCurvedPriceChannels(trendLength, multiplier, tf).u;
def Dn = calcCurvedPriceChannels(trendLength, multiplier, tf).d;
def trendline = calcCurvedPriceChannels(trendLength, multiplier, tf).t;
#// ~~ Curved Price Channels Plots {
def cond = last[-trendLength];
plot CurvedHigh = if showCurvedChannel then Up else na; #, "Curved High"
plot CurvedLow = if showCurvedChannel then Dn else na; #, "Curved Low"
plot CurvedTrend = if !cond and showTrendline then trendline else na; # "Curved Trend"
plot CurvedTrend1 = if cond and showTrendline then trendline else na; # "Curved Trend"
CurvedHigh.SetDefaultColor(Color.GREEN);
CurvedLow.SetDefaultColor(Color.RED);
CurvedTrend1.SetStyle(Curve.SHORT_DASH);
CurvedTrend.AssignValueColor(if close > trendline then Color.CYAN else Color.MAGENTA);
CurvedTrend1.AssignValueColor(if close > trendline then Color.CYAN else Color.MAGENTA);
def p2 = Average(trendline, 20);
AddCloud(CurvedHigh, CurvedHigh - (CurvedHigh - p2) / 2.5, Color.DARK_GREEN, Color.DARK_GREEN);
AddCloud(CurvedLow, CurvedLow + (p2 - CurvedLow) / 2.5, Color.DARK_RED, Color.DARK_RED);
# Plot the new Chart
def n = candleOffset;
def loc = last[n - 1] and !last[n];
#// ~~ Range & Strength {
#// Calculate the distance of the close from the trendline relative to the range
def rangee = up - dn;
def relativePosition = (close(period = tf) - trendline) / rangee;
#// Normalize the current range to get the trend strength
def maxRange = highest(rangee, trendStrengthLookback);
def minRange = lowest(rangee, trendStrengthLookback);
def normalizedRange = (rangee - minRange) / (maxRange - minRange);
#// Combine the relative position and the normalized range to calculate trend strength
def Strength = relativePosition * normalizedRange;
def maxTrendStrength = highest(Strength, trendStrengthLookback);
def minTrendStrength = lowest(Strength, trendStrengthLookback);
def rndDiff = Strength ;
def labLoc = (trendline + close(period = tf)) / 2;
def candCond = showTrendStrengthCandle and loc;
AddChart(open = if candCond and rndDiff[n] > 0 then close(period = tf)[n] else na, high = trendline[n] ,
low = close(period = tf)[n] , close = trendline[n], type = ChartType.CANDLE, growcolor = Color.CYAN);
AddChart(open = if candCond and rndDiff[n] < 0 then trendline[n] else na, high = close(period = tf)[n] ,
low = trendline[n] , close = close(period = tf)[n], type = ChartType.CANDLE, growcolor = Color.MAGENTA);
AddChart(open = if candCond then labLoc[n] else na, high = up[n] , low = dn[n] , close = labLoc[n],
type = ChartType.CANDLE, growcolor = Color.GRAY);
#-- Bubble
AddLabel(lab, "Trend Strength: " + AsPercent(rndDiff), if rndDiff > 0 then Color.CYAN else Color.MAGENTA);
AddLabel(lab, "Max: " + AsPercent(maxTrendStrength), Color.CYAN);
AddLabel(lab, "Min: " + AsPercent(minTrendStrength), Color.MAGENTA);
AddChartBubble(bub and loc[1], labLoc[n+1], asPercent(rndDiff[n+1]),
if rndDiff[n+1] > 0 then Color.CYAN else Color.MAGENTA);
AddChartBubble(bub and loc, up[n], asPercent(maxTrendStrength[n]), Color.CYAN);
AddChartBubble(bub and loc, dn[n], asPercent(minTrendStrength[n]), Color.MaGENTA, no);
#-- END of CODE