1Copy the scriptPress Copy script above, or the copy button on the code below.
2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.
Source Code
154 lines of Pine Script v6 from SK_Current_Day_POC_VAH_VAL.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.
SK_Current_Day_POC_VAH_VAL.pine
// [ad] Current Day POC / VAH / VAL v1.0
// Developing current-session profile built from visible chart bars. Values are
// approximate because Pine scripts do not receive TradingView's internal
// tick-by-tick Volume Profile bins.
//@version=6
indicator("[ad] Current Day POC / VAH / VAL v1.0", shorttitle = "ad DAY VP", overlay = true, max_lines_count = 10, max_labels_count = 10)
string groupProfile = "Current day profile"
string profileTimezone = input.string("Etc/UTC", "Profile timezone", options = ["Etc/UTC", "Europe/Warsaw", "America/New_York", "exchange"], group = groupProfile)
string profileSession = input.session("0000-2359:1234567", "Profile session", group = groupProfile, tooltip = "Default is the full UTC day, suitable for 24/7 crypto. Choose exchange timezone and adjust the session for other markets.")
int rows = input.int(48, "Price rows", minval = 24, maxval = 100, group = groupProfile)
float valueAreaPercent = input.float(70.0, "Value area percent", minval = 50.0, maxval = 99.0, step = 1.0, group = groupProfile)
int maximumStoredBars = input.int(2000, "Maximum stored intraday bars", minval = 250, maxval = 5000, group = groupProfile)
bool showLabels = input.bool(true, "Show labels", group = groupProfile)
string timezone = profileTimezone == "exchange" ? syminfo.timezone : profileTimezone
int sessionTime = time(timeframe.period, profileSession, timezone)
int profileDay = time("D", profileSession, timezone)
bool inSession = timeframe.isintraday and not na(sessionTime)
int profileDayChange = ta.change(profileDay)
bool newProfileDay = not na(profileDay) and profileDayChange != 0
var int[] storedTimes = array.new_int()
var float[] storedHighs = array.new_float()
var float[] storedLows = array.new_float()
var float[] storedVolumes = array.new_float()
if newProfileDay
array.clear(storedTimes)
array.clear(storedHighs)
array.clear(storedLows)
array.clear(storedVolumes)
if inSession
bool newStoredBar = array.size(storedTimes) == 0 or array.get(storedTimes, array.size(storedTimes) - 1) != time
if newStoredBar
array.push(storedTimes, time)
array.push(storedHighs, high)
array.push(storedLows, low)
array.push(storedVolumes, nz(volume))
else
int lastIndex = array.size(storedTimes) - 1
array.set(storedHighs, lastIndex, high)
array.set(storedLows, lastIndex, low)
array.set(storedVolumes, lastIndex, nz(volume))
while array.size(storedTimes) > maximumStoredBars
array.shift(storedTimes)
array.shift(storedHighs)
array.shift(storedLows)
array.shift(storedVolumes)
var line pocLine = na
var line vahLine = na
var line valLine = na
var label pocLabel = na
var label vahLabel = na
var label valLabel = na
var label warningLabel = na
var float currentPoc = na
var float currentVah = na
var float currentVal = na
f_delete_drawings() =>
if not na(pocLine)
line.delete(pocLine)
if not na(vahLine)
line.delete(vahLine)
if not na(valLine)
line.delete(valLine)
if not na(pocLabel)
label.delete(pocLabel)
if not na(vahLabel)
label.delete(vahLabel)
if not na(valLabel)
label.delete(valLabel)
if not na(warningLabel)
label.delete(warningLabel)
if barstate.islast
f_delete_drawings()
pocLine := na
vahLine := na
valLine := na
pocLabel := na
vahLabel := na
valLabel := na
warningLabel := na
currentPoc := na
currentVah := na
currentVal := na
if not timeframe.isintraday
warningLabel := label.new(bar_index, high, "Current Day Profile requires an intraday chart", xloc = xloc.bar_index, yloc = yloc.price, style = label.style_label_down, color = color.new(color.red, 72), textcolor = color.white, size = size.small)
else if array.size(storedTimes) > 0
float profileLow = array.min(storedLows)
float profileHigh = array.max(storedHighs)
float profileRange = profileHigh - profileLow
if profileRange > 0
float rowHeight = profileRange / rows
float[] rowVolumes = array.new_float(rows, 0.0)
float totalVolume = 0.0
for i = 0 to array.size(storedTimes) - 1
float barHigh = array.get(storedHighs, i)
float barLow = array.get(storedLows, i)
float barVolume = array.get(storedVolumes, i)
totalVolume += barVolume
if barHigh > barLow
int firstRow = math.max(0, math.min(rows - 1, int(math.floor((barLow - profileLow) / rowHeight))))
int lastRow = math.max(0, math.min(rows - 1, int(math.floor((barHigh - profileLow) / rowHeight))))
for row = firstRow to lastRow
float rowBottom = profileLow + row * rowHeight
float rowTop = rowBottom + rowHeight
float overlap = math.max(0.0, math.min(barHigh, rowTop) - math.max(barLow, rowBottom))
if overlap > 0
array.set(rowVolumes, row, array.get(rowVolumes, row) + barVolume * overlap / (barHigh - barLow))
else
int row = math.max(0, math.min(rows - 1, int(math.floor((barLow - profileLow) / rowHeight))))
array.set(rowVolumes, row, array.get(rowVolumes, row) + barVolume)
if totalVolume > 0
int pocIndex = array.indexof(rowVolumes, array.max(rowVolumes))
int valueAreaLowIndex = pocIndex
int valueAreaHighIndex = pocIndex
float includedVolume = array.get(rowVolumes, pocIndex)
float targetVolume = totalVolume * valueAreaPercent / 100.0
while includedVolume < targetVolume and (valueAreaLowIndex > 0 or valueAreaHighIndex < rows - 1)
float volumeAbove = valueAreaHighIndex < rows - 1 ? array.get(rowVolumes, valueAreaHighIndex + 1) : -1.0
float volumeBelow = valueAreaLowIndex > 0 ? array.get(rowVolumes, valueAreaLowIndex - 1) : -1.0
if volumeAbove >= volumeBelow
valueAreaHighIndex += 1
includedVolume += math.max(volumeAbove, 0.0)
else
valueAreaLowIndex -= 1
includedVolume += math.max(volumeBelow, 0.0)
currentPoc := profileLow + (pocIndex + 0.5) * rowHeight
currentVah := profileLow + (valueAreaHighIndex + 1.0) * rowHeight
currentVal := profileLow + valueAreaLowIndex * rowHeight
int leftTime = array.get(storedTimes, 0)
pocLine := line.new(leftTime, currentPoc, time_close, currentPoc, xloc = xloc.bar_time, extend = extend.right, color = color.rgb(255, 193, 7), width = 3)
vahLine := line.new(leftTime, currentVah, time_close, currentVah, xloc = xloc.bar_time, extend = extend.right, color = color.rgb(239, 83, 80), width = 1, style = line.style_dashed)
valLine := line.new(leftTime, currentVal, time_close, currentVal, xloc = xloc.bar_time, extend = extend.right, color = color.rgb(38, 166, 154), width = 1, style = line.style_dashed)
if showLabels
pocLabel := label.new(bar_index + 1, currentPoc, "POC " + str.tostring(currentPoc, format.mintick), xloc = xloc.bar_index, yloc = yloc.price, style = label.style_label_left, color = color.new(color.rgb(255, 193, 7), 78), textcolor = color.rgb(255, 193, 7), size = size.tiny)
vahLabel := label.new(bar_index + 1, currentVah, "VAH " + str.tostring(currentVah, format.mintick), xloc = xloc.bar_index, yloc = yloc.price, style = label.style_label_left, color = color.new(color.rgb(239, 83, 80), 78), textcolor = color.rgb(239, 83, 80), size = size.tiny)
valLabel := label.new(bar_index + 1, currentVal, "VAL " + str.tostring(currentVal, format.mintick), xloc = xloc.bar_index, yloc = yloc.price, style = label.style_label_left, color = color.new(color.rgb(38, 166, 154), 78), textcolor = color.rgb(38, 166, 154), size = size.tiny)
plot(currentPoc, "Developing POC", color = color.new(color.rgb(255, 193, 7), 100), display = display.data_window)
plot(currentVah, "Developing VAH", color = color.new(color.rgb(239, 83, 80), 100), display = display.data_window)
plot(currentVal, "Developing VAL", color = color.new(color.rgb(38, 166, 154), 100), display = display.data_window)
Overview
[ad] Current Day POC / VAH / VAL builds an approximate volume profile by distributing each stored chart bar's volume across a configurable number of price rows, then marks the heaviest row and the selected value-area band. Timezone, session hours, row count, value-area percent, stored-bar limit, and labels change the profile. It does not run on daily or higher charts, and the result can differ from TradingView's built-in Volume Profile because it uses chart bars rather than finer intrabar data.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
Profile timezone
string
Etc/UTC
profileTimezone
Profile session
session
0000-2359:1234567
profileSession
Price rows
int
48
rows
Value area percent
float
70.0
valueAreaPercent
Maximum stored intraday bars
int
2000
maximumStoredBars
Show labels
bool
true
showLabels
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.
This indicator calculates and plots a session-based volume profile directly on the price chart. It maps volume distribution across price levels, highlighting key structural reference points including the Point of Control, Value Area High, and Value Area Low. C
The Midnight VWAP indicator calculates and overlays two distinct Volume Weighted Average Price (VWAP) lines on the price chart based on customizable session timeframes. It tracks an overnight or pre-market session alongside regular trading hours, resetting cal
This overlay indicator plots option strike walls and an optional session VWAP on the price chart for SPY or ES. It spaces major strikes by the selected instrument, draws a set number of strikes on each side, and marks wall-trap and sweep events after a cooldow
This overlay indicator draws a volume profile for a chosen trading session directly on the price chart. It plots the point of control, value area high and low, an optional value area box, a live zone, and a session box with labels. Users select Tokyo, London,
This overlay indicator marks the current day's low and a suggested entry zone a fraction of daily ATR below that low. It compares daily volume with a volume moving average, plots daily SMA and EMA distance, and draws an optional ATR-width price cloud. Labels c
This indicator plots a Market Profile on the price chart using time-price opportunity letters or symbols. It marks the point of control, a configurable value area, and the initial balance, and it can highlight a volume-profile point of control and session VWAP