1
1
atr = ta.atr(30)
createRSLine (color) =>
line.new(na, na, na, na, extend = expandLines ? extend.both : extend.none,
xloc=xloc.bar_time, color = color, width = lineWidth, style = lineStyle == "----" ?
line.style_dashed : lineStyle == "...." ? line.style_dotted : line.style_solid)
createRSLabel () =>
label.new(na, na, "", style = label.style_none, textcolor = textColor)
type customPoint
int t
float price
type RSInfo
bool isBroken = na
int brokenTime = na
string RSType = na
float price = na
line line = na
box box = na
label priceLabel = na
customPoint[] points = na
label[] debugPoints = na
label breakLabel = na
label[] retestLabels = na
line breakLine = na
box breakBox = na
curTR = ta.tr(true)
lowPivot = ta.pivotlow(low, pivotRange, pivotRange)
highPivot = ta.pivothigh(high, pivotRange, pivotRange)
pivotTime = time[pivotRange]
newRSInfoF
newRS.debugPoints := array.new<label>(0)
newRS.retestLabels := array.new<label>(0)
newRS.points := array.new<customPoint>(0)
if enableZones
newRS.box := createRSBox(RSType == "Resistance" ? resistanceColor :
supportColor, xloc.bar_time)
moveRSInfoBox(newRS.box, startTime, newRS.price, endTime)
box.set_extend(newRS.box, expandLines ? extend.both : extend.none)
box.set_text(newRS.box, histText)
else
newRS.line := line.copy(RSInfoF.line)
moveLine(newRS.line, startTime, newRS.price, endTime)
line.set_extend(newRS.line, expandLines ? extend.both : extend.none)
newRS.priceLabel := label.copy(RSInfoF.priceLabel)
label.set_text(newRS.priceLabel, histText)
label.set_xloc(newRS.priceLabel, (startTime + endTime) / 2, xloc.bar_time)
if not na(newRS.breakLabel)
newRS.breakLabel := label.copy(RSInfoF.breakLabel)
newRS
if RSInfoF.debugPoints.size() > 0
for i = 0 to RSInfoF.debugPoints.size() - 1
label.delete(RSInfoF.debugPoints.get(i))
if RSInfoF.retestLabels.size() > 0
for i = 0 to RSInfoF.retestLabels.size() - 1
label.delete(RSInfoF.retestLabels.get(i))
label.delete(RSInfoF.breakLabel)
line.delete(RSInfoF.breakLine)
box.delete(RSInfoF.breakBox)
type timeframeInfo
int index = na
string timeframeStr = na
bool isEnabled = false
RSInfo[] resistances = na
RSInfo[] supports = na
float[] highPivots = na
float[] highTRs = na
int[] highTimes = na
float[] lowPivots = na
float[] lowTRs = na
int[] lowTimes = na
newTFInfo.resistances := array.new<RSInfo>(debug_lastXResistances)
newTFInfo.supports := array.new<RSInfo>(debug_lastXSupports)
newTFInfo.highPivots := array.new<float>()
newTFInfo.highTRs := array.new<float>()
newTFInfo.highTimes := array.new<int>()
newTFInfo.lowPivots := array.new<float>()
newTFInfo.lowTRs := array.new<float>()
newTFInfo.lowTimes := array.new<int>()
newTFInfo
doValuesTouch (float value1, float value2, float tr, float customATRRatio) =>
if math.abs(value1 - value2) <= tr * customATRRatio
true
else
false
index = pivotsCount - i - 1
occurances = 0
invalidValue = false
pivotValue1 = pivots.get(index)
if bannedValues.size() > 0
for a = 0 to bannedValues.size() - 1
if doValuesTouch(pivotValue1, bannedValues.get(a),
trs.get(index))
invalidValue := true
break
if invalidValue
continue
for j = 0 to pivotsCount - 1
if j >= maxTraverse
break
index2 = pivotsCount - j - 1
pivotValue2 = pivots.get(index2)
if doValuesTouch(pivotValue1, pivotValue2, trs.get(index))
occurances += 1
if not na(latestRSF)
break
if not na(latestRSF)
cnt = 0
if pivotsCount > 0
for i = 0 to pivotsCount - 1
if i >= maxTraverse
break
index = pivotsCount - i - 1
pivotValue = pivots.get(index)
if doValuesTouch(pivotValue, latestRSF.price, trs.get(index))
labelTime = times.get(index)
latestRSF.points.push(customPoint.new(labelTime, pivotValue))
cnt += 1
if cnt == strength
break
curIndex = 0
float foundBreakLevel = na
int foundBreakTime = na
float foundBreakTR = na
while true
if curIndex >= maxTraverse
break
shortSum = 0.0
longSum = 0.0
for i = 0 to shortTerm
shortSum += volume[curIndex + i]
for i = 0 to longTerm
longSum += volume[curIndex + i]
if isTrueBreakout
foundBreakLevel := rsInfo.RSType == "Resistance" ? low[curIndex] :
high[curIndex]
foundBreakTime := time[curIndex]
foundBreakTR := high[curIndex] - low[curIndex]
curIndex += 1
if time[curIndex] <= rsInfo.points.get(rsInfo.points.size() - 1).t
break
[foundBreakLevel, foundBreakTime, foundBreakTR]
curIndex = 0
lastRetestIndex = -999
int[] retestTimes = array.new<int>()
float[] retestLevels = array.new<float>()
float[] retestTRs = array.new<float>()
while true
if curIndex >= maxTraverse
break
if retestLevels.size() == maxRetestLabels
break
if rsInfo.isBroken and time[curIndex] >= rsInfo.brokenTime
curIndex += 1
continue
tr = high[curIndex] - low[curIndex]
isRetest = (rsInfo.RSType == "Resistance" ? (doValuesTouch(rsInfo.price,
close[curIndex], tr, retestATR) or doValuesTouch(rsInfo.price, high[curIndex], tr,
retestATR)) : (doValuesTouch(rsInfo.price, close[curIndex], tr, retestATR) or
doValuesTouch(rsInfo.price, low[curIndex], tr, retestATR)))
if isRetest and curIndex - lastRetestIndex >= retestLabelEveryXBars
retestLevels.push(rsInfo.RSType == "Resistance" ? high[curIndex] :
low[curIndex])
retestTimes.push(time[curIndex])
retestTRs.push(high[curIndex] - low[curIndex])
lastRetestIndex := curIndex
curIndex += 1
if time[curIndex] <= rsInfo.points.get(rsInfo.points.size() - 1).t
break
[retestLevels, retestTimes, retestTRs]
if not na(foundBreakLevel)
if showBreaks
if na(RSInfoF.breakLabel)
RSInfoF.breakLabel := createBreakLabel(RSInfoF.RSType)
label.set_xy(RSInfoF.breakLabel, foundBreakTime, foundBreakLevel +
(RSInfoF.RSType == "Resistance" ? (-foundBreakTR / labelOffsetY) : foundBreakTR /
labelOffsetY))
if expandLines
if na(RSInfoF.breakLine) and enableZones == false
RSInfoF.breakLine := createRSLine(color.black)
if not enableZones
line.set_extend(RSInfoF.breakLine, extend.right)
else
box.set_extend(RSInfoF.breakBox, extend.right)
if showRetests
[retestLevels, retestTimes, retestTRs] = getRetests(RSInfoF)
timeSkipOffset = 0
if enableZones
zoneEndX = time + timeSkipOffset +
timeframe.in_seconds(timeframe.period) * 1000 * labelOffsetsXIndex
startTime = math.min(time, RSInfoF.points.get(RSInfoF.points.size() -
1).t)
moveRSInfoBox(RSInfoF.box, startTime, RSInfoF.price, na(foundBreakTime)
? zoneEndX : foundBreakTime)
moveRSInfoBox(RSInfoF.breakBox, foundBreakTime, RSInfoF.price,
zoneEndX)
else
endTime = time + timeSkipOffset +
timeframe.in_seconds(timeframe.period) * 1000
startTime = math.min(time, RSInfoF.points.get(RSInfoF.points.size() -
1).t)
moveLine(RSInfoF.line, startTime, RSInfoF.price, na(foundBreakTime) ?
endTime : foundBreakTime)
moveLine(RSInfoF.breakLine, foundBreakTime, RSInfoF.price, endTime)
//log.info(str.tostring(RSInfoF.price) + " | " +
str.tostring(RSInfoF.points.get(strength - 1).time) + " = " +
str.tostring(line.get_x1(RSInfoF.line)) + " | " + str.tostring(endTime) + " = " +
str.tostring(line.get_x2(RSInfoF.line)))
if expandLines
if not enableZones
line.set_extend(RSInfoF.line, (na(foundBreakTime)) ? extend.both :
extend.left)
else
box.set_extend(RSInfoF.box, (na(foundBreakTime)) ? extend.both :
extend.left)
else
if not enableZones
line.set_extend(RSInfoF.line, na(foundBreakTime) ? extend.right :
extend.none)
else
box.set_extend(RSInfoF.box, na(foundBreakTime) ? extend.right :
extend.none)
if not enableZones
label.set_text(RSInfoF.priceLabel, enableZones ? "" : labelTitle)
label.set_y(RSInfoF.priceLabel, RSInfoF.price)
else
box.set_text(RSInfoF.box, (RSInfoF.isBroken and expandLines) ? "" :
labelTitle)
box.set_text(RSInfoF.breakBox, labelTitle)
timeframeInfoF.lowTimes.clear()
timeframeInfoF.highTimes.clear()
timeframeInfoF.lowTRs.clear()
timeframeInfoF.highTRs.clear()
timeframeInfoF.lowPivots := lowPivots
timeframeInfoF.highPivots := highPivots
timeframeInfoF.lowTimes := lowTimes
timeframeInfoF.highTimes := highTimes
timeframeInfoF.lowTRs := lowTRs
timeframeInfoF.highTRs := highTRs
if timeframeInfoF.resistances.size() > 0
for j = 0 to timeframeInfoF.resistances.size() - 1
RSInfo RSInfoF = timeframeInfoF.resistances.get(j)
if not na(RSInfoF)
if enabledHistory
if checkIfArrHasRS(oldRSList, RSInfoF) == false
oldRSList.push(RSInfoF)
oldRetestsCount += RSInfoF.retestLabels.size()
oldBreaksCount += RSInfoF.isBroken ? 1 : 0
derenderRSInfo(RSInfoF)
if timeframeInfoF.supports.size() > 0
for j = 0 to timeframeInfoF.supports.size() - 1
RSInfo RSInfoF = timeframeInfoF.supports.get(j)
if not na(RSInfoF)
if enabledHistory
if checkIfArrHasRS(history, RSInfoF) == false
oldRSList.push(RSInfoF)
oldRetestsCount += RSInfoF.retestLabels.size()
oldBreaksCount += RSInfoF.isBroken ? 1 : 0
derenderRSInfo(RSInfoF)
timeframeInfoF.resistances.clear()
timeframeInfoF.supports.clear()
[oldRetestsCount, oldBreaksCount]
if count > 0
for j = 0 to count - 1
foundRS = findLatestNthRS(timeframeInfoF, RSType, pivots, times, trs, j
+ 1)
if not na(foundRS)
notDuplicate = true
for a = 0 to timeframeInfos.size() - 1
aInfo = timeframeInfos.get(a)
if na(aInfo) or aInfo.isEnabled == false
continue
otherTimeframeArray = (RSType == "Resistance" ?
aInfo.resistances : aInfo.supports)
if otherTimeframeArray.size() > 0
for b = 0 to otherTimeframeArray.size() - 1
if checkIfRSAreSame(foundRS,
otherTimeframeArray.get(b))
notDuplicate := false
break
if notDuplicate == false
break
if arr.size() > 0
for j = 0 to arr.size() - 1
curRS = arr.get(j)
if not na(curRS)
handleRSInfo(timeframeInfoF, curRS, j, RSType)
curRetestsCount += curRS.retestLabels.size()
curBreaksCount += curRS.isBroken ? 1 : 0
[curRetestsCount, curBreaksCount]
//#region Pivots
if insideSession
if not na(lowPivot)
allLowPivots.push(lowPivot)
allLowTimes.push(pivotTime)
allLowTR.push(curTR[pivotRange])
if allLowPivots.size() > maxPivotsAllowed
allLowPivots.remove(0)
allLowTimes.remove(0)
allLowTR.remove(0)
if not na(highPivot)
allHighPivots.push(highPivot)
allHighTimes.push(pivotTime)
allHighTR.push(curTR[pivotRange])
if allHighPivots.size() > maxPivotsAllowed
allHighPivots.remove(0)
allHighTimes.remove(0)
allHighTR.remove(0)
//#endregion
//plot(nz(na,timeframeInfos.get(0).highPivots.size() > 0 ?
timeframeInfos.get(0).highPivots.get(timeframeInfos.get(0).highPivots.size() - 1) :
0), color = color.blue, title = "High Pivots")
//plot(nz(na,timeframeInfos.get(0).lowPivots.size() > 0 ?
timeframeInfos.get(0).lowPivots.get(timeframeInfos.get(0).lowPivots.size() - 1) :
0), color = color.fuchsia, title = "Low Pivots")
int oldRetestsCount = 0
int curRetestsCount = 0
int oldBreaksCount = 0
int curBreaksCount = 0
for i = 0 to timeframeCount - 1
timeframeInfo curInfo = timeframeInfos.get(i)
if not curInfo.isEnabled
continue
if enabledHistory
historyIndexesToDelete = array.new<int>(0)
if history.size() > 0
for i = 0 to history.size() - 1
if checkIfArrHasRS(curRSList, history.get(i))
historyIndexesToDelete.push(i)
if historyIndexesToDelete.size() > 0
for i = 0 to historyIndexesToDelete.size() - 1
deleteIndex =
historyIndexesToDelete.get(historyIndexesToDelete.size() - i - 1)
safeDeleteRSInfo(history.get(deleteIndex))
history.remove(deleteIndex)
if oldRSList.size() > 0
for i = 0 to oldRSList.size() - 1
curRS = oldRSList.get(i)
if checkIfArrHasRS(curRSList, curRS) == false
history.push(histRSInfo(curRS))
if history.size() > debug_maxHistoryRecords
safeDeleteRSInfo(history.get(0))
history.remove(0)
if oldRSList.size() > 0
for i = 0 to oldRSList.size() - 1
safeDeleteRSInfo(oldRSList.get(i))
curRSList.clear()
oldRSList.clear()
if DEBUG
log.info("History Size : " + str.tostring(history.size()))
log.info("Label Count : " + str.tostring(label.all.size()))
log.info("Line Count : " + str.tostring(line.all.size()))
log.info("Box Count : " + str.tostring(box.all.size()))
initRun := false
///////////////////////////////////////////////////////////////////////////////////
///////////////
//@version=5
//
// Author: JustUncleL
// Revision: R1.2
// Date: 6-Jan-2018
//
// Description:
// ============
// This indicator is a Super Guppy version of standard Guppy GMMA as used in
// "CM_GUPPY_EMA Revised R2 by JustUncleL". Guppy is designed to capture the
// inferred behaviour of traders and investors by using two groups of averages.
// In this version of Super Guppy Traders Group of EMAs are:
// EMA3 to EMA23 step 2 (Aqua=Uptrend, Blue=downtrend)
// and Investors Group EMAs are:
// EMA25 to EMA70 step 3 (Lime=Uptrend, Red=downtrend)
// (Gray=Trend not established or in a Pull Back).
//
// The idea of Guppy EMAs is to use fractal repetitions to identify points of
// agreement and disagreement which precede significant trend changes.
// For further info on how Guppy/Super Guppy can be used in trading please refer
to
// http://www.guppytraders.com/gup329.shtml
// and many other articles available on the subject.
//
// This indicator provides the following :
// - Swing Arrow Alerts (Red for Sell and Green for Buy) to indicate PullBack
entries
// after new trend has been established. Also have option to wait for both fast
and
// slow to completely seperate (Confluence). Another option is to show alerts
// when show arrows when Candle colour changes, this is handy when using Heikin
Ashi
// or Renko Charts.
// - Trend Break Arrow Alerts (Blue for Sell and Aqua for Buy) to indicate entries
// for agressive trend swing point and is calculated by cross over of the
// average Traders EMA with the average Investors EMA. This was suggested option
// by Guppy himself.
// - Anchor time frame (0=current). This is the time frame that the Guppy MAs are
// calculated for. This way 60 Guppy can be viewed on a 15 min chart to
establish
// tighter Stop Loss conditions.
// - Alert conditions are also created for the TradingView Alarm subsystem. Only
// alerts for the selected alert options are generated.
//
// References:
// ===========
// - Based on Daryl Guppy GMMA and
// CM GMMA Original - https://www.tradingview.com/v/3rxOtFe0/
// - http://www.guppytraders.com/gup329.shtml
//
//
// Revisions:
// ==========
// R1 - Original Version
//
// R1.1 - Some changes to limit the number of Alerts that occur close together.
//
// 13-Jan-2018
// - Fix bug in Anchor calculations when chart Time frame not intraday.
// - Fix bug in Break Arrow calculation, stop signal when Investor MAs
// not change direction yet.
// - Change Traders group to start colouring before Investors Group,
// rather than together.
//
// R1.2 14-Feb-2018
// - Fix bug in 1st pullback arrow calculation.
// - Added option to display candle colours relative to Guppy Trend
// indication.
// 06-Apr-2018
// - Change Anchor to be based purely on Minutes, so 1 month=30240mins
// (21 trading days), 1 week=7200mins (5 trading days), 1 Day=1440mins.
// This makes it more consistent across intraday and extraday chart
Timeframes.
//
//
// -----------------------------------------------------------------------------
// Copyright 2014 Chris Moody
// Copyright 2018 JustUncleL
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// The GNU General Public License can be found here
// <http://www.gnu.org/licenses/>.
//
// -----------------------------------------------------------------------------
//
y = ta.ema(close, 55)
// z = sma(close, 200)
// -----------------------------------------------------------------------------
//
//
// Use Alternate Anchor TF for MAs
anchor = input.int(0, minval=0, maxval=1440, title='Use Alternate Anchor TimeFrame
(0=none, max=1440 (mins,D,W)')
//
src = input(close, title='EMA Source')
ShowBreak = input(true, title='Show Trend Break Arrow Alerts')
ShowSwing = input(true, title='Show Swing Arrow Alerts')
ShowCon = input(false, title='Give Only Fast+Slow Confluence Alerts')
uOCCswing = input(false, title='Add Bar Colour Changes to Swing Alerts')
Lookback = input(6, title='Alert Lookback Length')
ShowAvgs = input(false, title='Show Average Fast and Slow Guppy Curves')
show200 = input(false, title='Show 200 EMA Curve')
emaFilter = input(false, title='Filter Alerts with 200ema')
clrBars = input(false, title='Colour Candles to Guppy Trend state')
//
//Fast EMAs
lenF1 = input.int(3, minval=1, title='Fast EMA 1')
lenF2 = input.int(5, minval=1, title='Fast EMA 2')
lenF3 = input.int(7, minval=1, title='Fast EMA 3')
lenF4 = input.int(9, minval=1, title='Fast EMA 4')
lenF5 = input.int(11, minval=1, title='Fast EMA 5')
lenF6 = input.int(13, minval=1, title='Fast EMA 6')
lenF7 = input.int(15, minval=1, title='Fast EMA 7')
lenF8 = input.int(17, minval=1, title='Fast EMA 8')
lenF9 = input.int(19, minval=1, title='Fast EMA 9')
lenF10 = input.int(21, minval=1, title='Fast EMA 10')
lenF11 = input.int(23, minval=1, title='Fast EMA 11')
//Slow EMAs
lenS1 = input.int(25, minval=1, title='Slow EMA 1')
lenS2 = input.int(28, minval=1, title='Slow EMA 2')
lenS3 = input.int(31, minval=1, title='Slow EMA 3')
lenS4 = input.int(34, minval=1, title='Slow EMA 4')
lenS5 = input.int(37, minval=1, title='Slow EMA 5')
lenS6 = input.int(40, minval=1, title='Slow EMA 6')
lenS7 = input.int(43, minval=1, title='Slow EMA 7')
lenS8 = input.int(46, minval=1, title='Slow EMA 8')
lenS9 = input.int(49, minval=1, title='Slow EMA 9')
lenS10 = input.int(52, minval=1, title='Slow EMA 10')
lenS11 = input.int(55, minval=1, title='Slow EMA 11')
lenS12 = input.int(58, minval=1, title='Slow EMA 12')
lenS13 = input.int(61, minval=1, title='Slow EMA 13')
lenS14 = input.int(64, minval=1, title='Slow EMA 14')
lenS15 = input.int(67, minval=1, title='Slow EMA 15')
lenS16 = input.int(70, minval=1, title='Slow EMA 16')
gold = #FFD700
AQUA = #00FFFFFF
BLUE = #0000FFFF
GRAY = #808080FF
//Fast EMA
emaF1 = ta.ema(src, lenF1 * mult)
emaF2 = ta.ema(src, lenF2 * mult)
emaF3 = ta.ema(src, lenF3 * mult)
emaF4 = ta.ema(src, lenF4 * mult)
emaF5 = ta.ema(src, lenF5 * mult)
emaF6 = ta.ema(src, lenF6 * mult)
emaF7 = ta.ema(src, lenF7 * mult)
emaF8 = ta.ema(src, lenF8 * mult)
emaF9 = ta.ema(src, lenF9 * mult)
emaF10 = ta.ema(src, lenF10 * mult)
emaF11 = ta.ema(src, lenF11 * mult)
//average
emafast = (emaF1 + emaF2 + emaF3 + emaF4 + emaF5 + emaF6 + emaF7 + emaF8 + emaF9 +
emaF10 + emaF11) / 11
//
//Slow EMA
emaS1 = ta.ema(src, lenS1 * mult)
emaS2 = ta.ema(src, lenS2 * mult)
emaS3 = ta.ema(src, lenS3 * mult)
emaS4 = ta.ema(src, lenS4 * mult)
emaS5 = ta.ema(src, lenS5 * mult)
emaS6 = ta.ema(src, lenS6 * mult)
emaS7 = ta.ema(src, lenS7 * mult)
emaS8 = ta.ema(src, lenS8 * mult)
emaS9 = ta.ema(src, lenS9 * mult)
emaS10 = ta.ema(src, lenS10 * mult)
emaS11 = ta.ema(src, lenS11 * mult)
emaS12 = ta.ema(src, lenS12 * mult)
emaS13 = ta.ema(src, lenS13 * mult)
emaS14 = ta.ema(src, lenS14 * mult)
emaS15 = ta.ema(src, lenS15 * mult)
emaS16 = ta.ema(src, lenS16 * mult)
// average
emaslow = (emaS1 + emaS2 + emaS3 + emaS4 + emaS5 + emaS6 + emaS7 + emaS8 + emaS9 +
emaS10 + emaS11 + emaS12 + emaS13 + emaS14 + emaS15 + emaS16) / 16
//
//EMA 200
ema200 = ta.ema(src, len * mult)
//
fill(p33, p43, color=color.new(color.silver, 95))
//
//eof
// EMA 1
ema1 = ta.ema(src, len)
plot(ema1, title="EMA 1", color=color.white, style=plot.style_line, linewidth=1)
// Resistance Channel 2
channel = input.bool(false, title="Resistance Channel 2 On/Off")
var float up = na
var float down = na
if (close < nz(up[1]) and close > nz(down[1]))
up := nz(up[1])
down := nz(down[1])
else
up := high
down := low
plot(channel ? up : na, color=color.red, linewidth=1, style=plot.style_linebr,
title="Resistance Level Top")
plot(channel ? down : na, color=color.green, linewidth=1, style=plot.style_linebr,
title="Resistance Level Bottom")
// Fractals
length = input.int(55, title="Fractal Length")
filterFractals = input.bool(true, title="Signal Filter On/Off")
ftop = high[2] > high[3] and high[2] > high[4] and high[2] > high[1] and high[2] >
high[0]
fbot = low[2] < low[3] and low[2] < low[4] and low[2] < low[1] and low[1] < low[0]
topf = ftop and high[2] >= ta.highest(high, length)
botf = fbot and low[2] <= ta.lowest(low, length)
filteredtopf = filterFractals ? topf : ftop
filteredbotf = filterFractals ? botf : fbot
plotshape(filteredtopf, style=shape.triangledown, location=location.abovebar,
color=color.maroon, text="SELL", offset=-1)
plotshape(filteredbotf, style=shape.triangleup, location=location.belowbar,
color=color.green, text="BUY", offset=-1)
// VWAP
vwap = ta.vwap(close)
plot(vwap, title="VWAP", color=color.purple, linewidth=2)