Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
25 views49 pages

Pine Script

This document contains a Pine Script™ code for a trading indicator called 'Weighted Volume Profile Pivot Points' developed by Flux Charts. It includes various configurations and settings for displaying order blocks and pivot points on trading charts, along with functionalities for analyzing market data. The script is designed to be customizable, allowing users to adjust parameters such as volume weighting, swing length, and the number of order blocks displayed.

Uploaded by

brianototo15
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views49 pages

Pine Script

This document contains a Pine Script™ code for a trading indicator called 'Weighted Volume Profile Pivot Points' developed by Flux Charts. It includes various configurations and settings for displaying order blocks and pivot points on trading charts, along with functionalities for analyzing market data. The script is designed to be customizable, allowing users to adjust parameters such as volume weighting, swing length, and the number of order blocks displayed.

Uploaded by

brianototo15
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 49

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.

0 at
https://mozilla.org/MPL/2.0/

// © fluxchart

//@version=5

const bool DEBUG = false

const bool OBSettings = false

const int maxBoxesCount = 500

const int maxRowSize = 50

const int priceBoxSize = 5

const int v2Gap = 1

const string v2TextSize = size.small

const int edgeOffset = 25

const int minDistance = 125

const float overlapThresholdPercentage = 0

const int maxDistanceToLastBar = 1750 // Affects Running Time


const int maxOrderBlocks = 30

indicator("Weighted Volume Profile Pivot Points | Flux Charts", shorttitle = "WVPPP | Flux Charts",
overlay = true, max_boxes_count = maxBoxesCount, max_labels_count = maxBoxesCount,
max_lines_count = maxBoxesCount, max_bars_back = 1005)

showPreviousSessions = input.bool(true, "Show Previous Sessions", group = "General Configuration",


display = display.none)

dbgMode = input.string("Order Blocks", "Mode", options = ["Pivots", "Order Blocks"], group = "General
Configuration")

analyzeBars = input.int(200, "Analyze Bars", minval = 1, maxval = 1000, group = "General Configuration")

rowCount = input.int(30, "Row Count", minval = 1, maxval = 1000, group = "General Configuration")

volumeWeight = input.string("Normal", "Volume Weighting", ["Recent", "Normal", "Past"], group =


"General Configuration", display = display.none)

swingLen = input.int(10, "Swing Length", minval = 1, group = "General Configuration")

keepOldPOC = input.bool(true, "Keep Past POC Lines", group = "General Configuration")

intersectionBody = DEBUG ? input.bool(false, "[DBG] Intersection With Body", group = "General


Configuration") : false
// OB Settings

showInvalidated = OBSettings ? input.bool(true, "Show Historic Zones", group = "Order Blocks", display =
display.none) : true

OBRendering = OBSettings ? input.bool(true, "Show Order Blocks", group = "Order Blocks", display =
display.none) : false

orderBlockVolumetricInfo = OBSettings ? input.bool(true, "Volumetric Info", group = "Order Blocks",


inline="EV", display = display.none) : true

obEndMethod = OBSettings ? input.string("Wick", "Zone Invalidation", options = ["Wick", "Close"],


group = "Order Blocks", display = display.none) : "Wick"

combineOBs = DEBUG ? input.bool(true, "Combine Zones", group = "Order Blocks", display =


display.none) : true

maxATRMult = DEBUG ? input.float(3.5,"Max Atr Multiplier", group = "Order Blocks") : 3.5

zoneCount = OBSettings ? input.string("Low", 'Zone Count', options = ["High", "Medium", "Low", "One"],
tooltip = "Number of Order Block Zones to be rendered. Higher options will result in older Order Blocks
shown.", group = "Order Blocks", display = display.none) : "Low"

bullOrderBlockColor = OBSettings ? input(#08998180, 'Bullish', inline = 'obColor', group = 'Order Blocks',


display = display.none) : #08998180

bearOrderBlockColor = OBSettings ? input(#f2364680, 'Bearish', inline = 'obColor', group = 'Order


Blocks', display = display.none) : #f2364680

bullishOrderBlocks = zoneCount == "One" ? 1 : zoneCount == "Low" ? 3 : zoneCount == "Medium" ? 5 :


10
bearishOrderBlocks = zoneCount == "One" ? 1 : zoneCount == "Low" ? 3 : zoneCount == "Medium" ? 5 :
10

timeframe1Enabled = true

timeframe1 = ""

highlightSessions = input.bool(true, "Highlight Sessions", group = "Style", display = display.none)

dbgStyling = DEBUG ? input.string("v2", "[DBG] Styling", ["v1", "v2"], group = "Style", display =
display.none) : "v2"

alignSetting = input.string("Left", "Align To", options = ["Left", "Right"], group = "Style", display =
display.none)

POCEnabled = input.bool(true, "POC Line ", inline = "POC", group = "Style", display = display.none)

POCLineStyle = input.string("____", " ", options = ["____", "----", "...."], group = "Style", inline = "POC",
display = display.none)

POCLineWidth = input.int(2, "", options = [1,2,3], group = "Style", inline = "POC", display = display.none)

POCLineColor = input.color(color.yellow, "", group = "Style", inline = "POC", display = display.none)

bullishColor = input.color(#089981, "Bullish", inline = "color", group = "Style", display = display.none)


bearishColor = input.color(#f23646, "Bearish", inline = "color", group = "Style", display = display.none)

textColor = input.color(#ffffff80, "Text Color", group = "Style")

extendZonesBy = DEBUG ? input.int(15, "Extend Zones", group = "Style", minval = 1, maxval = 30, inline =
"ExtendZones") : 15

extendZonesDynamic = DEBUG ? input.bool(true, "Dynamic", group = "Style", inline = "ExtendZones") :


true

combinedText = DEBUG ? input.bool(false, "Combined Text", group = "Style", inline =


"CombinedColor") : false

volumeBarsPlace = DEBUG ? input.string("Left", "Show Volume Bars At", options = ["Left", "Right"],
group = "Style", inline = "volumebars") : "Left"

mirrorVolumeBars = DEBUG ? input.bool(true, "Mirror Volume Bars", group = "Style", inline =


"volumebars") : true

volumeBarsLeftSide = (volumeBarsPlace == "Left")

extendZonesByTime = extendZonesBy * timeframe.in_seconds(timeframe.period) * 1000

atr = ta.atr(10)
type orderBlockInfo

float top

float bottom

float obVolume

string obType

int startTime

float bbVolume

float obLowVolume

float obHighVolume

bool breaker

int breakTime

string timeframeStr

bool disabled = false

string combinedTimeframesStr = na

bool combined = false


type orderBlock

orderBlockInfo info

bool isRendered = false

box orderBox = na

box breakerBox = na

line orderBoxLineTop = na

line orderBoxLineBottom = na

line breakerBoxLineTop = na

line breakerBoxLineBottom = na

//

box orderBoxText = na

box orderBoxPositive = na

box orderBoxNegative = na
line orderSeperator = na

line orderTextSeperator = na

createOrderBlock (orderBlockInfo orderBlockInfoF) =>

orderBlock newOrderBlock = orderBlock.new(orderBlockInfoF)

newOrderBlock

safeDeleteOrderBlock (orderBlock orderBlockF) =>

orderBlockF.isRendered := false

box.delete(orderBlockF.orderBox)

box.delete(orderBlockF.breakerBox)

box.delete(orderBlockF.orderBoxText)

box.delete(orderBlockF.orderBoxPositive)

box.delete(orderBlockF.orderBoxNegative)
line.delete(orderBlockF.orderBoxLineTop)

line.delete(orderBlockF.orderBoxLineBottom)

line.delete(orderBlockF.breakerBoxLineTop)

line.delete(orderBlockF.breakerBoxLineBottom)

line.delete(orderBlockF.orderSeperator)

line.delete(orderBlockF.orderTextSeperator)

type timeframeInfo

int index = na

string timeframeStr = na

bool isEnabled = false

orderBlockInfo[] bullishOrderBlocksList = na

orderBlockInfo[] bearishOrderBlocksList = na

newTimeframeInfo (index, timeframeStr, isEnabled) =>


newTFInfo = timeframeInfo.new()

newTFInfo.index := index

newTFInfo.isEnabled := isEnabled

newTFInfo.timeframeStr := timeframeStr

newTFInfo

type obSwing

int x = na

float y = na

float swingVolume = na

bool crossed = false

// ____ TYPES END ____


var timeframeInfo[] timeframeInfos = array.from(newTimeframeInfo(1, timeframe1,
timeframe1Enabled))

var bullishOrderBlocksList = array.new<orderBlockInfo>(0)

var bearishOrderBlocksList = array.new<orderBlockInfo>(0)

var allOrderBlocksList = array.new<orderBlock>(0)

moveLine(_line, _x, _y, _x2) =>

line.set_xy1(_line, _x, _y)

line.set_xy2(_line, _x2, _y)

moveBox (_box, _topLeftX, _topLeftY, _bottomRightX, _bottomRightY) =>

box.set_lefttop(_box, _topLeftX, _topLeftY)

box.set_rightbottom(_box, _bottomRightX, _bottomRightY)

isTimeframeLower (timeframe1F, timeframe2F) =>


timeframe.in_seconds(timeframe1F) < timeframe.in_seconds(timeframe2F)

getMinTimeframe (timeframe1F, timeframe2F) =>

if isTimeframeLower(timeframe1F, timeframe2F)

timeframe1F

else

timeframe2F

getMaxTimeframe (timeframe1F, timeframe2F) =>

if isTimeframeLower(timeframe1F, timeframe2F)

timeframe2F

else

timeframe1F

formatTimeframeString (formatTimeframe) =>

timeframeF = formatTimeframe == "" ? timeframe.period : formatTimeframe


if str.contains(timeframeF, "D") or str.contains(timeframeF, "W") or str.contains(timeframeF, "S") or
str.contains(timeframeF, "M")

timeframeF

else

seconds = timeframe.in_seconds(timeframeF)

if seconds >= 3600

hourCount = int(seconds / 3600)

str.tostring(hourCount) + " Hour" + (hourCount > 1 ? "s" : "")

else

timeframeF + " Min"

betterCross(s1, s2) =>

string ret = na

if s1 >= s2 and s1[1] < s2

ret := "Bull"
if s1 < s2 and s1[1] >= s2

ret := "Bear"

ret

colorWithTransparency (colorF, transparencyX) =>

color.new(colorF, color.t(colorF) * transparencyX)

createOBBox (boxColor, transparencyX = 1.0, xlocType = xloc.bar_time) =>

box.new(na, na, na, na, text_size = size.normal, xloc = xlocType, extend = extend.none, bgcolor =
colorWithTransparency(boxColor, transparencyX), text_color = textColor, text_halign =
text.align_center, border_color = #00000000)

renderOrderBlock (orderBlock ob) =>

orderBlockInfo info = ob.info

ob.isRendered := true

orderColor = ob.info.obType == "Bull" ? bullOrderBlockColor : bearOrderBlockColor


if OBRendering and (not false or not (false and info.breaker)) and not (not showInvalidated and
info.breaker)

ob.orderBox := createOBBox(orderColor, 1.5)

if ob.info.combined

ob.orderBox.set_bgcolor(colorWithTransparency(orderColor, 1.1))

ob.orderBoxText := createOBBox(color.new(color.white, 100))

if orderBlockVolumetricInfo

ob.orderBoxPositive := createOBBox(bullOrderBlockColor)

ob.orderBoxNegative := createOBBox(bearOrderBlockColor)

ob.orderSeperator :=
line.new(na,na,na,na,xloc.bar_time,extend.none,textColor,line.style_dashed,1)

ob.orderTextSeperator :=
line.new(na,na,na,na,xloc.bar_time,extend.none,textColor,line.style_solid,1)

zoneSize = extendZonesDynamic ? na(info.breakTime) ? extendZonesByTime : (info.breakTime -


info.startTime) : extendZonesByTime

if na(info.breakTime)

zoneSize := (time + 1) - info.startTime


startX = volumeBarsLeftSide ? info.startTime : info.startTime + zoneSize - zoneSize / 3

maxEndX = volumeBarsLeftSide ? info.startTime + zoneSize / 3 : info.startTime + zoneSize

moveBox(ob.orderBox, info.startTime, info.top, info.startTime + zoneSize, info.bottom)

moveBox(ob.orderBoxText, volumeBarsLeftSide ? maxEndX : info.startTime, info.top,


volumeBarsLeftSide ? info.startTime + zoneSize : startX, info.bottom)

percentage = int((math.min(info.obHighVolume, info.obLowVolume) /


math.max(info.obHighVolume, info.obLowVolume)) * 100.0)

OBText = (na(ob.info.combinedTimeframesStr) ? formatTimeframeString(ob.info.timeframeStr) :


ob.info.combinedTimeframesStr) + " OB"

box.set_text(ob.orderBoxText, (orderBlockVolumetricInfo ? str.tostring(ob.info.obVolume,


format.volume) + " (" + str.tostring(percentage) + "%)\n" : "") + (combinedText and ob.info.combined ?
"[Combined]\n" : "") + OBText)

if orderBlockVolumetricInfo

showHighLowBoxText = false
curEndXHigh = int(math.ceil((info.obHighVolume / info.obVolume) * (maxEndX - startX) + startX))

curEndXLow = int(math.ceil((info.obLowVolume / info.obVolume) * (maxEndX - startX) + startX))

moveBox(ob.orderBoxPositive, mirrorVolumeBars ? startX : curEndXLow, info.top,


mirrorVolumeBars ? curEndXHigh : maxEndX, (info.bottom + info.top) / 2)

box.set_text(ob.orderBoxPositive, showHighLowBoxText ? str.tostring(info.obHighVolume,


format.volume) : "")

moveBox(ob.orderBoxNegative, mirrorVolumeBars ? startX : curEndXHigh, info.bottom,


mirrorVolumeBars ? curEndXLow : maxEndX, (info.bottom + info.top) / 2)

box.set_text(ob.orderBoxNegative, showHighLowBoxText ? str.tostring(info.obLowVolume,


format.volume) : "")

moveLine(ob.orderSeperator, volumeBarsLeftSide ? startX : maxEndX, (info.bottom + info.top) /


2, volumeBarsLeftSide ? maxEndX : startX)

line.set_xy1(ob.orderTextSeperator, volumeBarsLeftSide ? maxEndX : startX, info.top)

line.set_xy2(ob.orderTextSeperator, volumeBarsLeftSide ? maxEndX : startX, info.bottom)


findOBSwings(len) =>

var swingType = 0

var obSwing top = obSwing.new(na, na)

var obSwing bottom = obSwing.new(na, na)

upper = ta.highest(len)

lower = ta.lowest(len)

swingType := high[len] > upper ? 0 : low[len] < lower ? 1 : swingType

if swingType == 0 and swingType[1] != 0

top := obSwing.new(bar_index[len], high[len], volume[len])

if swingType == 1 and swingType[1] != 1

bottom := obSwing.new(bar_index[len], low[len], volume[len])


[top, bottom]

findOrderBlocks () =>

if bar_index > last_bar_index - maxDistanceToLastBar and barstate.isconfirmed

[top, btm] = findOBSwings(swingLen)

useBody = false

max = useBody ? math.max(close, open) : high

min = useBody ? math.min(close, open) : low

// Bullish Order Block

bullishBreaked = 0

if bullishOrderBlocksList.size() > 0

for i = bullishOrderBlocksList.size() - 1 to 0

currentOB = bullishOrderBlocksList.get(i)
if not currentOB.breaker

if (obEndMethod == "Wick" ? low : math.min(open, close)) < currentOB.bottom

currentOB.breaker := true

currentOB.breakTime := time

currentOB.bbVolume := volume

else

if high > currentOB.top

bullishOrderBlocksList.remove(i)

else if i < bullishOrderBlocks and top.y < currentOB.top and top.y > currentOB.bottom

bullishBreaked := 1

if close > top.y and not top.crossed

top.crossed := true

boxBtm = max[1]

boxTop = min[1]
boxLoc = time[1]

for i = 1 to (bar_index - top.x) - 1

boxBtm := math.min(min[i], boxBtm)

boxTop := boxBtm == min[i] ? max[i] : boxTop

boxLoc := boxBtm == min[i] ? time[i] : boxLoc

newOrderBlockInfo = orderBlockInfo.new(boxTop, boxBtm, volume + volume[1] + volume[2],


"Bull", boxLoc)

newOrderBlockInfo.obLowVolume := volume[2]

newOrderBlockInfo.obHighVolume := volume + volume[1]

obSize = math.abs(newOrderBlockInfo.top - newOrderBlockInfo.bottom)

if obSize <= atr * maxATRMult

bullishOrderBlocksList.unshift(newOrderBlockInfo)

if bullishOrderBlocksList.size() > maxOrderBlocks


bullishOrderBlocksList.pop()

// Bearish Order Block

bearishBreaked = 0

if bearishOrderBlocksList.size() > 0

for i = bearishOrderBlocksList.size() - 1 to 0

currentOB = bearishOrderBlocksList.get(i)

if not currentOB.breaker

if (obEndMethod == "Wick" ? high : math.max(open, close)) > currentOB.top

currentOB.breaker := true

currentOB.breakTime := time

currentOB.bbVolume := volume

else
if low < currentOB.bottom

bearishOrderBlocksList.remove(i)

else if i < bearishOrderBlocks and btm.y > currentOB.bottom and btm.y < currentOB.top

bearishBreaked := 1

if close < btm.y and not btm.crossed

btm.crossed := true

boxBtm = min[1]

boxTop = max[1]

boxLoc = time[1]

for i = 1 to (bar_index - btm.x) - 1

boxTop := math.max(max[i], boxTop)

boxBtm := boxTop == max[i] ? min[i] : boxBtm

boxLoc := boxTop == max[i] ? time[i] : boxLoc


newOrderBlockInfo = orderBlockInfo.new(boxTop, boxBtm, volume + volume[1] + volume[2],
"Bear", boxLoc)

newOrderBlockInfo.obLowVolume := volume + volume[1]

newOrderBlockInfo.obHighVolume := volume[2]

obSize = math.abs(newOrderBlockInfo.top - newOrderBlockInfo.bottom)

if obSize <= atr * maxATRMult

bearishOrderBlocksList.unshift(newOrderBlockInfo)

if bearishOrderBlocksList.size() > maxOrderBlocks

bearishOrderBlocksList.pop()

true

areaOfOB (orderBlockInfo OBInfoF) =>

float XA1 = OBInfoF.startTime

float XA2 = na(OBInfoF.breakTime) ? time + 1 : OBInfoF.breakTime


float YA1 = OBInfoF.top

float YA2 = OBInfoF.bottom

float edge1 = math.sqrt((XA2 - XA1) * (XA2 - XA1) + (YA2 - YA2) * (YA2 - YA2))

float edge2 = math.sqrt((XA2 - XA2) * (XA2 - XA2) + (YA2 - YA1) * (YA2 - YA1))

float totalArea = edge1 * edge2

totalArea

doOBsTouch (orderBlockInfo OBInfo1, orderBlockInfo OBInfo2) =>

float XA1 = OBInfo1.startTime

float XA2 = na(OBInfo1.breakTime) ? time + 1 : OBInfo1.breakTime

float YA1 = OBInfo1.top

float YA2 = OBInfo1.bottom

float XB1 = OBInfo2.startTime

float XB2 = na(OBInfo2.breakTime) ? time + 1 : OBInfo2.breakTime

float YB1 = OBInfo2.top


float YB2 = OBInfo2.bottom

float intersectionArea = math.max(0, math.min(XA2, XB2) - math.max(XA1, XB1)) * math.max(0,


math.min(YA1, YB1) - math.max(YA2, YB2))

float unionArea = areaOfOB(OBInfo1) + areaOfOB(OBInfo2) - intersectionArea

float overlapPercentage = (intersectionArea / unionArea) * 100.0

if overlapPercentage > overlapThresholdPercentage

true

else

false

isOBValid (orderBlockInfo OBInfo) =>

valid = true

if OBInfo.disabled

valid := false
valid

combineOBsFunc () =>

if allOrderBlocksList.size() > 0

lastCombinations = 999

while lastCombinations > 0

lastCombinations := 0

for i = 0 to allOrderBlocksList.size() - 1

curOB1 = allOrderBlocksList.get(i)

for j = 0 to allOrderBlocksList.size() - 1

curOB2 = allOrderBlocksList.get(j)

if i == j

continue

if not isOBValid(curOB1.info) or not isOBValid(curOB2.info)

continue

if curOB1.info.obType != curOB2.info.obType
continue

if doOBsTouch(curOB1.info, curOB2.info)

curOB1.info.disabled := true

curOB2.info.disabled := true

orderBlock newOB = createOrderBlock(orderBlockInfo.new(math.max(curOB1.info.top,


curOB2.info.top), math.min(curOB1.info.bottom, curOB2.info.bottom), curOB1.info.obVolume +
curOB2.info.obVolume, curOB1.info.obType))

newOB.info.startTime := math.min(curOB1.info.startTime, curOB2.info.startTime)

newOB.info.breakTime := math.max(nz(curOB1.info.breakTime),
nz(curOB2.info.breakTime))

newOB.info.breakTime := newOB.info.breakTime == 0 ? na : newOB.info.breakTime

newOB.info.timeframeStr := curOB1.info.timeframeStr

newOB.info.obVolume := curOB1.info.obVolume + curOB2.info.obVolume

newOB.info.obLowVolume := curOB1.info.obLowVolume + curOB2.info.obLowVolume

newOB.info.obHighVolume := curOB1.info.obHighVolume + curOB2.info.obHighVolume

newOB.info.bbVolume := nz(curOB1.info.bbVolume, 0) + nz(curOB2.info.bbVolume, 0)

newOB.info.breaker := curOB1.info.breaker or curOB2.info.breaker


newOB.info.combined := true

if timeframe.in_seconds(curOB1.info.timeframeStr) !=
timeframe.in_seconds(curOB2.info.timeframeStr)

newOB.info.combinedTimeframesStr := (na(curOB1.info.combinedTimeframesStr) ?
formatTimeframeString(curOB1.info.timeframeStr) : curOB1.info.combinedTimeframesStr) + " & " +
(na(curOB2.info.combinedTimeframesStr) ? formatTimeframeString(curOB2.info.timeframeStr) :
curOB2.info.combinedTimeframesStr)

allOrderBlocksList.unshift(newOB)

lastCombinations += 1

reqSeq (timeframeStr) =>

[bullishOrderBlocksListF, bearishOrderBlocksListF] = request.security(syminfo.tickerid, timeframeStr,


[bullishOrderBlocksList, bearishOrderBlocksList])

[bullishOrderBlocksListF, bearishOrderBlocksListF]

getTFData (timeframeInfo timeframeInfoF, timeframeStr) =>


if not isTimeframeLower(timeframeInfoF.timeframeStr, timeframe.period) and
timeframeInfoF.isEnabled

[bullishOrderBlocksListF, bearishOrderBlocksListF] = reqSeq(timeframeStr)

[bullishOrderBlocksListF, bearishOrderBlocksListF]

else

[na, na]

handleTimeframeInfo (timeframeInfo timeframeInfoF, bullishOrderBlocksListF, bearishOrderBlocksListF)


=>

if not isTimeframeLower(timeframeInfoF.timeframeStr, timeframe.period) and


timeframeInfoF.isEnabled

timeframeInfoF.bullishOrderBlocksList := bullishOrderBlocksListF

timeframeInfoF.bearishOrderBlocksList := bearishOrderBlocksListF

handleOrderBlocksFinal () =>

if DEBUG

log.info("Bullish OB Count " + str.tostring(bullishOrderBlocksList.size()))


log.info("Bearish OB Count " + str.tostring(bearishOrderBlocksList.size()))

if allOrderBlocksList.size () > 0

for i = 0 to allOrderBlocksList.size() - 1

safeDeleteOrderBlock(allOrderBlocksList.get(i))

allOrderBlocksList.clear()

for i = 0 to timeframeInfos.size() - 1

curTimeframe = timeframeInfos.get(i)

if not curTimeframe.isEnabled

continue

if curTimeframe.bullishOrderBlocksList.size() > 0

for j = 0 to math.min(curTimeframe.bullishOrderBlocksList.size() - 1, bullishOrderBlocks - 1)

orderBlockInfoF = curTimeframe.bullishOrderBlocksList.get(j)

orderBlockInfoF.timeframeStr := curTimeframe.timeframeStr

allOrderBlocksList.unshift(createOrderBlock(orderBlockInfo.copy(orderBlockInfoF)))
if curTimeframe.bearishOrderBlocksList.size() > 0

for j = 0 to math.min(curTimeframe.bearishOrderBlocksList.size() - 1, bearishOrderBlocks - 1)

orderBlockInfoF = curTimeframe.bearishOrderBlocksList.get(j)

orderBlockInfoF.timeframeStr := curTimeframe.timeframeStr

allOrderBlocksList.unshift(createOrderBlock(orderBlockInfo.copy(orderBlockInfoF)))

if combineOBs

combineOBsFunc()

if allOrderBlocksList.size() > 0

for i = 0 to allOrderBlocksList.size() - 1

curOB = allOrderBlocksList.get(i)

if isOBValid(curOB.info)

renderOrderBlock(curOB)
findOrderBlocks()

[bullishOrderBlocksListTimeframe1, bearishOrderBlocksListTimeframe1] =
getTFData(timeframeInfos.get(0), timeframe1)

if barstate.isconfirmed

handleTimeframeInfo(timeframeInfos.get(0), bullishOrderBlocksListTimeframe1,
bearishOrderBlocksListTimeframe1)

handleOrderBlocksFinal()

type rowType

float top

float bottom

int startIndex

int endIndex

float totalVolume = 0

float bullVolume = 0
float bearVolume = 0

box bullBox = na

box priceBox = na

box bearBox = na

type volumeProfile

array<rowType> rows

line POCLine = na

box highlightBox = na

int edgeIndex = na

int startIndex = na

float vpTop = na

float vpBottom = na

int vpStart = na

int vpEnd = na
type barType

float o = open

float c = close

float h = high

float l = low

float v = volume

var float validPivotHigh = na

var float validPivotLow = na

var int distanceToLastVP = 999

var volumeProfile latestVolumeProfile = na

if not na(latestVolumeProfile)

distanceToLastVP := bar_index - latestVolumeProfile.vpStart


pvHigh = ta.pivothigh(swingLen, swingLen)

pvLow = ta.pivotlow(swingLen, swingLen)

var float vph = na

var float vpl = na

vph := nz(pvHigh, vph)

vpl := nz(pvLow, vpl)

if dbgMode == "Pivots"

if (alignSetting == "Left" and distanceToLastVP > minDistance) or (alignSetting == "Right" and


distanceToLastVP > minDistance)

validPivotHigh := vph

validPivotLow := vpl
else if dbgMode == "Order Blocks"

if (alignSetting == "Left" and distanceToLastVP > minDistance) or (alignSetting == "Right" and


distanceToLastVP > minDistance)

if bullishOrderBlocksList.size() > 0

curOB = bullishOrderBlocksList.get(0)

validPivotHigh := curOB.bottom

if bearishOrderBlocksList.size() > 0

curOB = bearishOrderBlocksList.get(0)

validPivotLow := curOB.top

pivotsChanged = false

if ((validPivotHigh != validPivotHigh[1]) or (validPivotLow != validPivotLow[1])) and (not


na(validPivotHigh)) and (not na(validPivotLow)) and math.abs(validPivotHigh - validPivotLow) > atr * 5

pivotsChanged := true
float top = validPivotHigh

float bottom = validPivotLow

float step = (top - bottom) / rowCount

float gap = rowCount < 100 ? (step / 3.0) : 0

var line oldLine = na

var box oldBox = na

var int latestEdgeIndex = na

if pivotsChanged

if not na(latestVolumeProfile)

latestVolumeProfile.vpEnd := bar_index

oldBox := latestVolumeProfile.highlightBox

if not keepOldPOC

line.delete(latestVolumeProfile.POCLine)
latestEdgeIndex := latestVolumeProfile.edgeIndex

oldLine := latestVolumeProfile.POCLine

latestVolumeProfile := volumeProfile.new()

latestVolumeProfile.vpStart := bar_index

latestVolumeProfile.vpTop := top

latestVolumeProfile.vpBottom := bottom

latestVolumeProfile.rows := array.new<rowType>(rowCount)

for x = 0 to rowCount - 1

rowTop = top - step * x

latestVolumeProfile.rows.set(x, rowType.new(rowTop, rowTop - step))

doIntersect (candleTop, candleBottom, rowType row) =>

if (candleBottom > row.top)

false

else if (candleTop < row.bottom)


false

else

true

var float maxVolumeSize = 0

var float minVolumeSize = 0

f_lin_interpolate(x0, y0, x1, y1, x) =>

y0 + (x - x0) * (y1 - y0) / (x1 - x0)

renderRow (startIndex, flip, rowType row) =>

totalSize = f_lin_interpolate(minVolumeSize, 1, maxVolumeSize, maxRowSize, row.totalVolume)

bullSize = nz(math.round((row.bullVolume / row.totalVolume) * totalSize), 0)

bearSize = nz(math.round((row.bearVolume / row.totalVolume) * totalSize), 0)

bullPercent = str.tostring(bullSize * 100.0 / totalSize, "#.##") + "%"

bearPercent = str.tostring(100.0 - str.tonumber(str.replace(bullPercent,"%","")), "#.##") + "%"


rowPrice = (row.top + row.bottom) / 2.0

if dbgStyling == "v2"

row.startIndex := startIndex - bullSize

if flip

row.startIndex := startIndex + bullSize

else

row.startIndex := startIndex

row.endIndex := row.startIndex

if dbgStyling == "v1"

if bullSize + bearSize > 0

if not flip

row.endIndex := row.startIndex + bullSize + bearSize

row.bullBox := box.new(row.startIndex, row.top - gap / 2.0, row.startIndex + bullSize,


row.bottom + gap / 2.0, bgcolor = bullishColor, border_color = color.black, border_width = 0)
if bearSize > 0

row.bearBox := box.new(row.startIndex + bullSize, row.top - gap / 2.0, row.startIndex +


bullSize + bearSize, row.bottom + gap / 2.0, bgcolor = bearishColor, border_color = color.black,
border_width = 0)

else

row.endIndex := row.startIndex - bullSize - bearSize

row.bullBox := box.new(row.startIndex, row.top - gap / 2.0, row.startIndex - bullSize,


row.bottom + gap / 2.0, bgcolor = bullishColor, border_color = color.black, border_width = 0)

if bearSize > 0

row.bearBox := box.new(row.startIndex - bullSize, row.top - gap / 2.0, row.startIndex -


bullSize - bearSize, row.bottom + gap / 2.0, bgcolor = bearishColor, border_color = color.black,
border_width = 0)

else if dbgStyling == "v2"

if not flip

row.endIndex := row.startIndex + bullSize + v2Gap + priceBoxSize + v2Gap + bearSize

if bullSize > 0

row.bullBox := box.new(row.startIndex, row.top - gap / 2.0, row.startIndex + bullSize,


row.bottom + gap / 2.0, text = bullPercent, text_size = v2TextSize, text_color = textColor, bgcolor =
color.new(bullishColor, 50), border_color = bullishColor, border_width = 1)

row.priceBox := box.new(row.startIndex + bullSize + v2Gap, row.top - gap / 2.0, row.startIndex +


bullSize + v2Gap + priceBoxSize, row.bottom + gap / 2.0, text = str.tostring(rowPrice, format.mintick),
text_color = textColor, text_size = v2TextSize, bgcolor = color.new(color.blue, 50), border_width = 1)

if bearSize > 0

row.bearBox := box.new(row.startIndex + bullSize + v2Gap + priceBoxSize + v2Gap, row.top -


gap / 2.0, row.startIndex + bullSize + v2Gap + priceBoxSize + v2Gap + bearSize, row.bottom + gap / 2.0,
text = bearPercent, text_size = v2TextSize, text_color = textColor, bgcolor = color.new(bearishColor, 50),
border_color = bearishColor, border_width = 1)

else

row.endIndex := row.startIndex - bullSize - v2Gap - priceBoxSize - v2Gap - bearSize

if bullSize > 0

row.bullBox := box.new(row.startIndex, row.top - gap / 2.0, row.startIndex - bullSize,


row.bottom + gap / 2.0, text = bullPercent, text_size = v2TextSize, text_color = textColor, bgcolor =
color.new(bullishColor, 50), border_color = bullishColor, border_width = 1)

row.priceBox := box.new(row.startIndex - bullSize - v2Gap, row.top - gap / 2.0, row.startIndex -


bullSize - v2Gap - priceBoxSize, row.bottom + gap / 2.0, text = str.tostring(rowPrice, format.mintick),
text_color = textColor, text_size = v2TextSize, bgcolor = color.new(color.blue, 50), border_width = 1)

if bearSize > 0

row.bearBox := box.new(row.startIndex - bullSize - v2Gap - priceBoxSize - v2Gap, row.top -


gap / 2.0, row.startIndex - bullSize - v2Gap - priceBoxSize - v2Gap - bearSize, row.bottom + gap / 2.0,
text = bearPercent, text_size = v2TextSize, text_color = textColor, bgcolor = color.new(bearishColor, 50),
border_color = bearishColor, border_width = 1)

curIndex = bar_index
const float weightImpact = 0.85

if ((bar_index > last_bar_index - maxDistanceToLastBar and barstate.isconfirmed and


showPreviousSessions) or (barstate.islast and not showPreviousSessions)) and (not
na(latestVolumeProfile))

for i = 0 to analyzeBars

for j = 0 to latestVolumeProfile.rows.size() - 1

curRow = latestVolumeProfile.rows.get(j)

vol = volume[i]

if volumeWeight == "Recent"

vol := ((vol * weightImpact) / (i + 1)) + (vol * (1.0 - weightImpact))

if volumeWeight == "Past"

vol := ((vol * weightImpact) * ((i + 1) / analyzeBars)) + (vol * (1.0 - weightImpact))


if doIntersect(intersectionBody ? math.max(open[i], close[i]) : high[i], intersectionBody ?
math.min(open[i], close[i]) : low[i], curRow)

if close[i] > open[i]

curRow.bullVolume += vol

else

curRow.bearVolume += vol

curRow.totalVolume += vol

//

maxVolumeSize := 0

minVolumeSize := latestVolumeProfile.rows.get(0).totalVolume

rowType maxVolRow = na

for i = 0 to latestVolumeProfile.rows.size() - 1

curRow = latestVolumeProfile.rows.get(i)

maxVolumeSize := math.max(maxVolumeSize, curRow.totalVolume)

if curRow.totalVolume == maxVolumeSize

maxVolRow := curRow
minVolumeSize := math.min(minVolumeSize, curRow.totalVolume)

int startIndex = na

if alignSetting == "Left"

startIndex := (curIndex - analyzeBars + 1)

if not na(latestEdgeIndex)

startIndex := math.max(startIndex, latestEdgeIndex + edgeOffset)

else

startIndex := (curIndex + 75)

if not na(latestEdgeIndex)

startIndex := math.max(startIndex, latestEdgeIndex + 75)

latestVolumeProfile.startIndex := startIndex

for i = 0 to latestVolumeProfile.rows.size() - 1

curRow = latestVolumeProfile.rows.get(i)
box.delete(curRow.bearBox)

box.delete(curRow.priceBox)

box.delete(curRow.bullBox)

renderRow(startIndex, alignSetting == "Left" ? false : true, curRow)

if alignSetting == "Left"

latestVolumeProfile.edgeIndex := math.max(nz(latestVolumeProfile.edgeIndex, 0),


curRow.endIndex)

else

latestVolumeProfile.edgeIndex := math.max(nz(latestVolumeProfile.edgeIndex, 0),


curRow.startIndex)

if not na(oldLine)

oldLine.set_extend(extend.none)

if alignSetting == "Left"

oldLine.set_xy2(startIndex, oldLine.get_y2())

else
oldLine.set_xy1(latestEdgeIndex, oldLine.get_y2())

oldLine.set_xy2(latestVolumeProfile.edgeIndex, oldLine.get_y2())

if not na(oldBox)

oldBox.set_right(startIndex)

line.delete(latestVolumeProfile.POCLine)

box.delete(latestVolumeProfile.highlightBox)

if highlightSessions and alignSetting == "Left"

latestVolumeProfile.highlightBox := box.new(startIndex, latestVolumeProfile.vpTop,


nz(latestVolumeProfile.vpEnd, bar_index), latestVolumeProfile.vpBottom, bgcolor =
color.new(color.blue, 80), border_width = 0)

maxRowMid = (maxVolRow.top + maxVolRow.bottom) / 2.0

if POCEnabled and maxVolRow.totalVolume > 0

if alignSetting == "Left"
latestVolumeProfile.POCLine := line.new(maxVolRow.endIndex, maxRowMid, bar_index,
maxRowMid, extend = extend.right, width = POCLineWidth, color = POCLineColor, style = POCLineStyle
== "____" ? line.style_solid : POCLineStyle == "----" ? line.style_dashed : line.style_dotted)

else

latestVolumeProfile.POCLine := line.new(bar_index, maxRowMid, maxVolRow.endIndex,


maxRowMid, extend = extend.left, width = POCLineWidth, color = POCLineColor, style = POCLineStyle ==
"____" ? line.style_solid : POCLineStyle == "----" ? line.style_dashed : line.style_dotted)

You might also like