Enhance Market Insights with the Comprehensive Trendline and Volume Profile Script
January 3, 2025 | by admin

//@version=5
indicator(" TRANDLINE/ART ̶", overlay = true, max_boxes_count=500, max_bars_back=5000, max_labels_count =500, max_lines_count =500)
//=====================================================================================================================================
// ATR Settings for Futures Trading
//=====================================================================================================================================
myAtrLength = input(25, title="ATR Length") // Optimized for faster markets
atrMultiplier = input(2, title="ATR Multiplier") // Wider stop-loss for futures volatility
// ATR Stoploss Switch
atrStoplossEnabled = input(false, title="Enable ATR Stoploss") // Default enabled for futures risk management
// ATR Stoploss Calculation
atr1 = ta.atr(myAtrLength)
atrStoplossLong = atrStoplossEnabled ? (low - atr1 * atrMultiplier) : na
atrStoplossShort = atrStoplossEnabled ? (high + atr1 * atrMultiplier) : na
// ATR Stoploss Plot
plot(atrStoplossLong, color=color.rgb(76, 175, 137), title="ATR Stoploss Long", linewidth=1)
plot(atrStoplossShort, color=color.rgb(243, 76, 76), title="ATR Stoploss Short", linewidth=1)
//---------------------------------------------------------------------------------------------------------------------}
// Settings
//---------------------------------------------------------------------------------------------------------------------{
disp = display.all - display.status_line
rpGR = 'Profile Generic Settings'
rpLN = input.int(200, ' Lookback Length / Fixed Range', minval = 10, maxval = 1500, step = 10 , group = rpGR, display = disp)
rpLN := last_bar_index > rpLN ? rpLN - 1 : last_bar_index
vpSRC = input.string('Volume', ' Profile Source', options = ['Volume', 'Money Flow'], group = rpGR, display = disp)
vpGR = 'Profile Presentation Settings'
vpTP = 'displays total trading activity/money flow (common interest, both buying and selling trading activity/money flow) over a specified time period at specific price levels\n\n' +
' - high traded node rows : high trading activity/money flow price levels - usually represents consolidation levels (value areas)\n' +
' - average traded node rows : average trading activity/money flow price levels\n' +
' - low traded node rows : low trading activity/money flow price levels - usually represents supply & demand levels or liquidity levels\n\n' +
'row lengths, indicates the amount of the traded activity/money flow at specific price levels'
vpSH = input.bool(true, 'Volume/Money Flow Profile', group = vpGR, tooltip = vpTP, display = disp)
vpHVC = input.color(color.new(#ffeb3b, 50), ' High Traded Nodes', inline = 'VP1', group = vpGR)
vpHVT = input.int(53, 'Threshold %' , minval = 50, maxval = 99 , step = 1,inline = 'VP1', group = vpGR, tooltip = 'option range [50-99]', display = disp) / 100
vpAVC = input.color(color.new(#2962ff, 50), ' Average Traded Nodes', group = vpGR)
vpLVC = input.color(color.new(#f23645, 50), ' Low Traded Nodes', inline = 'VP2', group = vpGR)
vpLVT = input.int(37, 'Threshold %' , minval = 10, maxval = 40 , step = 1,inline = 'VP2', group = vpGR, tooltip = 'option range [10-40]', display = disp) / 100
spTP = 'displays the sentiment, the dominat party over a specified time period at the specific price levels\n\n' +
' - bullish node rows : buying trading activity/money flow is higher\n' +
' - barish node rows : selling trading activity/money flow is higher\n\n' +
'row lengths, indicates the strength of the buyers/sellers at the specific price levels'
spSH = input.bool(true, 'Sentiment Profile', group = vpGR, tooltip = spTP)
spPTT = 'conditions used to calculate the up/down volume/money flow\n\n' +
'* bar polarity\n up => if close > open\n down => if close <= open\n\n' +
'* bar buying/selling pressure\n up => if (close - low) > (high - close)\n down => if (close - low) <= (high - close)'
spPT1 = 'Bar Polarity'
spPT2 = 'Bar Buying/Selling Pressure'
spPTY = input.string(spPT1, ' Sentiment Polarity Method', options = [spPT1, spPT2], group = vpGR, tooltip = spPTT, display = disp)
spBLC = input.color(color.new(#26a69a, 50), ' Bullish Nodes', inline = 'SP', group = vpGR)
spBRC = input.color(color.new(#ef5350, 50), 'Bearish Nodes', inline = 'SP', group = vpGR)
hmSH = input.bool(false, 'Profile Heatmap', group = vpGR, tooltip = 'tip : higher number of rows results with a better visuals')
hmSO1 = 'Volume/Money Flow Profile'
hmSRC = input.string(hmSO1, ' Heatmap Source', options = [hmSO1, 'Sentiment Profile'], group = vpGR, display = disp)
hmTR = input.int(73, ' Heatmap Transparency' , minval = 0, maxval = 100 , group = vpGR, display = disp)
othGR = 'Other Presentation Settings'
pcTP = 'displays the price level of the highest traded activity/money flow or the changes of the price levels with the highest traded activity/money flow'
rpPC = input.string('Last(Zone)', ' Level of Significance', options = ['Developing', 'Last(Line)', 'Last(Zone)', 'None'], inline='PoC', group = othGR, tooltip = pcTP, display = disp)
vaSH = input.bool(true, 'Consolidation Zones', group = othGR, display = disp)
vaTH = input.int(25, ' Consolidation Threshold %' , minval = 0, maxval = 100, inline = 'va', group = othGR, display = disp) / 100
vaC = input.color(color.new(#2962ff, 80), '', inline = 'va', group = othGR)
spTT = 'displays the price zone of the highest bullish or bearish sentiment zone'
spPC = input.bool(false, 'Highest Sentiment Zone', inline = 'spP', group = othGR, tooltip = spTT)
rpPL = input.bool(false, 'Profile Price Levels', inline = 'BBe', group = othGR)
rpPLC = input.color(color.new(#00bcd4, 0), '', inline = 'BBe', group = othGR)
rpLS = input.string('Small', "", options=['Tiny', 'Small', 'Normal'], inline = 'BBe', group = othGR, display = disp)
rpBG = input.bool(false, 'Profile Range Background Fill', inline = 'BG', group = othGR)
rpBGC = input.color(color.new(#00bcd4, 85), '', inline = 'BG', group = othGR)
otGR = 'Other Profile Settings'
rpNR = input.int(25, ' Number of Rows' , minval = 10, maxval = 100 ,step = 5, group = otGR, tooltip = 'option range [10-100]', display = disp)
rpW = input.int(13, ' Profile Width %', minval = 10, maxval = 50, group = otGR, tooltip = 'option range [10-50]', display = disp) / 100
vpLS = input.string('Auto', " Profile Text Size", options=['Auto', 'Tiny', 'Small'], group = otGR, display = disp)
vpHO = input.int(13, ' Profile Horizontal Offset', group = otGR, tooltip = 'option allows negative numbers as well, in case of a use the profiles will overlap with the price chart', display = disp)
//---------------------------------------------------------------------------------------------------------------------}
// User Defined Types
//---------------------------------------------------------------------------------------------------------------------{
// @type bar properties with their values
//
// @field o (float) open price of the bar
// @field h (float) high price of the bar
// @field l (float) low price of the bar
// @field c (float) close price of the bar
// @field v (float) volume of the bar
// @field i (int) index of the bar
type bar
float o = open
float h = high
float l = low
float c = close
float v = volume
int i = bar_index
//---------------------------------------------------------------------------------------------------------------------}
// Variables
//---------------------------------------------------------------------------------------------------------------------{
bar b = bar.new()
rpVST = array.new_float(rpNR, 0.)
rpVSB = array.new_float(rpNR, 0.)
rpVSD = array.new_float(rpNR, 0.)
var dRP = array.new_box()
var pocPoints = array.new<chart.point>()
var polyline pocPolyline = na
var polyline spPolyline = na
var color llC = na
var color lsC = na
//---------------------------------------------------------------------------------------------------------------------}
// Functions/Methods
//---------------------------------------------------------------------------------------------------------------------{
// @function creates new label object and updates existing label objects
//
// @param details in Pine Script™ language reference manual
//
// @returns none, updated visual objects (labels)
f_drawLabelX(_x, _y, _text, _style, _textcolor, _size, _tooltip) =>
var lb = label.new(_x, _y, _text, xloc.bar_index, yloc.price, color(na), _style, _textcolor, _size, text.align_left, _tooltip)
lb.set_xy(_x, _y)
lb.set_text(_text)
lb.set_tooltip(_tooltip)
lb.set_textcolor(_textcolor)
// @function This function converts string to enumerated size
//
// @param _t [string] custom string
//
// @returns [string] enumerated size
f_gTS(_t) =>
switch _t
'Tiny' => size.tiny
'Small' => size.small
'Normal' => size.normal
'Auto' => size.auto
//---------------------------------------------------------------------------------------------------------------------}
// Calculations
//---------------------------------------------------------------------------------------------------------------------{
bull = spPTY == spPT1 ? b.c > b.o : (b.c - b.l) > (b.h - b.c)
nzV = nz(b.v)
rpS = f_gTS(rpLS)
vpS = f_gTS(vpLS)
var float pLST = na
var float pHST = na
if b.i == last_bar_index - rpLN
pLST := b.l
pHST := b.h
else if b.i > last_bar_index - rpLN
pLST := math.min(b.l, pLST)
pHST := math.max(b.h, pHST)
pSTP = (pHST - pLST) / rpNR
if barstate.islast and not na(nzV) and not timeframe.isseconds and rpLN > 0 and pSTP > 0 and nzV > 0
if dRP.size() > 0
for i = 0 to dRP.size() - 1
box.delete(dRP.shift())
if pocPoints.size() > 0
pocPoints.clear()
a_allPolylines = polyline.all
if array.size(a_allPolylines) > 0
for i = 0 to array.size(a_allPolylines) - 1
polyline.delete(a_allPolylines.get(i))
for bI = rpLN to 0
l = 0
for pLL = pLST to pHST - pSTP by pSTP
if b.h[bI] >= pLL and b.l[bI] < pLL + pSTP
vPOR = if b.l[bI] >= pLL and b.h[bI] > pLL + pSTP
(pLL + pSTP - b.l[bI]) / (b.h[bI] - b.l[bI])
else if b.h[bI] <= pLL + pSTP and b.l[bI] < pLL
(b.h[bI] - pLL) / (b.h[bI] - b.l[bI])
else if (b.l[bI] >= pLL and b.h[bI] <= pLL + pSTP)
1
else
pSTP / (b.h[bI] - b.l[bI])
if vpSRC == 'Money Flow'
rpVST.set(l, rpVST.get(l) + nzV[bI] * vPOR * (pLST + (l + .5) * pSTP) )
else
rpVST.set(l, rpVST.get(l) + nzV[bI] * vPOR )
if bull[bI] and spSH
if vpSRC == 'Money Flow'
rpVSB.set(l, rpVSB.get(l) + nzV[bI] * vPOR * (pLST + (l + .5) * pSTP))
else
rpVSB.set(l, rpVSB.get(l) + nzV[bI] * vPOR )
l += 1
if rpPC == 'Developing'
if bI == rpLN
pocPoints.push(chart.point.from_index(b.i[bI], pLST + (rpVST.indexof(rpVST.max()) + .5) * pSTP))
else
pocPoints.push(chart.point.from_index(b.i[bI], pLST + (rpVST.indexof(rpVST.max()) + .5) * pSTP))
if rpPC == 'Developing'
pocPolyline := polyline.new(pocPoints, false, false, xloc.bar_index, vpHVC, color(na), line.style_solid, 2)
if rpPC == 'Last(Zone)' or rpPC == 'Last(Line)'
pocPoints.push(chart.point.from_index(b.i[rpLN], pLST + (rpVST.indexof(rpVST.max()) + .5) * pSTP))
pocPoints.push(chart.point.from_index(b.i, pLST + (rpVST.indexof(rpVST.max()) + .5) * pSTP))
pocPolyline := polyline.new(pocPoints, false, false, xloc.bar_index, vpHVC, color(na), rpPC == 'Last(Line)' ? line.style_solid : line.style_dotted, rpPC == 'Last(Line)' ? 2 : 1)
for l = 0 to rpNR - 1
bbp = 2 * rpVSB.get(l) - rpVST.get(l)
rpVSD.set(l, rpVSD.get(l) + bbp * (bbp > 0 ? 1 : -1) )
if vpSH or spSH
sBI = b.i + (spSH ? rpLN * rpW : 7) + int(rpLN * rpW / 3)
dRP.push(box.new(sBI - 1 + vpHO, pLST + (l + .1) * pSTP, sBI - int(rpLN * rpW / 3) + 1 + vpHO, pLST + (l + .9) * pSTP, #2962ff80, bgcolor = #2962ff10,
text = str.tostring(pLST + (l + .5) * pSTP, format.mintick), text_color = chart.fg_color, text_size = vpS ))
if rpBG
dRP.push(box.new(b.i - rpLN, pLST, b.i, pHST, rpBGC, bgcolor = rpBGC ))
if rpPL
f_drawLabelX(b.i, pHST, str.tostring(pHST, format.mintick), label.style_label_down, rpPLC, rpS,
'Profile High - ' + str.tostring(pHST, format.mintick) + '\n %' + str.tostring((pHST - pLST) / pLST * 100, '#.##') + ' higher than the Profile Low\n\n' +
'Total ' + (vpSRC == 'Volume' ? 'Volume : ' : 'Money Flow (' + syminfo.currency + ') : ') + str.tostring(rpVST.sum(), format.volume) +
'\nNumber of bars : ' + str.tostring(rpLN + 1))
f_drawLabelX(b.i, pLST, str.tostring(pLST, format.mintick), label.style_label_up , rpPLC, rpS,
'Profile Low - ' + str.tostring(pLST, format.mintick) + '\n %' + str.tostring((pHST - pLST) / pHST * 100, '#.##') + ' lower than the Profile High\n\n' +
'Total ' + (vpSRC == 'Volume' ? 'Volume : ' : 'Money Flow (' + syminfo.currency + ') : ') + str.tostring(rpVST.sum(), format.volume) +
'\nNumber of bars : ' + str.tostring(rpLN + 1))
for l = 0 to rpNR - 1
if dRP.size() < 500
vtLV = rpVST.get(l)
vtMX = rpVST.max()
LpM = vtLV / vtMX
vdMX = rpVSD.max()
DpM = rpVSD.get(l) / vdMX
llC := LpM > vpHVT ? color.from_gradient(LpM, vpHVT, 1, vpAVC, vpHVC) : color.from_gradient(LpM, 0, vpLVT, vpLVC, vpAVC)
bbp = 2 * rpVSB.get(l) - vtLV
lsC := bbp > 0 ? color.from_gradient(DpM, 0, .7, color.new(spBLC, 70 + int(hmTR / 4)), color.new(spBLC, 30 + int(hmTR / 4))) :
color.from_gradient(DpM, 0, .7, color.new(spBRC, 70 + int(hmTR / 4)), color.new(spBRC, 30 + int(hmTR / 4)))
if rpPC == 'Last(Zone)' and LpM == 1
dRP.push(box.new(b.i[rpLN], pLST + (rpVST.indexof(vtMX) + .0) * pSTP, b.i, pLST + (rpVST.indexof(vtMX) + 1.) * pSTP, vpHVC, bgcolor = color.new(vpHVC, 73) ))
if vaSH and LpM > vaTH and LpM < 1
dRP.push(box.new(b.i[rpLN], pLST + (l + .0) * pSTP, b.i, pLST + (l + 1.) * pSTP, color(na), bgcolor = vaC ))
if vaSH and rpPC != 'Last(Zone)' and LpM == 1
dRP.push(box.new(b.i[rpLN], pLST + (l + .0) * pSTP, b.i, pLST + (l + 1.) * pSTP, color(na), bgcolor = vaC ))
if spPC and DpM == 1
spPolyline := polyline.new(array.from(chart.point.from_index(b.i[rpLN], pLST + (rpVSD.indexof(vdMX) + .5) * pSTP), chart.point.from_index(b.i, pLST + (rpVSD.indexof(vdMX) + .5) * pSTP)), false, false, xloc.bar_index, lsC, color(na), line.style_dotted, 1)
dRP.push(box.new(b.i[rpLN], pLST + (rpVSD.indexof(vdMX) + .0) * pSTP, b.i, pLST + (rpVSD.indexof(vdMX) + 1.) * pSTP, lsC, bgcolor = color.new(lsC, 73) ))
if vpSH
sBI = b.i + (spSH ? rpLN * rpW : 7) + int(rpLN * rpW / 3)
eBI = sBI + int(LpM * rpLN * rpW)
dRP.push(box.new(sBI + vpHO, pLST + (l + .1) * pSTP, eBI + vpHO, pLST + (l + .9) * pSTP, llC, bgcolor = llC,
text = str.tostring(vpSRC == 'Money Flow' ? array.get(rpVST, l) : array.get(rpVST, l) * (pLST + (l + .5) * pSTP), format.volume) + ' ' +
syminfo.currency + ' (' + str.tostring(math.abs(vtLV / rpVST.sum() * 100), '#.##') + '%)',
text_halign = text.align_left, text_color = chart.fg_color, text_size = vpS ))
if spSH
sBI = b.i + rpLN * rpW
eBI = sBI - int(DpM * rpLN * rpW)
dRP.push(box.new(sBI + vpHO, pLST + (l + .1) * pSTP, eBI + vpHO, pLST + (l + .9) * pSTP, lsC, bgcolor = lsC,
text = str.tostring(bbp, format.volume ) + (vpSRC == 'Money Flow' ? ' ' + syminfo.currency : '') +
' (' + str.tostring(math.abs(bbp / vtLV * 100), '#.##') + '%)',
text_halign = text.align_right, text_color = chart.fg_color, text_size = vpS ))
if hmSH
dRP.push(box.new(b.i[rpLN], pLST + (l + .0) * pSTP, b.i, pLST + (l + 1.) * pSTP, hmSRC == hmSO1 ? color.new(llC, hmTR) : lsC, bgcolor = hmSRC == hmSO1 ? color.new(llC, hmTR) : lsC))
//---------------------------------------------------------------------------------------------------------------------}
//=====================================================================================================================================
//TRAND LINE
//=====================================================================================================================================
confidence(pearsonR) =>
switch
pearsonR < 0.2 => "Extremely Weak"
pearsonR < 0.3 => "Very Weak"
pearsonR < 0.4 => "Weak"
pearsonR < 0.5 => "Mostly Weak"
pearsonR < 0.6 => "Somewhat Weak"
pearsonR < 0.7 => "Moderately Weak"
pearsonR < 0.8 => "Moderate"
pearsonR < 0.9 => "Moderately Strong"
pearsonR < 0.92 => "Mostly Strong"
pearsonR < 0.94 => "Strong"
pearsonR < 0.96 => "Very Strong"
pearsonR < 0.98 => "Exceptionally Strong"
=> "Ultra Strong"
getTablePosition(string pos) =>
switch pos
"Bottom Right" => position.bottom_right
"Bottom Center" => position.bottom_center
"Bottom Left" => position.bottom_left
"Top Right" => position.top_right
"Top Left" => position.top_left
"Top Center" => position.top_center
"Middle Right" => position.middle_right
=> position.middle_left // "Middle Left" - default
// Calculate deviations for given length
calcDev(float source, int length) =>
float logSource = math.log(source)
var int period_1 = length - 1
if barstate.islast
float sumX = 0.0
float sumXX = 0.0
float sumYX = 0.0
float sumY = 0.0
for int i=1 to length
float lSrc = logSource[i-1]
sumX += i
sumXX += i * i
sumYX += i * lSrc
sumY += lSrc
float slope = nz((length * sumYX - sumX * sumY) / (length * sumXX - sumX * sumX))
float average = sumY / length
float intercept = average - (slope * sumX / length) + slope
float sumDev = 0.0
float sumDxx = 0.0
float sumDyy = 0.0
float sumDyx = 0.0
float regres = intercept + slope * period_1 * 0.5
float sumSlp = intercept
for int i=0 to period_1
float lSrc = logSource[i]
float dxt = lSrc - average
float dyt = sumSlp - regres
lSrc -= sumSlp
sumSlp += slope
sumDxx += dxt * dxt
sumDyy += dyt * dyt
sumDyx += dxt * dyt
sumDev += lSrc * lSrc
float unStdDev = math.sqrt(sumDev / period_1) // unbiased
float divisor = sumDxx * sumDyy
float pearsonR = nz(sumDyx / math.sqrt(divisor))
[unStdDev, pearsonR, slope, intercept]
else
[na, na, na, na]
string t1 = "In Long-Term Channel mode, if the channel is not visible, scroll back on the chart for additional historical data. To view both Short-Term and Long-Term channels simultaneously, load this indicator twice on your chart."
string t2 = "Displays the length of the period automatically selected by the indicator that shows the strongest trend. This period is determined by identifying the highest correlation between price movements and trend direction."
string t3 = "Pearson's R is a statistical measure that evaluates the linear relationship between price movements and trend projection. A value closer to 1 indicates a strong positive correlation, increasing confidence in the trend direction based on historical data."
string t4 = "Displays the annualized return (CAGR) of the trend over the auto-selected period. This feature is available only for daily (D) and weekly (W) timeframes, providing insight into the expected yearly growth rate if the trend continues."
sourceInput = input.source(close, title="Source")
//=======================================================================================================================================================================
//INPUT MAIN
//=======================================================================================================================================================================
string group0 = "CHANNEL SETTINGS"
bool periodMode = input.bool ( false, "Use Long-Term Channel", group=group0, tooltip=t1)
float devMultiplier = input.float ( 2.0, "Deviation Multiplier:", group=group0, step=0.1)
color colorInput = input.color ( #ffffff, "", group=group0, inline=group0)
string lineStyle1 = input.string( "Solid", "", group=group0, inline=group0, options=["Solid", "Dotted", "Dashed"])
string extendStyle = input.string("Extend Right", "", group=group0, inline=group0, options=["Extend Right", "Extend Both", "Extend None", "Extend Left"])
int fillTransparency = input.int ( 93,"Fill Transp:", group=group0, inline="mid", minval=0, maxval=100, step=1)
int channelTransparency = input.int ( 0, "Line Transp:", group=group0, inline="mid", minval=0, maxval=100, step=1)
string group1 = "MIDLINE SETTINGS"
color colorInputMidline = input.color ( color.blue, "", group=group1, inline=group1)
int transpInput = input.int ( 100, "Transp:", group=group1, inline=group1, minval=0, maxval=100, step=10)
int lineWidth = input.int ( 1, "Line Width:", group=group1, inline=group1)
string midLineStyle = input.string( "Dashed", "", group=group1, inline=group1, options=["Dotted", "Solid", "Dashed"])
//========================================================================================================================================================================
//TABLE SETTINGS
//========================================================================================================================================================================
string group2 = "TABLE SETTINGS"
bool showAutoSelectedPeriod = input(true, "Show Auto-Selected Period", group=group2, tooltip=t2)
bool showTrendStrength = input(true, "Show Trend Strength", group=group2, inline="secondLine")
bool showPearsonInput = input.bool(false, "Show Pearson's R", group=group2, inline="secondLine", tooltip=t3)
bool showTrendAnnualizedReturn = input(true, "Show Trend Annualized Return", group=group2, tooltip=t4)
string tablePositionInput = input.string("Bottom Right", "Table Position", options=["Bottom Right", "Bottom Left", "Middle Right", "Middle Left", "Top Right", "Top Left", "Top Center", "Bottom Center"], group=group2, inline="fourthLine")
string textSizeInput = input.string( "Normal", "Text Size", options=["Normal", "Large", "Small"], group=group2, inline="fourthLine")
//========================================================================================================================================================================
// Helper function to get the multiplier based on timeframe
//========================================================================================================================================================================
get_tf_multiplier() =>
var float multiplier = 1.0
if syminfo.type == "crypto"
if timeframe.isdaily
multiplier := 365 // ~365 trading days per year
else if timeframe.isweekly
multiplier := 52 // 52 weeks per year
multiplier
else // Default for stocks and other asset types
if timeframe.isdaily
multiplier := 252 // ~252 trading days per year
else if timeframe.isweekly
multiplier := 52 // 52 weeks per year
multiplier
//=======================================================================================================================================================================
// Helper function to check if the timeframe is daily or weekly
//=======================================================================================================================================================================
is_valid_timeframe() =>
timeframe.isdaily or timeframe.isweekly
var string EXTEND_STYLE = switch extendStyle
"Extend Right" => extend.right
"Extend Both" => extend.both
"Extend None" => extend.none
=> extend.left
// Length Inputs
var array<int> Periods = periodMode ? array.from(na,300,350,400,450,500,550,600,650,700) : array.from(na,20,30,40)
// Calculate deviations, correlation, slope, and intercepts for different lengths
[stdDev01, pearsonR01, slope01, intercept01] = calcDev(sourceInput, Periods.get( 1))
[stdDev02, pearsonR02, slope02, intercept02] = calcDev(sourceInput, Periods.get( 2))
[stdDev03, pearsonR03, slope03, intercept03] = calcDev(sourceInput, Periods.get( 3))
if barstate.islast
// Find the highest Pearson's R
float highestPearsonR = math.max(pearsonR01, pearsonR02, pearsonR03)
// Determine selected length, slope, intercept, and deviations
int detectedPeriod = na
float detectedSlope = na
float detectedIntrcpt = na
float detectedStdDev = na
switch highestPearsonR
pearsonR01 =>
detectedPeriod := Periods.get(1)
detectedSlope := slope01
detectedIntrcpt := intercept01
detectedStdDev := stdDev01
pearsonR02 =>
detectedPeriod := Periods.get(2)
detectedSlope := slope02
detectedIntrcpt := intercept02
detectedStdDev := stdDev02
pearsonR03 =>
detectedPeriod := Periods.get(3)
detectedSlope := slope03
detectedIntrcpt := intercept03
detectedStdDev := stdDev03
var line upperLine = na, var linefill upperFill = na
var line baseLine = na
var line lowerLine = na, var linefill lowerFill = na
// Calculate start and end price based on detected slope and intercept
float startPrice = math.exp(detectedIntrcpt + detectedSlope * (detectedPeriod - 1))
float endPrice = math.exp(detectedIntrcpt)
int startAtBar = bar_index - detectedPeriod + 1
var color ChannelColor = color.new(colorInput, channelTransparency)
if na(baseLine)
baseLine := line.new(startAtBar, startPrice, bar_index, endPrice,
width=lineWidth, extend=EXTEND_STYLE,
color=color.new(colorInputMidline, transpInput),
style=midLineStyle == "Dotted" ? line.style_dotted :
midLineStyle == "Dashed" ? line.style_dashed : line.style_solid)
else
line.set_xy1(baseLine, startAtBar, startPrice)
line.set_xy2(baseLine, bar_index, endPrice)
float upperStartPrice = startPrice * math.exp(devMultiplier * detectedStdDev)
float upperEndPrice = endPrice * math.exp(devMultiplier * detectedStdDev)
if na(upperLine)
upperLine := line.new(startAtBar, upperStartPrice, bar_index, upperEndPrice,
width=1, extend=EXTEND_STYLE,
color=ChannelColor,
style=lineStyle1 == "Dotted" ? line.style_dotted :
lineStyle1 == "Dashed" ? line.style_dashed : line.style_solid)
else
line.set_xy1 (upperLine, startAtBar, upperStartPrice)
line.set_xy2 (upperLine, bar_index, upperEndPrice)
line.set_color(upperLine, colorInput)
float lowerStartPrice = startPrice / math.exp(devMultiplier * detectedStdDev)
float lowerEndPrice = endPrice / math.exp(devMultiplier * detectedStdDev)
if na(lowerLine)
lowerLine := line.new(startAtBar, lowerStartPrice, bar_index, lowerEndPrice,
width=1, extend=EXTEND_STYLE,
color=ChannelColor,
style=lineStyle1 == "Dotted" ? line.style_dotted :
lineStyle1 == "Dashed" ? line.style_dashed : line.style_solid)
else
line.set_xy1 (lowerLine, startAtBar, lowerStartPrice)
line.set_xy2 (lowerLine, bar_index, lowerEndPrice)
line.set_color(lowerLine, colorInput)
if na(upperFill)
upperFill := linefill.new(upperLine, baseLine, color=color.new(colorInput, fillTransparency))
if na(lowerFill)
lowerFill := linefill.new(baseLine, lowerLine, color=color.new(colorInput, fillTransparency))
var table t = na
if periodMode
t := table.new(position.bottom_center, 2, 3)
else
t := table.new(getTablePosition(tablePositionInput), 2, 3)
string text1 = periodMode ? " ̶⫍AutoPeriodLongTermt⫎̶ ̶" + str.tostring(detectedPeriod) : " ̶⫍AutoPeriod⫎̶ ̶" + str.tostring(detectedPeriod)
var colorInputLight = color.new(colorInput, 0)
// Display or hide the "Auto-Selected Period" cell
if showAutoSelectedPeriod
table.cell(t, 0, 0, text1, text_color=colorInputLight, text_size=textSizeInput == "Large" ? size.large : textSizeInput == "Small" ? size.small : size.normal)
// Display or hide the "Trend Strength" or "Pearson's R" cell
if showTrendStrength
if showPearsonInput
table.cell(t, 0, 1, " ̶⫍Pearson⫎̶ ̶: " + str.tostring(detectedSlope > 0.0 ? -highestPearsonR : highestPearsonR, "#.###"), text_color=colorInput, text_size=textSizeInput == "Large" ? size.large : textSizeInput == "Small" ? size.small : size.normal)
else
table.cell(t, 0, 1, " ̶⫍TrendStrength⫎̶ ̶" + confidence(highestPearsonR), text_color=colorInput, text_size=textSizeInput == "Large" ? size.large : textSizeInput == "Small" ? size.small : size.normal)
// Calculate CAGR
float cagr = na
if not na(detectedPeriod) and bar_index >= detectedPeriod and is_valid_timeframe()
float num_of_periods = detectedPeriod
float multiplier = get_tf_multiplier()
float startClosePrice = close[detectedPeriod - 1]
cagr := math.pow(close / startClosePrice, multiplier / num_of_periods) - 1
// Display or hide the "Trend Annualized Return" cell
if showTrendAnnualizedReturn and is_valid_timeframe()
table.cell(t, 0, 2, " ̶⫍TrendReturn⫎̶ ̶: " + (not na(cagr) ? str.tostring(cagr * 100, "#.#") + "%" : "N/A"), text_color=colorInput, text_size=textSizeInput == "Large" ? size.large : textSizeInput == "Small" ? size.small : size.normal)
//==================================================================================================================================================================================================================================================
How to Apply Pine Script in TradingView:
- Open TradingView and log in.
- Navigate to the Pine Script Editor at the bottom of the screen.
- Copy the provided Pine Script code.
- Paste it into the editor and click Save.
- Name the script, e.g., “Advanced Trendline and Volume Profile.”
- Click Add to Chart to apply it to your selected chart.
- Customize the settings via the indicator panel to suit your trading style.
Key Features of the Script:
- Advanced Volume Profile:
- Displays high, average, and low trading activity nodes for volume or money flow.
- Highlights significant price levels such as supply and demand zones and consolidation levels.
- Sentiment and Heatmap Visualization:
- Provides sentiment analysis with bullish and bearish nodes based on price action.
- Includes a dynamic heatmap for a clearer representation of trading activity.
- Customizable ATR-Based Stop-Loss:
- Incorporates ATR calculations for long and short positions.
- Adjustable parameters for risk management tailored to market volatility.
- Dynamic Trendline Channel:
- Automatically calculates short-term and long-term channels using Pearson’s R for trend strength.
- Offers customizable midline, upper, and lower band settings.
- Multi-Timeframe Analysis:
- Analyzes trends and deviations across different timeframes with customizable periods.
- Automatically adapts to selected chart resolution for accuracy.
- Integrated Table Display:
- Summarizes key metrics such as auto-selected periods, trend strength, and annualized return (CAGR).
- Fully adjustable table position, size, and data display settings.
- Customizable Alerts:
- Alerts for breakouts, deviations, and key trading levels.
- Ideal for real-time notifications and proactive trade management.
Recommended Usage:
- Trend Analysis and Forecasting:
- Use the trendline channel and volume profile to identify market trends and anticipate reversals.
- Ideal for swing traders and investors seeking long-term perspectives.
- Day Trading and Scalping:
- Employ ATR stop-losses and dynamic sentiment analysis to manage short-term positions.
- Risk Management:
- Leverage ATR-based calculations and visualized zones to optimize entry and exit points.
- Comprehensive Market Visualization:
- Utilize sentiment profiles and heatmaps for a complete picture of market activity.
Script Evaluation:
- Functionality: 4.9/5
The script combines multiple trading tools into a single framework, making it versatile and powerful for traders of all levels. - Ease of Use: 4.5/5
While highly customizable, the sheer number of settings may require some learning for beginners. - Accuracy: 4.8/5
Trendline calculations and volume profile visualizations are accurate, providing actionable insights for traders. - Repainting:
This script does not repaint, as all calculations are performed on closed bars and do not adjust past data. - Overall Score: 4.8/5
A robust and comprehensive tool that streamlines analysis and improves trading efficiency.
RELATED POSTS
View all