// Copyright 2025 Major Hayden
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//@version=6
indicator('Filtered Volume Markers', shorttitle = 'Vol Markers', overlay = true, dynamic_requests = true)
// Time filtering inputs (must match main indicator settings)
startHour = input.int(10, 'Start Hour', minval = 0, maxval = 23, group = 'Volume Filtering Hours (NYC Time)', tooltip = 'Only volume within these hours will be included in the filtered percentage calculation')
startMinute = input.int(30, 'Start Minute', minval = 0, maxval = 59, group = 'Volume Filtering Hours (NYC Time)')
endHour = input.int(15, 'End Hour', minval = 0, maxval = 23, group = 'Volume Filtering Hours (NYC Time)')
endMinute = input.int(00, 'End Minute', minval = 0, maxval = 59, group = 'Volume Filtering Hours (NYC Time)')
// Color zone thresholds (must match main indicator)
lowThreshold = input.float(30.0, 'Low Threshold (%)', minval = 0.0, maxval = 100.0, tooltip = 'Percentage below this will be colored red')
highThreshold = input.float(70.0, 'High Threshold (%)', minval = 0.0, maxval = 100.0, tooltip = 'Percentage above this will be colored green')
// Marker settings
showGreenMarkers = input.bool(true, 'Show Green Markers', tooltip = 'Show markers when filtered volume > high threshold')
showRedMarkers = input.bool(true, 'Show Red Markers', tooltip = 'Show markers when filtered volume < low threshold')
// Function to check if a time is within trading hours (NYC time)
isTimeInRange(t) =>
barHour = hour(t, 'America/New_York')
barMinute = minute(t, 'America/New_York')
// Convert times to minutes for easier comparison
barTimeInMinutes = barHour * 60 + barMinute
startTimeInMinutes = startHour * 60 + startMinute
endTimeInMinutes = endHour * 60 + endMinute
// Check if bar is within the time range
barTimeInMinutes >= startTimeInMinutes and barTimeInMinutes <= endTimeInMinutes
// Calculate filtered and unfiltered volume based on timeframe
filteredVolume = 0.0
unfilteredVolume = 0.0
if timeframe.isintraday
// For intraday charts, just check the current bar's time (no lower TF lookup needed)
nycTime = time('', 'America/New_York')
filteredVolume := isTimeInRange(nycTime) ? volume : 0
unfilteredVolume := volume
else
// For daily or higher timeframes, fetch lower timeframe data (30-min bars for performance)
volArray = request.security_lower_tf(syminfo.tickerid, '30', volume)
timeArray = request.security_lower_tf(syminfo.tickerid, '30', time)
float sessionVol = 0.0
float totalVol = 0.0
if array.size(volArray) > 0
for i = 0 to array.size(volArray) - 1
barVol = array.get(volArray, i)
barTime = array.get(timeArray, i)
totalVol += barVol
if isTimeInRange(barTime)
sessionVol += barVol
filteredVolume := sessionVol
unfilteredVolume := totalVol
// Calculate percentage (handle division by zero)
volumePercentage = unfilteredVolume > 0 ? filteredVolume / unfilteredVolume * 100 : 0.0
// Detect if we've reached the filter start time yet (to avoid showing red before filter starts)
hasReachedFilterStart = true // Default to true
if timeframe.isintraday
// For intraday, check if current bar time is past the start time
nycTime = time('', 'America/New_York')
barHour = hour(nycTime, 'America/New_York')
barMinute = minute(nycTime, 'America/New_York')
barTimeInMinutes = barHour * 60 + barMinute
startTimeInMinutes = startHour * 60 + startMinute
hasReachedFilterStart := barTimeInMinutes >= startTimeInMinutes
else
// For daily+, check if any lower TF bar has reached or passed the start time
timeArray = request.security_lower_tf(syminfo.tickerid, '30', time)
if array.size(timeArray) > 0
lastBarTime = array.get(timeArray, array.size(timeArray) - 1)
lastBarTimeInMinutes = hour(lastBarTime, 'America/New_York') * 60 + minute(lastBarTime, 'America/New_York')
startTimeInMinutes = startHour * 60 + startMinute
hasReachedFilterStart := lastBarTimeInMinutes >= startTimeInMinutes
// Determine conditions for markers (only show red after filter start time)
isGreen = volumePercentage > highThreshold
isRed = hasReachedFilterStart and volumePercentage < lowThreshold
// Plot markers below the bar
plotshape(showGreenMarkers and isGreen, title = 'High Quality Volume', style = shape.circle, location = location.belowbar, color = color.green, size = size.auto)
plotshape(showRedMarkers and isRed, title = 'Low Quality Volume', style = shape.circle, location = location.belowbar, color = color.red, size = size.auto)
Overview
On intraday charts, it evaluates whether the current bar falls inside the session, while on higher timeframes it retrieves 30-minute intraday volume to calculate the session's volume share. When the percentage crosses above a high threshold or falls below a low threshold, visual markers appear directly on the price chart. Users can adjust session hours, minutes, and threshold percentages.
Configurable time window filtering in New York time
Dynamic lower-timeframe volume aggregation on higher timeframes
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
Start Hour
int
10
startHour
Start Minute
int
30
startMinute
End Hour
int
15
endHour
End Minute
int
00
endMinute
Low Threshold (%)
float
30.0
lowThreshold
High Threshold (%)
float
70.0
highThreshold
Show Green Markers
bool
true
showGreenMarkers
Show Red Markers
bool
true
showRedMarkers
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
An educational Pine Script v4 indicator demonstrating how to plot volume histograms on the main price chart using unscaled axes. The code includes examples and commented templates for creating vertical line markers at specific dates or time zones, such as mark
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