Objective: If consolidation zones are plotted at Upper value (example 53000 and lower value 52500) with lines, the same should be visible on 5 min chart at same levels. This is to see consolidation zone of higher timeframes on the chart with lower timeframe. with below code, the zones are identified and plotted correctly on 15 min chart but same zone levels are not plotted when the chart is changed to 5 min time frame.
Summary of the Issue:
I’m working on a TradingView indicator that calculates consolidation zones on the 15-minute timeframe and want to plot them on a 5-minute chart [code below]. The consolidation zones are determined using request.security() to fetch 15-minute OHLC data and are calculated via a library function. While this approach works initially, a critical issue arises:
When I switch from a 15-minute chart to a 5-minute chart, the entire consolidation logic is recalculated on the 5-minute chart.
This leads to inconsistent results because request.security() behaves dynamically based on the chart’s timeframe and recalculates for each bar of the lower timeframe.
Despite persisting the consolidation values in var variables, they still reset when the chart timeframe changes, as Pine Script reinitializes the script entirely.
Key Challenges:
Preventing Logic Recalculation: The 15-minute consolidation zones should remain fixed and not be recalculated when switching to the 5-minute chart.
Persistent Storage: The calculated consolidation zones need to remain intact across timeframe changes without being reset or recalculated.
Displaying on Lower Timeframes: The zones must plot consistently on the 5-minute chart without breaking the higher timeframe logic.
Looking for:
A robust method to prevent logic recalculation when switching timeframes in Pine Script.
Best practices for persisting higher timeframe values and plotting them accurately on lower timeframes.
Suggestions or alternative approaches to retain calculated values without recalculating the entire script.
Any insights or solutions from the community would be greatly appreciated!
What I’ve Tried:
Using var Variables: Persistent storage for lastCondHigh_15m and lastCondLow_15m with conditional updates, but these values still reset upon a timeframe change.
Dynamic Requests: Ensured request.security() fetches 15-minute data, but recalculations happen due to script reinitialization.
Bypassing Logic on Lower Timeframes: Attempted to conditionally disable recalculations on the 5-minute chart, yet values are still inconsistent.
Moved the consolidation logic to library, still not able to solve the problem
So in short, when the code is defined to fetch data of 15min chart and plot condhigh_15m, condlow_15m, it should retain the values of these variable on 5 min chart and should not recalculate.
// 15 min consolidation code begins
// Inputs (hardcoded)
prd_15m = 10 // Hardcoded Loopback Period
conslen_15m = 3 // Hardcoded Min Consolidation Length
paintcons_15m = true // Hardcoded Paint Consolidation Area
zonecol_15m = color.new(color.blue, 70) // Hardcoded Zone Color
var bool lastCondLowBreakDown_15m = false
// Variables
var int dir_15m = 0
var float condhigh_15m = na
var float condlow_15m = na
var float lastCondHigh_15m = na
var float lastCondLow_15m = na
var line upline_15m = na
var line dnline_15m = na
var bool isConsolidating_15m = false
// Get 15-min timeframe high/low data
high_15m = request.security(syminfo.tickerid, "15", high)
low_15m = request.security(syminfo.tickerid, "15", low)
close_15m = request.security(syminfo.tickerid, "15", close)
open_15m = request.security(syminfo.tickerid, "15", open)
// Compute highest and lowest bars for the loopback period
float highest_bar_15m = (ta.highest(high_15m, prd_15m) == high_15m ? high_15m : na)
float lowest_bar_15m = (ta.lowest(low_15m, prd_15m) == low_15m ? low_15m : na)
// Direction determination
dir_15m := highest_bar_15m and na(lowest_bar_15m) ? 1 : (lowest_bar_15m and na(highest_bar_15m) ? -1 : dir_15m)
float zz_15m = na
zz_15m := highest_bar_15m ? highest_bar_15m : (lowest_bar_15m ? lowest_bar_15m : na)
// Pivot point tracking
float pivot_point_15m = na
for y = 0 to 500
if na(close_15m) or dir_15m != dir_15m[y]
break
if zz_15m[y]
if na(pivot_point_15m)
pivot_point_15m := zz_15m[y]
else
if dir_15m[y] == 1 and zz_15m[y] > pivot_point_15m
pivot_point_15m := zz_15m[y]
if dir_15m[y] == -1 and zz_15m[y] < pivot_point_15m
pivot_point_15m := zz_15m[y]
// Consolidation tracking
var int cons_count_15m = 0
bool breakout_up_15m = false
bool breakout_down_15m = false
float highest_cons_15m = ta.highest(high_15m, conslen_15m)
float lowest_cons_15m = ta.lowest(low_15m, conslen_15m)
bool breakoutup_15m = false
bool breakoutdown_15m = false
bool BreakDown_SignalGenerated_15m = false
bool BreakUpSignalGenerated_15m = false
// Updated breakout logic to allow multiple candles to confirm the breakout
if math.abs(pivot_point_15m - pivot_point_15m[1]) >= ((close_15m/100)*0.02)
if cons_count_15m > conslen_15m
if pivot_point_15m > condhigh_15m+((close_15m/100)*0.03) and close_15m > condhigh_15m+((close_15m/100)*0.03)
breakoutup_15m := true
if pivot_point_15m < condlow_15m-((close_15m/100)*0.03) and close_15m < condlow_15m-((close_15m/100)*0.03)
breakoutdown_15m := true
if ta.change(pivot_point_15m)
if cons_count_15m > conslen_15m
breakout_up_15m := pivot_point_15m > condhigh_15m
breakout_down_15m := pivot_point_15m < condlow_15m
if cons_count_15m > 0 and pivot_point_15m <= condhigh_15m and pivot_point_15m >= condlow_15m
cons_count_15m := cons_count_15m + 1
else
cons_count_15m := 0
else
cons_count_15m := cons_count_15m + 1
if cons_count_15m >= conslen_15m
if cons_count_15m == conslen_15m
condhigh_15m := highest_cons_15m
condlow_15m := lowest_cons_15m
if (close_15m > condlow_15m and close_15m < condhigh_15m)
isConsolidating_15m := true
lastCondHigh_15m := condhigh_15m
lastCondLow_15m := condlow_15m
if (close_15m >lastCondLow_15m and close_15m <lastCondHigh_15m)
isConsolidating_15m := true
else
line.delete(upline_15m)
line.delete(dnline_15m)
condhigh_15m := math.max(condhigh_15m, high_15m)
condlow_15m := math.min(condlow_15m, low_15m)
if (validTimeframe_15m)
upline_15m := line.new(bar_index, condhigh_15m, bar_index - cons_count_15m, condhigh_15m, color=color.red, style=line.style_solid, width=5)
dnline_15m := line.new(bar_index, condlow_15m, bar_index - cons_count_15m, condlow_15m, color=color.lime, style=line.style_solid, width=5)
else
if breakoutup_15m or breakoutdown_15m or close_15m>condhigh_15m+((close_15m/100)*0.03) or close_15m<condlow_15m-((close_15m/100)*0.03)
isConsolidating_15m := false
if (not isConsolidating_15m and not breakoutdown_15m and not BreakDown_SignalGenerated_15m)
if (open_15m>lastCondLow_15m and close_15m <lastCondLow_15m)
lastCondLowBreakDown_15m := true
BreakDown_SignalGenerated_15m := true
if (not isConsolidating_15m and not BreakOutUp_SignalGenerated_15m)
if ((open_15m<lastCondHigh_15m and close_15m >lastCondHigh_15m and not BreakOutUp_SignalGenerated_15m ) or(open_15m>lastCondHigh_15m and open_15m-lastCondHigh_15m<((close_15m/100)*0.03) and close_15m>open_15m and close_15m-lastCondHigh_15m>((close_15m/100)*0.04)))
lastCondHighBreakUp_15m := true
BreakUpSignalGenerated_15m := true
Bhairav BankNifty is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.