Skip to content

Instantly share code, notes, and snippets.

@bnecreative
Created February 12, 2024 20:30
Show Gist options
  • Save bnecreative/501d48fdae3a8f40ad667dd0b2c669ba to your computer and use it in GitHub Desktop.
Save bnecreative/501d48fdae3a8f40ad667dd0b2c669ba to your computer and use it in GitHub Desktop.
PivotPoints
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © bluenotes
// Updated May 17 2023
// Fork of TradingView's "Pivot Points Standard" indicator
//@version=5
indicator("Pivot Points [blue]", "Pivot Points [blue]", overlay=true, max_lines_count=500, max_labels_count=500)
AUTO = "Auto"
DAILY = "Daily"
WEEKLY = "Weekly"
MONTHLY = "Monthly"
QUARTERLY = "Quarterly"
YEARLY = "Yearly"
BIYEARLY = "Biyearly"
TRIYEARLY = "Triyearly"
QUINQUENNIALLY = "Quinquennially"
DECENNIALLY = "Decennially"
TRADITIONAL = "Traditional"
kind = input.string(title="Type", defval="Traditional", options=[TRADITIONAL])
pivot_time_frame = input.string(title="Pivots Timeframe", defval=AUTO, options=[AUTO, DAILY, WEEKLY, MONTHLY, QUARTERLY, YEARLY, BIYEARLY, TRIYEARLY, QUINQUENNIALLY, DECENNIALLY])
look_back = input.int(title="Number of Pivots Back", defval=1, minval=1, maxval=20)
// Removing Daily setting as Equilibrium is based on the regular session - specifically for futures.
//is_daily_based = input.bool(title="Use Daily-based Values", defval=false, tooltip="When this option is unchecked, Pivot Points will use intraday data while calculating on intraday charts. If Extended Hours are displayed on the chart, they will be taken into account during the pivot level calculation. If intraday OHLC values are different from daily-based values (normal for stocks), the pivot levels will also differ.")
is_daily_based = false
show_labels = input.bool(title="Show Labels", defval=true, group="labels")
show_prices = input.bool(title="Show Prices", defval=true, group="labels")
show_timeframe = input.bool(title="Show Timeframe", defval=false, group="labels")
position_labels = input.string("Right", "Label Position", options=["Left", "Right"], group="labels")
label_size = input.string("Normal", "Label Size", options=["Tiny", "Small", "Normal"], group="labels")
line_width = input.int(title="Line Width", defval=1, minval=1, maxval=100, group="labels")
var DEF_COLOR = #FB8C00
var arr_time = array.new_int()
// Pivot (Equilibrium)
var p = array.new_float()
p_color = input.color(#4caf50, "Equilibrium", inline="EQ", group="Central Pivot Range")
p_show = input.bool(true, "", inline="EQ", group="Central Pivot Range")
// Pivot Range High
var tc = array.new_float()
tc_color = input.color(#ce65e3, "TC", inline="CPR", group="Central Pivot Range")
tc_show = input.bool(true, "", inline="CPR", group="Central Pivot Range")
// Pivot Range Low
var bc = array.new_float()
bc_color = input.color(#ce65e3, "BC", inline="CPR", group="Central Pivot Range")
bc_show = input.bool(true, "", inline="CPR", group="Central Pivot Range")
// Previous High
var h = array.new_float()
h_color = input.color(#FB8C00, "Prev High", inline="H/L", group="levels")
h_show = input.bool(true, "", inline="H/L", group="levels")
// Previous Low
var l = array.new_float()
l_color = input.color(#FB8C00, "Prev Low", inline="H/L", group="levels")
l_show = input.bool(true, "", inline="H/L", group="levels")
// R1
var r1 = array.new_float()
r1_color = input.color(#90bff9, "R1", inline="R1/MR1", group="levels")
r1_show = input.bool(true, "", inline="R1/MR1", group="levels")
// R1 Minor
var mr1 = array.new_float()
mr1_color = input.color(#9598a1, "Minor R1", inline="R1/MR1", group="levels")
mr1_show = input.bool(true, "", inline="R1/MR1", group="levels")
// R2
var r2 = array.new_float()
r2_color = input.color(#5b9cf6, "R2", inline="R2/MR2", group="levels")
r2_show = input.bool(true, "", inline="R2/MR2", group="levels")
// R2 Minor
var mr2 = array.new_float()
mr2_color = input.color(#9598a1, "Minor R2", inline="R2/MR2", group="levels")
mr2_show = input.bool(true, "", inline="R2/MR2", group="levels")
// R3
var r3 = array.new_float()
r3_color = input.color(#3179f5, "R3", inline="R3/M3", group="levels")
r3_show = input.bool(true, "", inline="R3/M3", group="levels")
// R3 Minor
var mr3 = array.new_float()
mr3_color = input.color(#9598a1, "Minor R3", inline="R3/M3", group="levels")
mr3_show = input.bool(true, "", inline="R3/M3", group="levels")
// R4
var r4 = array.new_float()
r4_color = input.color(#3179f5, "R4", inline="R4", group="levels")
r4_show = input.bool(true, "", inline="R4", group="levels")
// R5
var r5 = array.new_float()
r5_color = input.color(#3179f5, "R5", inline="R5", group="levels")
r5_show = input.bool(true, "", inline="R5", group="levels")
// S1
var s1 = array.new_float()
s1_color = input.color(#faa1a4, "S1", inline="S1/MS1" , group="levels")
s1_show = input.bool(true, "", inline="S1/MS1", group="levels")
// S1 Minor
var ms1 = array.new_float()
ms1_color = input.color(#9598a1, "Minor S1", inline="S1/MS1", group="levels")
ms1_show = input.bool(true, "", inline="S1/MS1", group="levels")
// S2
var s2 = array.new_float()
s2_color = input.color(#f77c80, "S2", inline="S2/MS2", group="levels")
s2_show = input.bool(true, "", inline="S2/MS2", group="levels")
// S2 Minor
var ms2 = array.new_float()
ms2_color = input.color(#9598a1, "Minor S2", inline="S2/MS2", group="levels")
ms2_show = input.bool(true, "", inline="S2/MS2", group="levels")
// S3
var s3 = array.new_float()
s3_color = input.color(#f7525f, "S3", inline="S3/MS3", group="levels")
s3_show = input.bool(true, "", inline="S3/MS3", group="levels")
// S3 Minor
var ms3 = array.new_float()
ms3_color = input.color(#9598a1, "Minor S3", inline="S3/MS3", group="levels")
ms3_show = input.bool(true, "", inline="S3/MS3", group="levels")
// S4
var s4 = array.new_float()
s4_color = input.color(#f7525f, "S4", inline="S4", group="levels")
s4_show = input.bool(true, "", inline="S4", group="levels")
// S5
var s5 = array.new_float()
s5_color = input.color(#f7525f, "S5", inline="S5", group="levels")
s5_show = input.bool(true, "", inline="S5", group="levels")
// Pivot Calculations
pivotX_open = float(na)
pivotX_open := nz(pivotX_open[1], open)
pivotX_high = float(na)
pivotX_high := nz(pivotX_high[1], high)
pivotX_low = float(na)
pivotX_low := nz(pivotX_low[1], low)
pivotX_prev_open = float(na)
pivotX_prev_open := nz(pivotX_prev_open[1])
pivotX_prev_high = float(na)
pivotX_prev_high := nz(pivotX_prev_high[1])
pivotX_prev_low = float(na)
pivotX_prev_low := nz(pivotX_prev_low[1])
pivotX_prev_close = float(na)
pivotX_prev_close := nz(pivotX_prev_close[1])
// Pivot Resolution
get_pivot_resolution() =>
resolution = "M"
if pivot_time_frame == AUTO
if timeframe.isintraday
resolution := timeframe.multiplier <= 15 ? "D" : "W"
else if timeframe.isweekly or timeframe.ismonthly
resolution := "12M"
else if pivot_time_frame == DAILY
resolution := "D"
else if pivot_time_frame == WEEKLY
resolution := "W"
else if pivot_time_frame == MONTHLY
resolution := "M"
else if pivot_time_frame == QUARTERLY
resolution := "3M"
else if pivot_time_frame == YEARLY or pivot_time_frame == BIYEARLY or pivot_time_frame == TRIYEARLY or pivot_time_frame == QUINQUENNIALLY or pivot_time_frame == DECENNIALLY
resolution := "12M"
resolution
// Lines / Label Arrays
var lines = array.new_line()
var labels = array.new_label()
draw_line(i, pivot, col, style=line.style_solid) =>
if array.size(arr_time) > 1
array.push(lines, line.new(array.get(arr_time, i), array.get(pivot, i), array.get(arr_time, i + 1), array.get(pivot, i), color=col, xloc=xloc.bar_time, width=line_width, style=style))
draw_label(i, y, txt, txt_color) =>
if (show_labels or show_prices) and not na(y)
display_text = (show_timeframe ? get_pivot_resolution() + " " : "") + (show_labels ? txt : "") + (show_prices ? str.format(" ({0})", math.round_to_mintick(y)) : "")
label_style = position_labels == "Left" ? label.style_label_right : label.style_label_left
x = position_labels == "Left" ? array.get(arr_time, i) : array.get(arr_time, i + 1)
position_label_size = size.normal
if( label_size == 'Tiny' )
position_label_size := size.tiny
if( label_size == 'Small' )
position_label_size := size.small
array.push(labels, label.new(x=x, y=y, text=display_text, textcolor=txt_color, size=position_label_size, style=label_style, color=#00000000, xloc=xloc.bar_time))
// Traditional (Floor) Pivot Calculations
traditional() =>
// EQ Calculation
pivotX_Median = (pivotX_prev_high + pivotX_prev_low + pivotX_prev_close) / 3
pivot_BC = (pivotX_prev_high + pivotX_prev_low) / 2
pivot_TC = (2 * pivotX_Median) - pivot_BC
// R1-5 Calculations
r1calc = pivotX_Median * 2 - pivotX_prev_low
r2calc = pivotX_Median + 1 * (pivotX_prev_high - pivotX_prev_low)
r3calc = pivotX_Median * 2 + (pivotX_prev_high - 2 * pivotX_prev_low)
r4calc = pivotX_Median * 3 + (pivotX_prev_high - 3 * pivotX_prev_low)
r5calc = pivotX_Median * 4 + (pivotX_prev_high - 4 * pivotX_prev_low)
// S1-5 Calculations
s1calc = pivotX_Median * 2 - pivotX_prev_high
s2calc = pivotX_Median - 1 * (pivotX_prev_high - pivotX_prev_low)
s3calc = pivotX_Median * 2 - (2 * pivotX_prev_high - pivotX_prev_low)
s4calc = pivotX_Median * 3 - (3 * pivotX_prev_high - pivotX_prev_low)
s5calc = pivotX_Median * 4 - (4 * pivotX_prev_high - pivotX_prev_low)
// EQ / Previous
array.push(p, pivotX_Median)
array.push(h, pivotX_prev_high)
array.push(l, pivotX_prev_low)
array.push(bc, pivot_BC)
array.push(tc, pivot_TC)
// R's
array.push(r1, r1calc)
array.push(r2, r2calc)
array.push(r3, r3calc)
array.push(r4, r4calc)
array.push(r5, r5calc)
// Minor R's
array.push(mr1, pivotX_Median + ( r1calc - pivotX_Median ) * .5 )
array.push(mr2, r1calc + ( (r2calc - r1calc) * .5 ) )
array.push(mr3, r2calc + ( (r3calc - r2calc) * .5 ) )
// S's
array.push(s1, s1calc)
array.push(s2, s2calc)
array.push(s3, s3calc)
array.push(s4, s4calc)
array.push(s5, s5calc)
// Minor S's
array.push(ms1, pivotX_Median - ( pivotX_Median - s1calc ) * .5 )
array.push(ms2, s1calc - ( (s1calc - s2calc) * .5 ) )
array.push(ms3, s2calc - ( (s2calc - s3calc) * .5 ) )
resolution = get_pivot_resolution()
SIMPLE_DIVISOR = -1
custom_years_divisor = switch pivot_time_frame
BIYEARLY => 2
TRIYEARLY => 3
QUINQUENNIALLY => 5
DECENNIALLY => 10
=> SIMPLE_DIVISOR
calc_high(prev, curr) =>
if na(prev) or na(curr)
nz(prev, nz(curr, na))
else
math.max(prev, curr)
calc_low(prev, curr) =>
if not na(prev) and not na(curr)
math.min(prev, curr)
else
nz(prev, nz(curr, na))
calc_OHLC_for_pivot(custom_years_divisor) =>
if custom_years_divisor == SIMPLE_DIVISOR
[open, high, low, close, open[1], high[1], low[1], close[1], time[1], time_close]
else
var prev_sec_open = float(na)
var prev_sec_high = float(na)
var prev_sec_low = float(na)
var prev_sec_close = float(na)
var prev_sec_time = int(na)
var curr_sec_open = float(na)
var curr_sec_high = float(na)
var curr_sec_low = float(na)
var curr_sec_close = float(na)
if year(time_close) % custom_years_divisor == 0
curr_sec_open := open
curr_sec_high := high
curr_sec_low := low
curr_sec_close := close
prev_sec_high := high[1]
prev_sec_low := low[1]
prev_sec_close := close[1]
prev_sec_time := time[1]
for i = 2 to custom_years_divisor
prev_sec_open := nz(open[i], prev_sec_open)
prev_sec_high := calc_high(prev_sec_high, high[i])
prev_sec_low := calc_low(prev_sec_low, low[i])
prev_sec_time := nz(time[i], prev_sec_time)
[curr_sec_open, curr_sec_high, curr_sec_low, curr_sec_close, prev_sec_open, prev_sec_high, prev_sec_low, prev_sec_close, prev_sec_time, time_close]
[sec_open, sec_high, sec_low, sec_close, prev_sec_open, prev_sec_high, prev_sec_low, prev_sec_close, prev_sec_time, sec_time] = request.security(syminfo.tickerid, resolution, calc_OHLC_for_pivot(custom_years_divisor), lookahead = barmerge.lookahead_on)
sec_open_gaps_on = request.security(syminfo.tickerid, resolution, open, gaps = barmerge.gaps_on, lookahead = barmerge.lookahead_on)
is_change_years = custom_years_divisor > 0 and ta.change(time(resolution)) and year(time_close) % custom_years_divisor == 0
var is_change = false
//var uses_current_bar = timeframe.isintraday and kind == WOODIE
var uses_current_bar = false
var change_time = int(na)
is_time_change = (ta.change(time(resolution)) and custom_years_divisor == SIMPLE_DIVISOR) or is_change_years
if is_time_change
change_time := time
var start_time = time
var was_last_premarket = false
var start_calculate_in_premarket = false
is_last_premarket = barstate.islast and session.ispremarket and time_close > sec_time and not was_last_premarket
if is_last_premarket
was_last_premarket := true
start_calculate_in_premarket := true
if session.ismarket
was_last_premarket := false
without_time_change = barstate.islast and array.size(arr_time) == 0
is_can_calc_pivot = (not uses_current_bar and is_time_change and session.ismarket) or (ta.change(sec_open) and not start_calculate_in_premarket) or is_last_premarket or (uses_current_bar and not na(sec_open_gaps_on)) or without_time_change
enough_bars_for_calculate = prev_sec_time >= start_time or is_daily_based
if is_can_calc_pivot and enough_bars_for_calculate
if array.size(arr_time) == 0 and is_daily_based
pivotX_prev_open := prev_sec_open[1]
pivotX_prev_high := prev_sec_high[1]
pivotX_prev_low := prev_sec_low[1]
pivotX_prev_close := prev_sec_close[1]
pivotX_open := sec_open[1]
pivotX_high := sec_high[1]
pivotX_low := sec_low[1]
array.push(arr_time, start_time)
traditional()
if is_daily_based
if is_last_premarket
pivotX_prev_open := sec_open
pivotX_prev_high := sec_high
pivotX_prev_low := sec_low
pivotX_prev_close := sec_close
pivotX_open := open
pivotX_high := high
pivotX_low := low
else
pivotX_prev_open := prev_sec_open
pivotX_prev_high := prev_sec_high
pivotX_prev_low := prev_sec_low
pivotX_prev_close := prev_sec_close
pivotX_open := sec_open
pivotX_high := sec_high
pivotX_low := sec_low
else
pivotX_prev_high := pivotX_high
pivotX_prev_low := pivotX_low
pivotX_prev_open := pivotX_open
pivotX_prev_close := close[1]
pivotX_open := open
pivotX_high := high
pivotX_low := low
if barstate.islast and not is_change and array.size(arr_time) > 0 and not without_time_change
array.set(arr_time, array.size(arr_time) - 1, change_time)
else if without_time_change
array.push(arr_time, start_time)
else
array.push(arr_time, nz(change_time, time))
// Start Traditional Pivots
traditional()
if array.size(arr_time) > look_back
if array.size(arr_time) > 0
array.shift(arr_time)
// EQ, Previous High/Low
if array.size(p) > 0 and p_show
array.shift(p)
// EQ Pivot High/Low
if array.size(bc) > 0 and bc_show
array.shift(bc)
if array.size(tc) > 0 and tc_show
array.shift(tc)
// Previous
if array.size(h) > 0 and h_show
array.shift(h)
if array.size(l) > 0 and l_show
array.shift(l)
// R's
if array.size(r1) > 0 and r1_show
array.shift(r1)
if array.size(mr1) > 0 and mr1_show
array.shift(mr1)
if array.size(r2) > 0 and r2_show
array.shift(r2)
if array.size(mr2) > 0 and mr2_show
array.shift(mr2)
if array.size(r3) > 0 and r3_show
array.shift(r3)
if array.size(mr3) > 0 and mr3_show
array.shift(mr3)
if array.size(r4) > 0 and r4_show
array.shift(r4)
if array.size(r5) > 0 and r5_show
array.shift(r5)
// S's
if array.size(s1) > 0 and s1_show
array.shift(s1)
if array.size(ms1) > 0 and ms1_show
array.shift(ms1)
if array.size(s2) > 0 and s2_show
array.shift(s2)
if array.size(ms2) > 0 and ms2_show
array.shift(ms2)
if array.size(s3) > 0 and s3_show
array.shift(s3)
if array.size(ms3) > 0 and ms3_show
array.shift(ms3)
if array.size(s4) > 0 and s4_show
array.shift(s4)
if array.size(s5) > 0 and s5_show
array.shift(s5)
is_change := true
else if not is_daily_based
pivotX_high := math.max(pivotX_high, high)
pivotX_low := math.min(pivotX_low, low)
if barstate.islast and not is_daily_based and array.size(arr_time) == 0
runtime.error("Not enough intraday data to calculate Pivot Points. Lower the Pivots Timeframe or turn on the 'Use Daily-based Values' option in the indicator settings.")
if barstate.islast and array.size(arr_time) > 0 and is_change
is_change := false
if custom_years_divisor > 0
last_pivot_time = array.get(arr_time, array.size(arr_time) - 1)
pivot_timeframe = str.tostring(12 * custom_years_divisor) + "M"
estimate_pivot_time = last_pivot_time + timeframe.in_seconds(pivot_timeframe) * 1000
array.push(arr_time, estimate_pivot_time)
else
array.push(arr_time, time_close(resolution))
for i = 0 to array.size(lines) - 1
if array.size(lines) > 0
line.delete(array.shift(lines))
if array.size(labels) > 0
label.delete(array.shift(labels))
// Draw out Pivot Lines
for i = 0 to array.size(arr_time) - 2
// EQ
if array.size(p) > 0 and p_show
draw_line(i, p, p_color, line.style_dashed)
draw_label(i, array.get(p, i), "EQ", p_color)
// EQ Range High & Low
if array.size(bc) > 0 and bc_show
draw_line(i, bc, bc_color, line.style_dotted)
draw_label(i, array.get(bc, i), "BC", bc_color)
if array.size(tc) > 0 and tc_show
draw_line(i, tc, tc_color, line.style_dotted)
draw_label(i, array.get(tc, i), "TC", tc_color)
// Prev High & Low
if array.size(h) > 0 and h_show
draw_line(i, h, h_color, line.style_dashed)
draw_label(i, array.get(h, i), "PHigh", h_color)
if array.size(l) > 0 and l_show
draw_line(i, l, l_color, line.style_dashed)
draw_label(i, array.get(l, i), "PLow", l_color)
// R's
if array.size(r1) > 0 and r1_show
draw_line(i, r1, r1_color)
draw_label(i, array.get(r1, i), "R1", r1_color)
if array.size(mr1) > 0 and mr1_show
draw_line(i, mr1, mr1_color)
draw_label(i, array.get(mr1, i), "mR1", mr1_color)
if array.size(r2) > 0 and r2_show
draw_line(i, r2, r2_color)
draw_label(i, array.get(r2, i), "R2", r2_color)
if array.size(mr2) > 0 and mr2_show
draw_line(i, mr2, mr2_color)
draw_label(i, array.get(mr2, i), "mR2", mr2_color)
if array.size(r3) > 0 and r3_show
draw_line(i, r3, r3_color)
draw_label(i, array.get(r3, i), "R3", r3_color)
if array.size(mr3) > 0 and mr3_show
draw_line(i, mr3, mr3_color)
draw_label(i, array.get(mr3, i), "mR3", mr3_color)
if array.size(r4) > 0 and r4_show
draw_line(i, r4, r4_color)
draw_label(i, array.get(r4, i), "R4", r4_color)
if array.size(r5) > 0 and r5_show
draw_line(i, r5, r5_color)
draw_label(i, array.get(r5, i), "R5", r5_color)
// S's
if array.size(s1) > 0 and s1_show
draw_line(i, s1, s1_color)
draw_label(i, array.get(s1, i), "S1", s1_color)
if array.size(ms1) > 0 and ms1_show
draw_line(i, ms1, ms1_color)
draw_label(i, array.get(ms1, i), "mS1", ms1_color)
if array.size(s2) > 0 and s2_show
draw_line(i, s2, s2_color)
draw_label(i, array.get(s2, i), "S2", s2_color)
if array.size(ms2) > 0 and ms2_show
draw_line(i, ms2, ms2_color)
draw_label(i, array.get(ms2, i), "mS2", ms2_color)
if array.size(s3) > 0 and s3_show
draw_line(i, s3, s3_color)
draw_label(i, array.get(s3, i), "S3", s3_color)
if array.size(ms3) > 0 and ms3_show
draw_line(i, ms3, ms3_color)
draw_label(i, array.get(ms3, i), "mS3", ms3_color)
if array.size(s4) > 0 and s4_show
draw_line(i, s4, s4_color)
draw_label(i, array.get(s4, i), "S4", s4_color)
if array.size(s5) > 0 and s5_show
draw_line(i, s5, s5_color)
draw_label(i, array.get(s5, i), "S5", s5_color)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment