// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © tamth_
//@version=6
indicator('SMC', overlay = true, max_boxes_count = 500, max_lines_count = 500, max_labels_count = 500, max_bars_back = 5000)
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
// Colors
color TRANSPARENT_COLOR = #ffffff00
color WHITE_COLOR = #dee2e6
color BLACK_COLOR = #000000
color RED_COLOR = #F72585
color ORANGE_COLOR = #fb5607
color YELLOW_COLOR = #ffbe0b
color GREEN_COLOR = #2a9d8f
color AQUA_COLOR = #4CC9F0
color BLUE_COLOR = #4361ee
color PURPLE_COLOR = #3F37C9
color PINK_COLOR = #B5179E
color LIGHT_GRAY_COLOR = #364156
color DARK_GRAY_COLOR = #212d40
color TEXT_COLOR = #ced4da
//-----------------------------------------------------------------------------
// Common Variables
//-----------------------------------------------------------------------------
series int barIdx = bar_index
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
type Helper
string name = 'Helper'
//-----------------------------------------------------------------------------
// Common Methods
//-----------------------------------------------------------------------------
debug(simple string txt) =>
var label lbl = label.new(barIdx, na, txt, xloc.bar_index, yloc.price, color(na), label.style_none, WHITE_COLOR, size.large, text.align_left)
label.set_xy(lbl, barIdx, ta.highest(10)[1])
label.set_text(lbl, txt)
method LineStyle(Helper helper, string style) =>
helper.name := style
out = switch style
'----' => line.style_dashed
'····' => line.style_dotted
=> line.style_solid
out
method DayOfWeek(Helper helper, int index) =>
helper.name := 'DOW'
switch
index == 1 => 'M'
index == 2 => 'T'
index == 3 => 'W'
index == 4 => 'T'
index == 5 => 'F'
index == 6 => 'S'
index == 7 => 'S'
na(index) => ''
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// HTF FVGs
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
type FVGSettings
string style
bool open_show
string open_style
int open_size
bool close_show
string close_style
int close_size
bool fill
int fill_percent
bool CE_show
string CE_style
int CE_size
color CE_bull_color
color CE_bear_color
bool link_show
string link_style
int link_size
int max_sets
bool mitigated_show
string mitigated_type
color mitigated_color_bull
color mitigated_color_bear
int mitigated_extend
bool ltf_hide
bool ctf_hide
bool label_show
bool label_open
bool label_close
bool label_ce
bool label_tf
bool label_type
bool label_level
color label_color
color label_bgcolor
string label_size
int extend
string extendby
int buffer
bool useProximity
int proximity
int labelfactor
float atrfactor
type FVGImbalanceSettings
bool show
string htf
color color_bull
color color_bear
color color_bull_ce
color color_bear_ce
int max_count
type FVGBox
line open
line close
line ce
line link
linefill fill
label label_open
label label_close
label label_ce
type FVGImbalance
int open_time
int close_time
float open
float middle
float close
bool mitigated
int mitigated_time
bool isbullish
FVGBox box2
type FVGImbalanceStructure
array<FVGImbalance> imbalance
FVGImbalanceSettings settings
int order = 1
int step = 0
//-----------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------
Fvg_Settings_HTF = 'FVG HTF'
Fvg_Settings_Display = 'FVG Display'
Fvg_Settings_Labels = 'FVG Labeling'
Fvg_Settings_Labels_Levels = 'FVG Label Levels To Display'
Fvg_Settings_Labels_Content = 'FVG Label Display Content'
Fvg_Settings_Advanced = 'FVG Advanced Settings'
FVGSettings fvg_settings = FVGSettings.new()
FVGImbalanceSettings HTF_1_Settings = FVGImbalanceSettings.new()
FVGImbalanceSettings HTF_2_Settings = FVGImbalanceSettings.new()
FVGImbalanceSettings HTF_3_Settings = FVGImbalanceSettings.new()
FVGImbalanceSettings HTF_4_Settings = FVGImbalanceSettings.new()
FVGImbalanceSettings HTF_5_Settings = FVGImbalanceSettings.new()
FVGImbalanceSettings HTF_6_Settings = FVGImbalanceSettings.new()
string fvg_tooltip1 = 'HTF FVG Settings:\n\tShow/Hide timeframe\n\tTimeframe to display\n\tBullish FVG Color\n\tBearish FVG Color\n\tMaximum number of FVGs to display'
string fvg_tooltip2 = 'Mitigated FVG Settings:\n\tShow/Hide mitigated (Applies to all).\n\tBullish FVG Color\n\tBearish FVG Color\n\tWhen to mark it as mitigated (Based on HTF timeframe, not current timeframe)'
HTF_1_Settings.show := input.bool(true, '', inline = 'htf1', group = Fvg_Settings_HTF)
htf_1 = input.timeframe('5', '', inline = 'htf1', group = Fvg_Settings_HTF)
HTF_1_Settings.htf := htf_1
HTF_1_Settings.color_bull := input.color(color.new(GREEN_COLOR, 25), '', inline = 'htf1', group = Fvg_Settings_HTF)
HTF_1_Settings.color_bear := input.color(color.new(RED_COLOR, 25), '', inline = 'htf1', group = Fvg_Settings_HTF)
HTF_1_Settings.max_count := input.int(20, '', inline = 'htf1', tooltip = fvg_tooltip1, group = Fvg_Settings_HTF)
HTF_2_Settings.show := input.bool(true, '', inline = 'htf2', group = Fvg_Settings_HTF)
htf_2 = input.timeframe('15', '', inline = 'htf2', group = Fvg_Settings_HTF)
HTF_2_Settings.htf := htf_2
HTF_2_Settings.color_bull := input.color(color.new(GREEN_COLOR, 25), '', inline = 'htf2', group = Fvg_Settings_HTF)
HTF_2_Settings.color_bear := input.color(color.new(RED_COLOR, 25), '', inline = 'htf2', group = Fvg_Settings_HTF)
HTF_2_Settings.max_count := input.int(20, '', inline = 'htf2', tooltip = fvg_tooltip1, group = Fvg_Settings_HTF)
HTF_3_Settings.show := input.bool(true, '', inline = 'htf3', group = Fvg_Settings_HTF)
htf_3 = input.timeframe('60', '', inline = 'htf3', group = Fvg_Settings_HTF)
HTF_3_Settings.htf := htf_3
HTF_3_Settings.color_bull := input.color(color.new(GREEN_COLOR, 25), '', inline = 'htf3', group = Fvg_Settings_HTF)
HTF_3_Settings.color_bear := input.color(color.new(RED_COLOR, 25), '', inline = 'htf3', group = Fvg_Settings_HTF)
HTF_3_Settings.max_count := input.int(20, '', inline = 'htf3', tooltip = fvg_tooltip1, group = Fvg_Settings_HTF)
HTF_4_Settings.show := input.bool(true, '', inline = 'htf4', group = Fvg_Settings_HTF)
htf_4 = input.timeframe('240', '', inline = 'htf4', group = Fvg_Settings_HTF)
HTF_4_Settings.htf := htf_4
HTF_4_Settings.color_bull := input.color(color.new(GREEN_COLOR, 25), '', inline = 'htf4', group = Fvg_Settings_HTF)
HTF_4_Settings.color_bear := input.color(color.new(RED_COLOR, 25), '', inline = 'htf4', group = Fvg_Settings_HTF)
HTF_4_Settings.max_count := input.int(10, '', inline = 'htf4', tooltip = fvg_tooltip1, group = Fvg_Settings_HTF)
HTF_5_Settings.show := input.bool(true, '', inline = 'htf5', group = Fvg_Settings_HTF)
htf_5 = input.timeframe('1D', '', inline = 'htf5', group = Fvg_Settings_HTF)
HTF_5_Settings.htf := htf_5
HTF_5_Settings.color_bull := input.color(color.new(GREEN_COLOR, 25), '', inline = 'htf5', group = Fvg_Settings_HTF)
HTF_5_Settings.color_bear := input.color(color.new(RED_COLOR, 25), '', inline = 'htf5', group = Fvg_Settings_HTF)
HTF_5_Settings.max_count := input.int(10, '', inline = 'htf5', tooltip = fvg_tooltip1, group = Fvg_Settings_HTF)
HTF_6_Settings.show := input.bool(true, '', inline = 'htf6', group = Fvg_Settings_HTF)
htf_6 = input.timeframe('1W', '', inline = 'htf6', group = Fvg_Settings_HTF)
HTF_6_Settings.htf := htf_6
HTF_6_Settings.color_bull := input.color(color.new(GREEN_COLOR, 25), '', inline = 'htf6', group = Fvg_Settings_HTF)
HTF_6_Settings.color_bear := input.color(color.new(RED_COLOR, 25), '', inline = 'htf6', group = Fvg_Settings_HTF)
HTF_6_Settings.max_count := input.int(2, '', inline = 'htf6', tooltip = fvg_tooltip1, group = Fvg_Settings_HTF)
fvg_settings.max_sets := input.int(6, 'Limit to next HTFs only', options = [1, 2, 3, 4, 5, 6])
fvg_settings.ltf_hide := input.bool(true, 'Hide Lower Timeframes')
fvg_settings.ctf_hide := input.bool(true, 'Hide Current Timeframe')
fvg_settings.fill := input.bool(false, 'Background Transparency', inline = 'fill')
fvg_settings.extendby := input.string('When in Range', 'Extend lines', options = ['Extension Only', 'Current Candle Plus Extension', 'When in Range'])
fvg_settings.extend := input.int(4, 'Distance from current candle', minval = 0)
fvg_settings.buffer := input.int(4, 'Spacing between timeframes', minval = 0)
fvg_settings.fill_percent := input.int(50, '', options = [98, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50], inline = 'fill')
fvg_settings.mitigated_show := input.bool(false, 'Mitigated', inline = '2')
fvg_settings.mitigated_color_bull := input.color(color.new(DARK_GRAY_COLOR, 60), '', inline = '2')
fvg_settings.mitigated_color_bear := input.color(color.new(DARK_GRAY_COLOR, 60), '', inline = '2')
fvg_settings.mitigated_type := input.string('Wick filled', 'when', options = ['None', 'Touched', 'Wick filled', 'Body filled', 'Wick filled half', 'Body filled half'], inline = '2', tooltip = fvg_tooltip2)
fvg_settings.mitigated_extend := input.int(5, 'Extend mitigated lines', minval = 0)
fvg_settings.open_show := input.bool(true, 'Open', group = Fvg_Settings_Display, inline = 'open')
fvg_settings.open_style := input.string('····', '', options = ['⎯⎯⎯', '----', '····'], group = Fvg_Settings_Display, inline = 'open')
fvg_settings.open_size := input.int(1, '', options = [1, 2, 3, 4], group = Fvg_Settings_Display, inline = 'open')
fvg_settings.close_show := input.bool(true, 'Close', group = Fvg_Settings_Display, inline = 'close')
fvg_settings.close_style := input.string('····', '', options = ['⎯⎯⎯', '----', '····'], group = Fvg_Settings_Display, inline = 'close')
fvg_settings.close_size := input.int(1, '', options = [1, 2, 3, 4], group = Fvg_Settings_Display, inline = 'close')
fvg_settings.CE_show := input.bool(true, 'C.E.', group = Fvg_Settings_Display, inline = '3')
fvg_settings.CE_bull_color := input.color(TRANSPARENT_COLOR, '', group = Fvg_Settings_Display, inline = '3')
fvg_settings.CE_bear_color := input.color(TRANSPARENT_COLOR, '', group = Fvg_Settings_Display, inline = '3')
fvg_settings.CE_style := input.string('····', '', options = ['⎯⎯⎯', '----', '····'], group = Fvg_Settings_Display, inline = '3')
fvg_settings.CE_size := input.int(1, '', options = [1, 2, 3, 4], group = Fvg_Settings_Display, inline = '3')
fvg_settings.link_show := input.bool(true, 'Link', group = Fvg_Settings_Display, inline = '4')
fvg_settings.link_style := input.string('⎯⎯⎯', '', options = ['⎯⎯⎯', '----', '····'], group = Fvg_Settings_Display, inline = '4')
fvg_settings.link_size := input.int(2, '', options = [1, 2, 3, 4], group = Fvg_Settings_Display, inline = '4')
fvg_settings.label_show := input.bool(true, 'Label', inline = 'label', group = Fvg_Settings_Labels)
fvg_settings.label_color := input.color(color.new(TEXT_COLOR, 50), '', group = Fvg_Settings_Labels, inline = 'label')
fvg_settings.label_bgcolor := input.color(TRANSPARENT_COLOR, '', group = Fvg_Settings_Labels, inline = 'label')
fvg_settings.label_size := input.string(size.small, '', [size.tiny, size.small, size.normal, size.large, size.huge], group = Fvg_Settings_Labels, inline = 'label')
fvg_settings.label_open := input.bool(false, 'Open', group = Fvg_Settings_Labels_Levels, inline = 'level')
fvg_settings.label_close := input.bool(false, 'Close', group = Fvg_Settings_Labels_Levels, inline = 'level')
fvg_settings.label_ce := input.bool(true, 'C.E.', group = Fvg_Settings_Labels_Levels, inline = 'level')
fvg_settings.label_tf := input.bool(true, 'Timeframe', group = Fvg_Settings_Labels_Content, inline = 'level2')
fvg_settings.label_type := input.bool(false, 'BISI / SIBI', group = Fvg_Settings_Labels_Content, inline = 'level3')
fvg_settings.label_level := input.bool(false, 'Open / Close / C.E.', group = Fvg_Settings_Labels_Content, inline = 'level4')
fvg_settings.useProximity := input.bool(true, 'Use Proximity to show to show/hide FVGs', group = Fvg_Settings_Advanced)
fvg_settings.proximity := 11 - input.int(9, 'Proximity factor based on daily range', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], group = Fvg_Settings_Advanced)
fvg_settings.labelfactor := input.int(10, 'Combine labels factor for visibility', options = [20, 15, 10, 6, 5, 4, 3], group = Fvg_Settings_Advanced) / 10
fvg_settings.atrfactor := input.int(10, 'Range should be within X candles', minval = 1, group = Fvg_Settings_Advanced)
//-----------------------------------------------------------------------------
// Variables
//-----------------------------------------------------------------------------
Helper fvg_helper = Helper.new()
var FVGImbalanceStructure FVG_1 = FVGImbalanceStructure.new()
var FVGImbalanceStructure FVG_2 = FVGImbalanceStructure.new()
var FVGImbalanceStructure FVG_3 = FVGImbalanceStructure.new()
var FVGImbalanceStructure FVG_4 = FVGImbalanceStructure.new()
var FVGImbalanceStructure FVG_5 = FVGImbalanceStructure.new()
var FVGImbalanceStructure FVG_6 = FVGImbalanceStructure.new()
var array<FVGImbalance> FVGs_1 = array.new<FVGImbalance>()
var array<FVGImbalance> FVGs_2 = array.new<FVGImbalance>()
var array<FVGImbalance> FVGs_3 = array.new<FVGImbalance>()
var array<FVGImbalance> FVGs_4 = array.new<FVGImbalance>()
var array<FVGImbalance> FVGs_5 = array.new<FVGImbalance>()
var array<FVGImbalance> FVGs_6 = array.new<FVGImbalance>()
FVG_1.imbalance := FVGs_1
FVG_1.settings := HTF_1_Settings
FVG_2.imbalance := FVGs_2
FVG_2.settings := HTF_2_Settings
FVG_3.imbalance := FVGs_3
FVG_3.settings := HTF_3_Settings
FVG_4.imbalance := FVGs_4
FVG_4.settings := HTF_4_Settings
FVG_5.imbalance := FVGs_5
FVG_5.settings := HTF_5_Settings
FVG_6.imbalance := FVGs_6
FVG_6.settings := HTF_6_Settings
//Used internally for padding
var int TF_1 = 0
var int TF_2 = 0
var int TF_3 = 0
var int TF_4 = 0
var int TF_5 = 0
var int TF_6 = 0
var float fvg_daily = 0
var float fvg_monthly = 0
int fvg_cspacer = time - time[1]
var array<float> fvg_median = array.new_float()
fvg_length = 500
fvg_median.unshift(high - low)
if fvg_median.size() > fvg_length
fvg_median.pop()
float fvg_spacing = ta.sma(ta.sma(fvg_median.median(), fvg_length), fvg_length) * fvg_settings.labelfactor
//-----------------------------------------------------------------------------
// Methods
//-----------------------------------------------------------------------------
method FVGText(Helper helper, string htf, string direction, string level, bool truncate) =>
helper.name := htf
string formatted = ''
if fvg_settings.label_tf
seconds = timeframe.in_seconds(htf)
if seconds < 60
formatted := str.tostring(seconds) + 's'
formatted
else if seconds / 60 < 60
formatted := str.tostring(seconds / 60) + 'm'
formatted
else if seconds / 60 / 60 < 24
formatted := str.tostring(seconds / 60 / 60) + 'H'
formatted
else
formatted := htf
formatted
if not truncate
if fvg_settings.label_type
if formatted != '' and direction != ''
formatted := formatted + ' '
formatted
formatted := formatted + direction
formatted
if fvg_settings.label_level
if formatted != '' and level != ''
formatted := formatted + ' '
formatted
formatted := formatted + level
formatted
formatted
method FVGValidTimeframe(Helper helper, tf) =>
bool valid = true
helper.name := tf
n1 = timeframe.in_seconds()
n2 = timeframe.in_seconds(tf)
if fvg_settings.ltf_hide and n1 > n2
valid := false
valid
if fvg_settings.ctf_hide and n1 == n2
valid := false
valid
valid
method FVGProximityRange(Helper helper, tf) =>
helper.name := tf
float range_high = 0
float range_low = 0
if timeframe.isseconds or timeframe.isminutes
range_high := close + fvg_daily / fvg_settings.proximity
range_low := close - fvg_daily / fvg_settings.proximity
range_low
if timeframe.isdaily
range_high := close + fvg_monthly * 3
range_low := close - fvg_monthly * 3
range_low
if timeframe.isweekly
range_high := close + fvg_monthly * 12
range_low := close - fvg_monthly * 12
range_low
[range_low, range_high]
method FVGHTFEnabled(Helper helper) =>
helper.name := 'HTFEnabled'
int enabled = 0
enabled := enabled + (FVG_1.settings.show and helper.FVGValidTimeframe(FVG_1.settings.htf) ? 1 : 0)
enabled := enabled + (FVG_2.settings.show and helper.FVGValidTimeframe(FVG_2.settings.htf) ? 1 : 0)
enabled := enabled + (FVG_3.settings.show and helper.FVGValidTimeframe(FVG_3.settings.htf) ? 1 : 0)
enabled := enabled + (FVG_4.settings.show and helper.FVGValidTimeframe(FVG_4.settings.htf) ? 1 : 0)
enabled := enabled + (FVG_5.settings.show and helper.FVGValidTimeframe(FVG_5.settings.htf) ? 1 : 0)
enabled := enabled + (FVG_6.settings.show and helper.FVGValidTimeframe(FVG_6.settings.htf) ? 1 : 0)
math.min(enabled, fvg_settings.max_sets)
fvgFindLow(float price, int start, int default, bool inverse) =>
int inc = time - time[1]
int loc = default
int x = inverse ? 0 : (time - start) / inc
int y = inverse ? (time - start) / inc : 0
if x < 10000 and y < 10000
for i = x to y by 1
if low[i] == price
loc := time[i]
break
loc
fvgFindHigh(float price, int start, int default, bool inverse) =>
int inc = time - time[1]
int loc = default
int x = inverse ? 0 : (time - start) / inc
int y = inverse ? (time - start) / inc : 0
if x < 10000 and y < 10000
for i = x to y by 1
if high[i] == price
loc := time[i]
break
loc
fvgVisibleHTFs() =>
int step = 1
FVG_1.step := 1
for t in FVG_1.imbalance
if not na(t.box2)
FVG_1.step := step
step := step + 1
break
FVG_2.step := 1
for t in FVG_2.imbalance
if not na(t.box2)
FVG_2.step := step
step := step + 1
break
FVG_3.step := 1
for t in FVG_3.imbalance
if not na(t.box2)
FVG_3.step := step
step := step + 1
break
FVG_4.step := 1
for t in FVG_4.imbalance
if not na(t.box2)
FVG_4.step := step
step := step + 1
break
FVG_5.step := 1
for t in FVG_5.imbalance
if not na(t.box2)
FVG_5.step := step
step := step + 1
break
FVG_6.step := 1
for t in FVG_6.imbalance
if not na(t.box2)
FVG_6.step := step
step := step + 1
break
//-----------------------------------------------------------------------------
// Imbalance Methods
//-----------------------------------------------------------------------------
method FVGClear(FVGImbalance imb) =>
if not na(imb.box2)
line.delete(imb.box2.open)
line.delete(imb.box2.close)
line.delete(imb.box2.ce)
line.delete(imb.box2.link)
linefill.delete(imb.box2.fill)
label.delete(imb.box2.label_open)
label.delete(imb.box2.label_close)
label.delete(imb.box2.label_ce)
imb.box2 := na
imb.box2
// AddZone is used to display and manage imbalance related boxes
method FVGAddZone(FVGImbalanceStructure IS, FVGImbalance imb, int step) =>
bool visible = true
if IS.settings.show
int buffer = time + (time - time[1]) * (fvg_settings.extend + 1 + fvg_settings.buffer * (step - 1))
if imb.mitigated and not fvg_settings.mitigated_show
if not na(imb.box2)
visible := false
visible
imb.FVGClear()
if na(imb.box2)
color c = imb.isbullish ? IS.settings.color_bull : IS.settings.color_bear
color cce = imb.isbullish ? fvg_settings.CE_bull_color : fvg_settings.CE_bear_color
imb.box2 := FVGBox.new()
imb.box2.open := line.new(imb.open_time, imb.open, buffer, imb.open, xloc = xloc.bar_time, style = fvg_helper.LineStyle(fvg_settings.open_style), color = fvg_settings.open_show ? c : TRANSPARENT_COLOR, width = fvg_settings.open_size)
imb.box2.close := line.new(imb.close_time, imb.close, buffer, imb.close, xloc = xloc.bar_time, style = fvg_helper.LineStyle(fvg_settings.close_style), color = fvg_settings.close_show ? c : TRANSPARENT_COLOR, width = fvg_settings.close_size)
if fvg_settings.link_show
imb.box2.link := line.new(buffer, imb.open, buffer, imb.close, xloc = xloc.bar_time, style = fvg_helper.LineStyle(fvg_settings.link_style), color = c, width = fvg_settings.link_size)
imb.box2.link
if fvg_settings.fill
imb.box2.fill := linefill.new(imb.box2.open, imb.box2.close, color.new(c, fvg_settings.fill_percent))
imb.box2.fill
if fvg_settings.CE_show
imb.box2.ce := line.new((imb.open_time + imb.close_time) / 2, imb.middle, buffer, imb.middle, xloc = xloc.bar_time, style = fvg_helper.LineStyle(fvg_settings.CE_style), color = cce, width = fvg_settings.CE_size)
imb.box2.ce
if fvg_settings.label_show
if math.abs(imb.open - imb.close) >= fvg_spacing
if fvg_settings.open_show or fvg_settings.fill
if fvg_settings.label_open
imb.box2.label_open := label.new(buffer, imb.open, text = fvg_helper.FVGText(IS.settings.htf, imb.isbullish ? 'BISI' : 'SIBI', 'Open', false), xloc = xloc.bar_time, textcolor = fvg_settings.label_color, style = label.style_label_left, color = fvg_settings.label_bgcolor, size = fvg_settings.label_size)
imb.box2.label_open
if fvg_settings.close_show or fvg_settings.fill
if fvg_settings.label_close
imb.box2.label_close := label.new(buffer, imb.close, text = fvg_helper.FVGText(IS.settings.htf, imb.isbullish ? 'BISI' : 'SIBI', 'Close', false), xloc = xloc.bar_time, textcolor = fvg_settings.label_color, style = label.style_label_left, color = fvg_settings.label_bgcolor, size = fvg_settings.label_size)
imb.box2.label_close
if fvg_settings.CE_show and fvg_settings.label_ce
imb.box2.label_ce := label.new(buffer, imb.middle, text = fvg_helper.FVGText(IS.settings.htf, imb.isbullish ? 'BISI' : 'SIBI', 'ce', false), xloc = xloc.bar_time, textcolor = fvg_settings.label_color, style = label.style_label_left, color = fvg_settings.label_bgcolor, size = fvg_settings.label_size)
imb.box2.label_ce
else
if fvg_settings.CE_show
imb.box2.label_ce := label.new(buffer, imb.middle, text = fvg_helper.FVGText(IS.settings.htf, imb.isbullish ? 'BISI' : 'SIBI', '', false), xloc = xloc.bar_time, textcolor = fvg_settings.label_color, style = label.style_label_left, color = fvg_settings.label_bgcolor, size = fvg_settings.label_size)
imb.box2.label_ce
visible
method FVGUpdateZone(FVGImbalanceStructure IS) =>
if barstate.islast
fvgVisibleHTFs()
int level = IS.step
for imb in IS.imbalance
if not na(imb.box2)
int buffer = 0
if imb.mitigated
buffer := imb.close_time + fvg_cspacer * fvg_settings.mitigated_extend
line.set_color(imb.box2.open, imb.isbullish ? fvg_settings.mitigated_color_bull : fvg_settings.mitigated_color_bear)
line.set_color(imb.box2.close, imb.isbullish ? fvg_settings.mitigated_color_bull : fvg_settings.mitigated_color_bear)
line.set_color(imb.box2.ce, imb.isbullish ? fvg_settings.mitigated_color_bull : fvg_settings.mitigated_color_bear)
line.set_color(imb.box2.link, imb.isbullish ? fvg_settings.mitigated_color_bull : fvg_settings.mitigated_color_bear)
linefill.set_color(imb.box2.fill, color.new(imb.isbullish ? fvg_settings.mitigated_color_bull : fvg_settings.mitigated_color_bear, fvg_settings.fill_percent))
else
if fvg_settings.extendby == 'Extension Only'
buffer := (imb.close_time < chart.left_visible_bar_time ? chart.left_visible_bar_time : imb.close_time) + fvg_cspacer * (fvg_settings.extend + 1)
buffer
else
if fvg_settings.extendby == 'When in Range'
float atrlength = ta.atr(14) * fvg_settings.atrfactor
if math.max(imb.open, imb.close) > close - atrlength and math.min(imb.open, imb.close) < close + atrlength
buffer := time + fvg_cspacer * (fvg_settings.extend + 1 + (level - 1) * fvg_settings.buffer)
buffer
else
buffer := imb.close_time + fvg_cspacer * (fvg_settings.extend + 1)
buffer
else
buffer := time + fvg_cspacer * (fvg_settings.extend + 1 + (level - 1) * fvg_settings.buffer)
buffer
line.set_x2(imb.box2.open, buffer)
line.set_x2(imb.box2.close, buffer)
line.set_x1(imb.box2.link, buffer)
line.set_x2(imb.box2.link, buffer)
if fvg_settings.label_show
label.set_x(imb.box2.label_open, buffer)
label.set_x(imb.box2.label_close, buffer)
label.set_x(imb.box2.label_ce, buffer)
if fvg_settings.CE_show
line.set_x2(imb.box2.ce, buffer)
if imb.mitigated
if na(imb.box2.label_ce)
imb.box2.label_ce := label.new(buffer, imb.middle, text = fvg_helper.FVGText(IS.settings.htf, '', '', true), xloc = xloc.bar_time, textcolor = fvg_settings.label_color, style = label.style_label_left, color = fvg_settings.label_bgcolor, size = fvg_settings.label_size)
imb.box2.label_ce
else
label.set_text(imb.box2.label_ce, fvg_helper.FVGText(IS.settings.htf, '', '', true))
label.delete(imb.box2.label_open)
label.delete(imb.box2.label_close)
// AddImbalance adds a newly discovered imbalance. this applies for both FVG and Volume Imbalance
method FVGAddImbalance(FVGImbalanceStructure IS, float o, float c, int o_time, int c_time) =>
FVGImbalance imb = FVGImbalance.new()
imb.open_time := o < c ? fvgFindHigh(o, o_time, o_time, false) : fvgFindLow(o, o_time, o_time, false) // o_time
imb.close_time := o < c ? fvgFindLow(c, o_time, c_time, true) : fvgFindHigh(c, o_time, c_time, true) // c_time
imb.open := o
imb.middle := (o + c) / 2
imb.close := c
imb.isbullish := o < c
IS.imbalance.unshift(imb)
if IS.imbalance.size() > IS.settings.max_count
temp = IS.imbalance.pop()
temp.FVGClear()
IS
// CheckMitigated checks if the imbalance has been mitigated based on the settings
method FVGCheckMitigated(FVGImbalanceStructure IS, o, h, l, c, bool isHTF) =>
if IS.imbalance.size() > 0
for i = IS.imbalance.size() - 1 to 0 by 1
imb = IS.imbalance.get(i)
if not imb.mitigated
switch fvg_settings.mitigated_type
'None' =>
imb.mitigated := false
imb.mitigated
'Touched' =>
imb.mitigated := (imb.open <= imb.close ? low < imb.close : high > imb.close)
imb.mitigated
'Wick filled' =>
imb.mitigated := (imb.open <= imb.close ? low <= imb.open : high >= imb.open)
imb.mitigated
'Body filled' =>
imb.mitigated := isHTF and (imb.open < imb.close ? math.min(o, c) <= imb.open : math.max(o, c) >= imb.open)
imb.mitigated
'Wick filled half' =>
imb.mitigated := imb.open <= imb.close ? low <= imb.middle : high >= imb.middle
imb.mitigated
'Body filled half' =>
imb.mitigated := isHTF and (imb.open <= imb.close ? math.min(o, c) <= imb.middle : math.max(o, c) >= imb.middle)
imb.mitigated
if imb.mitigated
if not fvg_settings.mitigated_show
imb.FVGClear()
IS.imbalance.remove(i)
else
imb.mitigated_time := time
imb.mitigated_time
IS.FVGUpdateZone()
IS
method FVGProximityTest(FVGImbalanceStructure IS) =>
if IS.imbalance.size() > 0
[rl, rh] = fvg_helper.FVGProximityRange(IS.settings.htf)
for i = 0 to IS.imbalance.size() - 1 by 1
imb = IS.imbalance.get(i)
if (math.max(imb.open, imb.close) > rl and math.min(imb.open, imb.close) < rh) or not fvg_settings.useProximity
IS.FVGAddZone(imb, IS.order)
else
imb.FVGClear()
IS
// FindImbalance looks for imbalances and, if found, adds it to the list
method FVGFindImbalance(FVGImbalanceStructure IS, o, h, l, c, t, o1, h1, l1, c1, t1, o2, h2, l2, c2, t2) =>
if IS.settings.show
if h < l2
IS.FVGAddImbalance(l2, h, t2, t)
if l > h2
IS.FVGAddImbalance(h2, l, t2, t)
IS
method FVGProcess(FVGImbalanceStructure IS, float o, float h, float l, float c, int t, float o1, float h1, float l1, float c1, int t1, float o2, float h2, float l2, float c2, int t2) =>
bool show = false
if IS.settings.show
if fvg_helper.FVGValidTimeframe(IS.settings.htf)
IS.FVGFindImbalance(o, h, l, c, t, o1, h1, l1, c1, t1, o2, h2, l2, c2, t2)
fvgGetHTF(string htf, int i) =>
[open[i], high[i], low[i], close[i], time[i]]
method fvgCheck(FVGImbalanceStructure IS, string htf) =>
bool newCandle = bool(ta.change(time(htf, "america/New_York")))
if newCandle
int inc = 1 //barstate.isrealtime ? 1 : 0
[o, h, l, c, t] = request.security(syminfo.tickerid, htf, fvgGetHTF(htf, inc), lookahead = barmerge.lookahead_on)
[o1, h1, l1, c1, t1] = request.security(syminfo.tickerid, htf, fvgGetHTF(htf, inc+1), lookahead = barmerge.lookahead_on)
[o2, h2, l2, c2, t2] = request.security(syminfo.tickerid, htf, fvgGetHTF(htf, inc+2), lookahead = barmerge.lookahead_on)
if not na(o)
IS.FVGProcess(o, h, l, c, t, o1, h1, l1, c1, t1, o2, h2, l2, c2, t2)
IS.FVGProximityTest()
IS.FVGCheckMitigated(o, h, l, c, bool(ta.change(time(htf, "america/New_York"))))
IS.FVGCheckMitigated(open, high, low, close, newCandle)
IS.FVGUpdateZone()
//-----------------------------------------------------------------------------
// Calculate & Render
//-----------------------------------------------------------------------------
// daily and monthly are used for proximity test on higher timeframes
fvg_daily := request.security(syminfo.tickerid, '1D', ta.atr(14))
fvg_monthly := request.security(syminfo.tickerid, '1M', ta.atr(14))
int fvg_cnt = 0
int fvg_last = fvg_helper.FVGHTFEnabled()
if true// barstate.isconfirmed
if FVG_1.settings.show
if fvg_helper.FVGValidTimeframe(htf_1)
fvg_cnt := fvg_cnt + 1
FVG_1.order := fvg_cnt
FVG_1.fvgCheck(htf_1)
if FVG_2.settings.show
if fvg_helper.FVGValidTimeframe(htf_2)
if fvg_cnt < fvg_last
fvg_cnt := fvg_cnt + 1
FVG_2.order := fvg_cnt
FVG_2.fvgCheck(htf_2)
if FVG_3.settings.show
if fvg_helper.FVGValidTimeframe(htf_3)
if fvg_cnt < fvg_last
fvg_cnt := fvg_cnt + 1
FVG_3.order := fvg_cnt
FVG_3.fvgCheck(htf_3)
if FVG_4.settings.show
if fvg_helper.FVGValidTimeframe(htf_4)
if fvg_cnt < fvg_last
fvg_cnt := fvg_cnt + 1
FVG_4.order := fvg_cnt
FVG_4.fvgCheck(htf_4)
if FVG_5.settings.show
if fvg_helper.FVGValidTimeframe(htf_5)
if fvg_cnt < fvg_last
fvg_cnt := fvg_cnt + 1
FVG_5.order := fvg_cnt
FVG_5.fvgCheck(htf_5)
if FVG_6.settings.show
if fvg_helper.FVGValidTimeframe(htf_6)
if fvg_cnt < fvg_last
fvg_cnt := fvg_cnt + 1
FVG_6.order := fvg_cnt
FVG_6.fvgCheck(htf_6)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// HTF Candles
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
type Candle
float o
float c
float h
float l
int o_time
int o_idx
int c_idx
int h_idx
int l_idx
string dow
box body
line wick_up
line wick_down
label dow_label
type CandeTrace
line o
line c
line h
line l
label o_l
label c_l
label h_l
label l_l
type CandeImbalance
box b
int idx
type CandeSettingsHTF
bool show
string htf
int max_display
type CandleSettings
int max_sets
color bull_body
color bull_border
color bull_wick
color bear_body
color bear_border
color bear_wick
int offset
int buffer
int htf_buffer
int width
bool use_custom_daily
string custom_daily
bool daily_name
bool trace_show
color trace_o_color
string trace_o_style
int trace_o_size
color trace_c_color
string trace_c_style
int trace_c_size
color trace_h_color
string trace_h_style
int trace_h_size
color trace_l_color
string trace_l_style
int trace_l_size
string trace_anchor
bool label_show
color label_color
string label_size
string label_position
string label_alignment
bool fvg_show
color fvg_color
bool vi_show
color vi_color
bool htf_label_show
color htf_label_color
string htf_label_size
bool htf_timer_show
color htf_timer_color
string htf_timer_size
color dow_color
string dow_size
type CandleSet
array<Candle> candles
array<CandeImbalance> imbalances
CandeSettingsHTF settings
label tfNameTop
label tfNameBottom
label tfTimerTop
label tfTimerBottom
CandleSettings candle_settings = CandleSettings.new()
var CandeSettingsHTF CandleSettingsHTF1 = CandeSettingsHTF.new()
var CandeSettingsHTF CandleSettingsHTF2 = CandeSettingsHTF.new()
var CandeSettingsHTF CandleSettingsHTF3 = CandeSettingsHTF.new()
var CandeSettingsHTF CandleSettingsHTF4 = CandeSettingsHTF.new()
var CandeSettingsHTF CandleSettingsHTF5 = CandeSettingsHTF.new()
var CandeSettingsHTF CandleSettingsHTF6 = CandeSettingsHTF.new()
var array<Candle> candles_1 = array.new<Candle>(0)
var array<Candle> candles_2 = array.new<Candle>(0)
var array<Candle> candles_3 = array.new<Candle>(0)
var array<Candle> candles_4 = array.new<Candle>(0)
var array<Candle> candles_5 = array.new<Candle>(0)
var array<Candle> candles_6 = array.new<Candle>(0)
var array<CandeImbalance> candles_imbalances_1 = array.new<CandeImbalance>()
var array<CandeImbalance> candles_imbalances_2 = array.new<CandeImbalance>()
var array<CandeImbalance> candles_imbalances_3 = array.new<CandeImbalance>()
var array<CandeImbalance> candles_imbalances_4 = array.new<CandeImbalance>()
var array<CandeImbalance> candles_imbalances_5 = array.new<CandeImbalance>()
var array<CandeImbalance> candles_imbalances_6 = array.new<CandeImbalance>()
var CandleSet candle_htf1 = CandleSet.new()
candle_htf1.settings := CandleSettingsHTF1
candle_htf1.candles := candles_1
candle_htf1.imbalances := candles_imbalances_1
var CandleSet candle_htf2 = CandleSet.new()
candle_htf2.settings := CandleSettingsHTF2
candle_htf2.candles := candles_2
candle_htf2.imbalances := candles_imbalances_2
var CandleSet candle_htf3 = CandleSet.new()
candle_htf3.settings := CandleSettingsHTF3
candle_htf3.candles := candles_3
candle_htf3.imbalances := candles_imbalances_3
var CandleSet candle_htf4 = CandleSet.new()
candle_htf4.settings := CandleSettingsHTF4
candle_htf4.candles := candles_4
candle_htf4.imbalances := candles_imbalances_4
var CandleSet candle_htf5 = CandleSet.new()
candle_htf5.settings := CandleSettingsHTF5
candle_htf5.candles := candles_5
candle_htf5.imbalances := candles_imbalances_5
var CandleSet candle_htf6 = CandleSet.new()
candle_htf6.settings := CandleSettingsHTF6
candle_htf6.candles := candles_6
candle_htf6.imbalances := candles_imbalances_6
//-----------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------
string group_htf_candles = "HTF Candles ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
string group_style = "Styling ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
string group_label = "Label ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
string group_imbalance = "Imbalance ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
string group_trace = "Trace ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
candle_htf1.settings.show := input.bool(false, 'HTF 1', inline = 'htf1', group = group_htf_candles)
cancle_htf_1_input = input.timeframe('5', '', inline = 'htf1', group = group_htf_candles)
candle_htf1.settings.htf := cancle_htf_1_input
candle_htf1.settings.max_display := input.int(10, '', inline = 'htf1', group = group_htf_candles)
candle_htf2.settings.show := input.bool(false, 'HTF 2', inline = 'htf2', group = group_htf_candles)
cancle_htf_2_input = input.timeframe('15', '', inline = 'htf2', group = group_htf_candles)
candle_htf2.settings.htf := cancle_htf_2_input
candle_htf2.settings.max_display := input.int(10, '', inline = 'htf2', group = group_htf_candles)
candle_htf3.settings.show := input.bool(true, 'HTF 3', inline = 'htf3', group = group_htf_candles)
cancle_htf_3_input = input.timeframe('60', '', inline = 'htf3', group = group_htf_candles)
candle_htf3.settings.htf := cancle_htf_3_input
candle_htf3.settings.max_display := input.int(10, '', inline = 'htf3', group = group_htf_candles)
candle_htf4.settings.show := input.bool(true, 'HTF 4', inline = 'htf4', group = group_htf_candles)
cancle_htf_4_input = input.timeframe('240', '', inline = 'htf4', group = group_htf_candles)
candle_htf4.settings.htf := cancle_htf_4_input
candle_htf4.settings.max_display := input.int(10, '', inline = 'htf4', group = group_htf_candles)
candle_htf5.settings.show := input.bool(true, 'HTF 5', inline = 'htf5', group = group_htf_candles)
cancle_htf_5_input = input.timeframe('1D', '', inline = 'htf5', group = group_htf_candles)
candle_htf5.settings.htf := cancle_htf_5_input
candle_htf5.settings.max_display := input.int(10, '', inline = 'htf5', group = group_htf_candles)
candle_htf6.settings.show := input.bool(true, 'HTF 6', inline = 'htf6', group = group_htf_candles)
cancle_htf_6_input = input.timeframe('1W', '', inline = 'htf6', group = group_htf_candles)
candle_htf6.settings.htf := cancle_htf_6_input
candle_htf6.settings.max_display := input.int(10, '', inline = 'htf6', group = group_htf_candles)
candle_settings.max_sets := input.int(6, 'Limit to next HTFs only', minval = 1, maxval = 6)
candle_settings.use_custom_daily := input.bool(false, 'Custom daily candle open', inline='customdaily')
candle_settings.custom_daily := input.string('Midnight', '', options=['Midnight', '8:30', '9:30'], inline='customdaily')
candle_settings.bull_body := input.color(WHITE_COLOR, 'Body', inline = 'body', group = group_style)
candle_settings.bear_body := input.color(BLUE_COLOR, '', inline = 'body', group = group_style)
candle_settings.bull_border := input.color(WHITE_COLOR, 'Borders', inline = 'borders', group = group_style)
candle_settings.bear_border := input.color(BLUE_COLOR, '', inline = 'borders', group = group_style)
candle_settings.bull_wick := input.color(LIGHT_GRAY_COLOR, 'Wick', inline = 'wick', group = group_style)
candle_settings.bear_wick := input.color(LIGHT_GRAY_COLOR, '', inline = 'wick', group = group_style)
candle_settings.offset := input.int(30, 'padding from current candles', minval = 1, group = group_style)
candle_settings.buffer := input.int(1, 'space between candles', minval = 1, maxval = 4, group = group_style)
candle_settings.htf_buffer := input.int(10, 'space between Higher Timeframes', minval = 1, maxval = 10, group = group_style)
candle_settings.width := input.int(1, 'Candle Width', minval = 1, maxval = 4, group = group_style) * 2
candle_settings.htf_label_show := input.bool(true, 'HTF Label', group = group_label, inline = 'HTFlabel')
candle_settings.htf_label_color := input.color(LIGHT_GRAY_COLOR, '', group = group_label, inline = 'HTFlabel')
candle_settings.htf_label_size := input.string(size.large, '', [size.tiny, size.small, size.normal, size.large, size.huge], group = group_label, inline = 'HTFlabel')
candle_settings.label_position := input.string("Top", 'Label Positions', options=['Both', 'Top', 'Bottom'], group = group_label)
candle_settings.label_alignment := input.string("Align", "Label Alignment", options=['Align', 'Follow Candles'], group = group_label)
candle_settings.htf_timer_show := input.bool(true, 'Remaining time', inline = 'timer', group = group_label)
candle_settings.htf_timer_color := input.color(LIGHT_GRAY_COLOR, '', inline = 'timer', group = group_label)
candle_settings.htf_timer_size := input.string(size.normal, '', [size.tiny, size.small, size.normal, size.large, size.huge], group = group_label, inline = 'timer')
candle_settings.daily_name := input.bool(false, 'Interval Value', group = group_label, inline = 'dow')
candle_settings.dow_color := input.color(LIGHT_GRAY_COLOR , '', group = group_label, inline = 'dow')
candle_settings.dow_size := input.string(size.small, '', [size.tiny, size.small, size.normal, size.large, size.huge], group = group_label, inline = 'dow')
candle_settings.fvg_show := input.bool(true, 'Fair Value Gap', group = group_imbalance, inline = 'fvg')
candle_settings.fvg_color := input.color(color.new(DARK_GRAY_COLOR, 60), '', inline = 'fvg', group = group_imbalance)
candle_settings.vi_show := input.bool(false, 'Volume Imbalance', group = group_imbalance, inline = 'vi')
candle_settings.vi_color := input.color(color.new(PINK_COLOR, 80), '', inline = 'vi', group = group_imbalance)
candle_settings.trace_show := input.bool(false, 'Trace lines', group = group_trace)
candle_settings.trace_o_color := input.color(DARK_GRAY_COLOR, 'Open', inline = '1', group = group_trace)
candle_settings.trace_o_style := input.string('····', '', options = ['⎯⎯⎯', '----', '····'], inline = '1', group = group_trace)
candle_settings.trace_o_size := input.int(1, '', options = [1, 2, 3, 4], inline = '1', group = group_trace)
candle_settings.trace_c_color := input.color(DARK_GRAY_COLOR, 'Close', inline = '2', group = group_trace)
candle_settings.trace_c_style := input.string('····', '', options = ['⎯⎯⎯', '----', '····'], inline = '2', group = group_trace)
candle_settings.trace_c_size := input.int(1, '', options = [1, 2, 3, 4], inline = '2', group = group_trace)
candle_settings.trace_h_color := input.color(DARK_GRAY_COLOR, 'High', inline = '3', group = group_trace)
candle_settings.trace_h_style := input.string('····', '', options = ['⎯⎯⎯', '----', '····'], inline = '3', group = group_trace)
candle_settings.trace_h_size := input.int(1, '', options = [1, 2, 3, 4], inline = '3', group = group_trace)
candle_settings.trace_l_color := input.color(DARK_GRAY_COLOR, 'Low', inline = '4', group = group_trace)
candle_settings.trace_l_style := input.string('····', '', options = ['⎯⎯⎯', '----', '····'], inline = '4', group = group_trace)
candle_settings.trace_l_size := input.int(1, '', options = [1, 2, 3, 4], inline = '4', group = group_trace)
candle_settings.trace_anchor := input.string('First Timeframe', 'Anchor to', options = ['First Timeframe', 'Last Timeframe'], group = group_trace)
candle_settings.label_show := input.bool(false, 'Price Label', inline = 'label')
candle_settings.label_color := input.color(color.new(TEXT_COLOR, 10), '', inline = 'label')
candle_settings.label_size := input.string(size.small, '', [size.tiny, size.small, size.normal, size.large, size.huge], inline = 'label')
//-----------------------------------------------------------------------------
// Variables
//-----------------------------------------------------------------------------
Helper candle_helper = Helper.new()
var CandeTrace candle_trace = CandeTrace.new()
//-----------------------------------------------------------------------------
// Methods
//-----------------------------------------------------------------------------
method CandleValidTimeframe(Helper helper, string HTF) =>
helper.name := HTF
if timeframe.in_seconds(HTF) >= timeframe.in_seconds('D') and timeframe.in_seconds(HTF) > timeframe.in_seconds()
true
else
n1 = timeframe.in_seconds()
n2 = timeframe.in_seconds(HTF)
n3 = n1 % n2
n1 < n2 and math.round(n2 / n1) == n2 / n1
method CandleRemainingTime(Helper helper, string HTF) =>
helper.name := HTF
if barstate.isrealtime
timeRemaining = (time_close(HTF) - timenow) / 1000
days = math.floor(timeRemaining / 86400)
hours = math.floor((timeRemaining - days * 86400) / 3600)
minutes = math.floor((timeRemaining - days * 86400 - hours * 3600) / 60)
seconds = math.floor(timeRemaining - days * 86400 - hours * 3600 - minutes * 60)
r = str.tostring(seconds, '00')
if minutes > 0 or hours > 0 or days > 0
r := str.tostring(minutes, '00') + ':' + r
r
if hours > 0 or days > 0
r := str.tostring(hours, '00') + ':' + r
r
if days > 0
r := str.tostring(days) + 'D ' + r
r
r
else
'n/a'
method CandleHTFName(Helper helper, string HTF) =>
helper.name := 'HTFName'
formatted = HTF
seconds = timeframe.in_seconds(HTF)
if seconds < 60
formatted := str.tostring(seconds) + 's'
formatted
else if seconds / 60 < 60
formatted := str.tostring(seconds / 60) + 'm'
formatted
else if seconds / 60 / 60 < 24
formatted := str.tostring(seconds / 60 / 60) + 'H'
formatted
formatted
method CandleHTFEnabled(Helper helper) =>
helper.name := 'HTFEnabled'
int enabled = 0
enabled := enabled + (candle_htf1.settings.show ? 1 : 0)
enabled := enabled + (candle_htf2.settings.show ? 1 : 0)
enabled := enabled + (candle_htf3.settings.show ? 1 : 0)
enabled := enabled + (candle_htf4.settings.show ? 1 : 0)
enabled := enabled + (candle_htf5.settings.show ? 1 : 0)
enabled := enabled + (candle_htf6.settings.show ? 1 : 0)
int last = math.min(enabled, candle_settings.max_sets)
last
method CandleSetHigh(Helper helper, array<Candle> candles, float h) =>
helper.name := 'CandlesSetHigh'
float _h = h
if array.size(candles) > 0
for i = 0 to array.size(candles) - 1 by 1
Candle c = array.get(candles, i)
if c.h > _h
_h := c.h
_h
_h
method CandleSetLow(Helper helper, array<Candle> candles, float l) =>
helper.name := 'CandlesSetLow'
float _l = l
if array.size(candles) > 0
for i = 0 to array.size(candles) - 1 by 1
Candle c = array.get(candles, i)
if c.l < _l
_l := c.l
_l
_l
method CandlesHigh(Helper helper, array<Candle> candles) =>
helper.name := 'CandlesHigh'
h = 0.0
int candle_cnt = 0
int last = helper.CandleHTFEnabled()
if candle_htf1.settings.show and helper.CandleValidTimeframe(candle_htf1.settings.htf)
h := helper.CandleSetHigh(candle_htf1.candles, h)
candle_cnt := candle_cnt + 1
if candle_htf2.settings.show and helper.CandleValidTimeframe(candle_htf2.settings.htf) and candle_cnt < last
h := helper.CandleSetHigh(candle_htf2.candles, h)
candle_cnt := candle_cnt + 1
if candle_htf3.settings.show and helper.CandleValidTimeframe(candle_htf3.settings.htf) and candle_cnt < last
h := helper.CandleSetHigh(candle_htf3.candles, h)
candle_cnt := candle_cnt + 1
if candle_htf4.settings.show and helper.CandleValidTimeframe(candle_htf4.settings.htf) and candle_cnt < last
h := helper.CandleSetHigh(candle_htf4.candles, h)
candle_cnt := candle_cnt + 1
if candle_htf5.settings.show and helper.CandleValidTimeframe(candle_htf5.settings.htf) and candle_cnt < last
h := helper.CandleSetHigh(candle_htf5.candles, h)
candle_cnt := candle_cnt + 1
if candle_htf6.settings.show and helper.CandleValidTimeframe(candle_htf6.settings.htf) and candle_cnt < last
h := helper.CandleSetHigh(candle_htf6.candles, h)
if array.size(candles) > 0
for i = 0 to array.size(candles) - 1 by 1
Candle c = array.get(candles, i)
if c.h > h
h := c.h
h
method CandlesLow(Helper helper, array<Candle> candles, float h) =>
helper.name := 'CandlesLow'
l = h
int candle_cnt = 0
int last = helper.CandleHTFEnabled()
if candle_htf1.settings.show and helper.CandleValidTimeframe(candle_htf1.settings.htf)
l := helper.CandleSetLow(candle_htf1.candles, l)
candle_cnt := candle_cnt + 1
if candle_htf2.settings.show and helper.CandleValidTimeframe(candle_htf2.settings.htf) and candle_cnt < last
l := helper.CandleSetLow(candle_htf2.candles, l)
candle_cnt := candle_cnt + 1
if candle_htf3.settings.show and helper.CandleValidTimeframe(candle_htf3.settings.htf) and candle_cnt < last
l := helper.CandleSetLow(candle_htf3.candles, l)
candle_cnt := candle_cnt + 1
if candle_htf4.settings.show and helper.CandleValidTimeframe(candle_htf4.settings.htf) and candle_cnt < last
l := helper.CandleSetLow(candle_htf4.candles, l)
candle_cnt := candle_cnt + 1
if candle_htf5.settings.show and helper.CandleValidTimeframe(candle_htf5.settings.htf) and candle_cnt < last
l := helper.CandleSetLow(candle_htf5.candles, l)
candle_cnt := candle_cnt + 1
if candle_htf6.settings.show and helper.CandleValidTimeframe(candle_htf6.settings.htf) and candle_cnt < last
l := helper.CandleSetLow(candle_htf6.candles, l)
if array.size(candles) > 0
for i = 0 to array.size(candles) - 1 by 1
Candle c = array.get(candles, i)
if c.l < l
l := c.l
l
method CandleUpdateTime(CandleSet candleSet, int offset) =>
if candle_settings.htf_timer_show and (barstate.isrealtime or barstate.islast)
string tmr = '(' + candle_helper.CandleRemainingTime(candleSet.settings.htf) + ')'
if not na(candleSet.tfTimerTop)
candleSet.tfTimerTop.set_text(tmr)
if not na(candleSet.tfTimerBottom)
candleSet.tfTimerBottom.set_text(tmr)
candleSet
method CandleReorder(CandleSet candleSet, int offset) =>
size = candleSet.candles.size()
if size > 0
for i = size - 1 to 0 by 1
Candle candle = candleSet.candles.get(i)
t_buffer = offset + (candle_settings.width + candle_settings.buffer) * (size - i - 1)
box.set_left(candle.body, bar_index + t_buffer)
box.set_right(candle.body, bar_index + candle_settings.width + t_buffer)
line.set_x1(candle.wick_up, bar_index + candle_settings.width / 2 + t_buffer)
line.set_x2(candle.wick_up, bar_index + candle_settings.width / 2 + t_buffer)
line.set_x1(candle.wick_down, bar_index + candle_settings.width / 2 + t_buffer)
line.set_x2(candle.wick_down, bar_index + candle_settings.width / 2 + t_buffer)
if candle_settings.daily_name //and candleSet.settings.htf == '1D'
if not na(candle.dow_label)
candle.dow_label.set_y(candle.h)
candle.dow_label.set_x(bar_index + candle_settings.width / 2 + t_buffer)
candle.dow_label.set_text(candle.dow)
else
candle.dow_label := label.new(bar_index + candle_settings.width / 2 + t_buffer, candle.h, candle.dow, color = TRANSPARENT_COLOR, textcolor = candle_settings.dow_color, style = label.style_label_down, size = candle_settings.dow_size)
top = 0.0
bottom = 0.0
if candle_settings.label_alignment == 'Align'
top := candle_helper.CandlesHigh(candleSet.candles)
bottom := candle_helper.CandlesLow(candleSet.candles, top)
if candle_settings.label_alignment == 'Follow Candles'
top := candle_helper.CandleSetHigh(candleSet.candles, 0)
bottom := candle_helper.CandleSetLow(candleSet.candles, top)
left = bar_index + offset + (candle_settings.width + candle_settings.buffer) * (size - 1) / 2
if candle_settings.htf_label_show
string lblt = candle_helper.CandleHTFName(candleSet.settings.htf)
string lbll = lblt
if candle_settings.htf_timer_show
lblt := lblt + '\n'
lbll := '\n' + lbll
if candle_settings.daily_name
lblt := lblt + '\n'
string tmr = '(' + candle_helper.CandleRemainingTime(candleSet.settings.htf) + ')' + (candle_settings.daily_name ? '\n' : '')
if candle_settings.label_position == 'Both' or candle_settings.label_position == 'Top'
if not na(candleSet.tfNameTop)
candleSet.tfNameTop.set_xy(left, top)
else
candleSet.tfNameTop := label.new(left, top, lblt, color = TRANSPARENT_COLOR, textcolor = candle_settings.htf_label_color, style = label.style_label_down, size = candle_settings.htf_label_size)
if candle_settings.htf_timer_show
if not na(candleSet.tfTimerTop)
candleSet.tfTimerTop.set_xy(left, top)
else
candleSet.tfTimerTop := label.new(left, top, tmr, color = TRANSPARENT_COLOR, textcolor = candle_settings.htf_timer_color, style = label.style_label_down, size = candle_settings.htf_timer_size)
if candle_settings.label_position == 'Both' or candle_settings.label_position == 'Bottom'
if not na(candleSet.tfNameBottom)
candleSet.tfNameBottom.set_xy(left, bottom)
else
candleSet.tfNameBottom := label.new(left, bottom, lbll, color = TRANSPARENT_COLOR, textcolor = candle_settings.htf_label_color, style = label.style_label_up, size = candle_settings.htf_label_size)
if candle_settings.htf_timer_show
if candle_settings.htf_timer_show
if not na(candleSet.tfTimerBottom)
candleSet.tfTimerBottom.set_xy(left, bottom)
else
candleSet.tfTimerBottom := label.new(left, bottom, tmr, color = TRANSPARENT_COLOR, textcolor = candle_settings.htf_timer_color, style = label.style_label_up, size = candle_settings.htf_timer_size)
candleSet
method CandleFindImbalance(CandleSet candleSet) =>
if barstate.isrealtime or barstate.islast
if candleSet.imbalances.size() > 0
for i = candleSet.imbalances.size() - 1 to 0 by 1
CandeImbalance del = candleSet.imbalances.get(i)
box.delete(del.b)
candleSet.imbalances.pop()
if candleSet.candles.size() > 3 and candle_settings.fvg_show
for i = 0 to candleSet.candles.size() - 3 by 1
candle1 = candleSet.candles.get(i)
candle2 = candleSet.candles.get(i + 2)
candle3 = candleSet.candles.get(i + 1)
if candle1.l > candle2.h and math.min(candle1.o, candle1.c) > math.max(candle2.o, candle2.c)
CandeImbalance imb = CandeImbalance.new()
imb.b := box.new(box.get_left(candle2.body), candle2.h, box.get_right(candle1.body), candle1.l, bgcolor = candle_settings.fvg_color, border_color = candle_settings.fvg_color, xloc = xloc.bar_index)
candleSet.imbalances.push(imb)
if candle1.h < candle2.l and math.max(candle1.o, candle1.c) < math.min(candle2.o, candle2.c)
CandeImbalance imb = CandeImbalance.new()
imb.b := box.new(box.get_right(candle1.body), candle1.h, box.get_left(candle2.body), candle2.l, bgcolor = candle_settings.fvg_color, border_color = candle_settings.fvg_color)
candleSet.imbalances.push(imb)
box temp = box.copy(candle3.body)
box.delete(candle3.body)
candle3.body := temp
candle3.body
if candleSet.candles.size() > 2 and candle_settings.vi_show
for i = 0 to candleSet.candles.size() - 2 by 1
candle1 = candleSet.candles.get(i)
candle2 = candleSet.candles.get(i + 1)
if candle1.l < candle2.h and math.min(candle1.o, candle1.c) > math.max(candle2.o, candle2.c)
CandeImbalance imb = CandeImbalance.new()
imb.b := box.new(box.get_left(candle2.body), math.min(candle1.o, candle1.c), box.get_right(candle1.body), math.max(candle2.o, candle2.c), bgcolor = candle_settings.vi_color, border_color = TRANSPARENT_COLOR)
candleSet.imbalances.push(imb)
if candle1.h > candle2.l and math.max(candle1.o, candle1.c) < math.min(candle2.o, candle2.c)
CandeImbalance imb = CandeImbalance.new()
imb.b := box.new(box.get_right(candle1.body), math.min(candle2.o, candle2.c), box.get_left(candle2.body), math.max(candle1.o, candle1.c), bgcolor = candle_settings.vi_color, border_color = TRANSPARENT_COLOR)
candleSet.imbalances.push(imb)
candleSet
method CandleMonitor(CandleSet candleSet) =>
HTFBarTime = time(candleSet.settings.htf, 'america/New_York')
isNewHTFCandle = ta.change(HTFBarTime) > 0
if candle_settings.use_custom_daily
int _830 = 0
if isNewHTFCandle
_830 := timestamp("America/New_York", year(time), month(time), dayofmonth(time), 0, 0) + 30600000
if candleSet.settings.htf == '1D'
if candle_settings.custom_daily == 'Midnight'
isNewHTFCandle := dayofweek(time, 'America/New_York') != dayofweek(time - (time - time[1]), 'America/New_York')
if candle_settings.custom_daily == '8:30'
// Get 8:30 AM New York time for today
isNewHTFCandle := not na(time(timeframe.period, "0830-0831:123456", 'America/New_York')) and na(time(timeframe.period, "0830-0831:123456", 'America/New_York')[1])
if candle_settings.custom_daily == '9:30'
// Get 9:30 AM New York time for today
isNewHTFCandle := not na(time(timeframe.period, "0930-0931:123456", 'America/New_York')) and na(time(timeframe.period, "0930-0931:123456", 'America/New_York')[1])
if isNewHTFCandle
Candle candle = Candle.new()
candle.o := open
candle.c := close
candle.h := high
candle.l := low
candle.o_time := time
candle.o_idx := bar_index
candle.c_idx := bar_index
candle.h_idx := bar_index
candle.l_idx := bar_index
candle.dow := switch
candleSet.settings.htf == '1D' =>
candle_helper.DayOfWeek(dayofweek(time_tradingday, "America/New_York"))
str.tonumber(candleSet.settings.htf) < 60 =>
str.format_time(candle.o_time, 'm', 'America/New_York')
str.tonumber(candleSet.settings.htf) >= 60 =>
str.format_time(candle.o_time, 'H', 'America/New_York')
candleSet.settings.htf == '1M' =>
str.format_time(candle.o_time, 'M', 'America/New_York')
=>
''
log.info('dow: {1} |{0}|', candle.dow, candleSet.settings.htf)
bull = candle.c > candle.o
candle.body := box.new(bar_index, math.max(candle.o, candle.c), bar_index + 2, math.min(candle.o, candle.c), bull ? candle_settings.bull_border : candle_settings.bear_border, 1, bgcolor = bull ? candle_settings.bull_body : candle_settings.bear_body)
candle.wick_up := line.new(bar_index + 1, candle.h, bar_index, math.max(candle.o, candle.c), color = bull ? candle_settings.bull_wick : candle_settings.bear_wick)
candle.wick_down := line.new(bar_index + 1, math.min(candle.o, candle.c), bar_index, candle.l, color = bull ? candle_settings.bull_wick : candle_settings.bear_wick)
candleSet.candles.unshift(candle)
if candleSet.candles.size() > candleSet.settings.max_display
Candle delCandle = array.pop(candleSet.candles)
box.delete(delCandle.body)
line.delete(delCandle.wick_up)
line.delete(delCandle.wick_down)
delCandle.dow_label.delete()
candleSet
method CandleUpdate(CandleSet candleSet, int offset, bool showTrace) =>
if candleSet.candles.size() > 0
Candle candle = candleSet.candles.first()
candle.h_idx := high > candle.h ? bar_index : candle.h_idx
candle.h := high > candle.h ? high : candle.h
candle.l_idx := low < candle.l ? bar_index : candle.l_idx
candle.l := low < candle.l ? low : candle.l
candle.c := close
candle.c_idx := bar_index
bull = candle.c > candle.o
box.set_top(candle.body, candle.o)
box.set_bottom(candle.body, candle.c)
box.set_bgcolor(candle.body, bull ? candle_settings.bull_body : candle_settings.bear_body)
box.set_border_color(candle.body, bull ? candle_settings.bull_border : candle_settings.bear_border)
line.set_color(candle.wick_up, bull ? candle_settings.bull_wick : candle_settings.bear_wick)
line.set_color(candle.wick_down, bull ? candle_settings.bull_wick : candle_settings.bear_wick)
line.set_y1(candle.wick_up, candle.h)
line.set_y2(candle.wick_up, math.max(candle.o, candle.c))
line.set_y1(candle.wick_down, candle.l)
line.set_y2(candle.wick_down, math.min(candle.o, candle.c))
if barstate.isrealtime or barstate.islast
candleSet.CandleReorder(offset)
if candle_settings.trace_show and showTrace
if bar_index - candle.o_idx < 5000
if na(candle_trace.o)
candle_trace.o := line.new(candle.o_idx, candle.o, box.get_left(candle.body), candle.o, xloc = xloc.bar_index, color = candle_settings.trace_o_color, style = candle_helper.LineStyle(candle_settings.trace_o_style), width = candle_settings.trace_o_size)
candle_trace.o
else
line.set_xy1(candle_trace.o, candle.o_idx, candle.o)
line.set_xy2(candle_trace.o, box.get_left(candle.body), candle.o)
if candle_settings.label_show
if na(candle_trace.o_l)
candle_trace.o_l := label.new(box.get_right(candle.body), candle.o, str.tostring(candle.o), textalign = text.align_center, style = label.style_label_left, size = candle_settings.label_size, color = TRANSPARENT_COLOR, textcolor = candle_settings.label_color)
candle_trace.o_l
else
label.set_xy(candle_trace.o_l, box.get_right(candle.body), candle.o)
label.set_text(candle_trace.o_l, str.tostring(candle.o))
if bar_index - candle.c_idx < 5000
if na(candle_trace.c)
candle_trace.c := line.new(candle.c_idx, candle.c, box.get_left(candle.body), candle.c, xloc = xloc.bar_index, color = candle_settings.trace_c_color, style = candle_helper.LineStyle(candle_settings.trace_c_style), width = candle_settings.trace_c_size)
candle_trace.c
else
line.set_xy1(candle_trace.c, candle.c_idx, candle.c)
line.set_xy2(candle_trace.c, box.get_left(candle.body), candle.c)
if candle_settings.label_show
if na(candle_trace.c_l)
candle_trace.c_l := label.new(box.get_right(candle.body), candle.c, str.tostring(candle.c), textalign = text.align_center, style = label.style_label_left, size = candle_settings.label_size, color = TRANSPARENT_COLOR, textcolor = candle_settings.label_color)
candle_trace.c_l
else
label.set_xy(candle_trace.c_l, box.get_right(candle.body), candle.c)
label.set_text(candle_trace.c_l, str.tostring(candle.c))
if bar_index - candle.h_idx < 5000
if na(candle_trace.h)
candle_trace.h := line.new(candle.h_idx, candle.h, line.get_x1(candle.wick_up), candle.h, xloc = xloc.bar_index, color = candle_settings.trace_h_color, style = candle_helper.LineStyle(candle_settings.trace_h_style), width = candle_settings.trace_h_size)
candle_trace.h
else
line.set_xy1(candle_trace.h, candle.h_idx, candle.h)
line.set_xy2(candle_trace.h, line.get_x1(candle.wick_up), candle.h)
if candle_settings.label_show
if na(candle_trace.h_l)
candle_trace.h_l := label.new(box.get_right(candle.body), candle.h, str.tostring(candle.h), textalign = text.align_center, style = label.style_label_left, size = candle_settings.label_size, color = TRANSPARENT_COLOR, textcolor = candle_settings.label_color)
candle_trace.h_l
else
label.set_xy(candle_trace.h_l, box.get_right(candle.body), candle.h)
label.set_text(candle_trace.h_l, str.tostring(candle.h))
if bar_index - candle.l_idx < 5000
if na(candle_trace.l)
candle_trace.l := line.new(candle.l_idx, candle.l, line.get_x1(candle.wick_down), candle.l, xloc = xloc.bar_index, color = candle_settings.trace_l_color, style = candle_helper.LineStyle(candle_settings.trace_l_style), width = candle_settings.trace_l_size)
candle_trace.l
else
line.set_xy1(candle_trace.l, candle.l_idx, candle.l)
line.set_xy2(candle_trace.l, line.get_x1(candle.wick_down), candle.l)
if candle_settings.label_show
if na(candle_trace.l_l)
candle_trace.l_l := label.new(box.get_right(candle.body), candle.l, str.tostring(candle.l), textalign = text.align_center, style = label.style_label_left, size = candle_settings.label_size, color = TRANSPARENT_COLOR, textcolor = candle_settings.label_color)
candle_trace.l_l
else
label.set_xy(candle_trace.l_l, box.get_right(candle.body), candle.l)
label.set_text(candle_trace.l_l, str.tostring(candle.l))
candleSet
//-----------------------------------------------------------------------------
// Calculate & Render
//-----------------------------------------------------------------------------
int candle_cnt = 0
int candle_last = candle_helper.CandleHTFEnabled()
int candle_offset = candle_settings.offset
if candle_htf1.settings.show and candle_helper.CandleValidTimeframe(candle_htf1.settings.htf)
bool showTrace = false
if candle_settings.trace_anchor == 'First Timeframe'
showTrace := true
showTrace
if candle_settings.trace_anchor == 'Last Timeframe' and candle_settings.max_sets == 1
showTrace := true
showTrace
candle_htf1.CandleUpdateTime(candle_offset)
candle_htf1.CandleMonitor().CandleUpdate(candle_offset, showTrace).CandleFindImbalance()
candle_cnt := candle_cnt + 1
candle_offset := candle_offset + (candle_cnt > 0 ? candle_htf1.candles.size() * candle_settings.width + (candle_htf1.candles.size() > 0 ? (candle_htf1.candles.size() - 1) * candle_settings.buffer : 0) + candle_settings.htf_buffer : 0)
candle_offset
if candle_htf2.settings.show and candle_helper.CandleValidTimeframe(candle_htf2.settings.htf) and candle_cnt < candle_last
bool showTrace = false
if candle_settings.trace_anchor == 'First Timeframe' and candle_cnt == 0
showTrace := true
showTrace
if candle_settings.trace_anchor == 'Last Timeframe' and candle_cnt == candle_last - 1
showTrace := true
showTrace
candle_htf2.CandleUpdateTime(candle_offset)
candle_htf2.CandleMonitor().CandleUpdate(candle_offset, showTrace).CandleFindImbalance()
candle_cnt := candle_cnt + 1
candle_offset := candle_offset + (candle_cnt > 0 ? candle_htf2.candles.size() * candle_settings.width + (candle_htf2.candles.size() > 0 ? (candle_htf2.candles.size() - 1) * candle_settings.buffer : 0) + candle_settings.htf_buffer : 0)
candle_offset
if candle_htf3.settings.show and candle_helper.CandleValidTimeframe(candle_htf3.settings.htf) and candle_cnt < candle_last
bool showTrace = false
if candle_settings.trace_anchor == 'First Timeframe' and candle_cnt == 0
showTrace := true
showTrace
if candle_settings.trace_anchor == 'Last Timeframe' and candle_cnt == candle_last - 1
showTrace := true
showTrace
candle_htf3.CandleUpdateTime(candle_offset)
candle_htf3.CandleMonitor().CandleUpdate(candle_offset, showTrace).CandleFindImbalance()
candle_cnt := candle_cnt + 1
candle_offset := candle_offset + (candle_cnt > 0 ? candle_htf3.candles.size() * candle_settings.width + (candle_htf3.candles.size() > 0 ? (candle_htf3.candles.size() - 1) * candle_settings.buffer : 0) + candle_settings.htf_buffer : 0)
candle_offset
if candle_htf4.settings.show and candle_helper.CandleValidTimeframe(candle_htf4.settings.htf) and candle_cnt < candle_last
bool showTrace = false
if candle_settings.trace_anchor == 'First Timeframe' and candle_cnt == 0
showTrace := true
showTrace
if candle_settings.trace_anchor == 'Last Timeframe' and candle_cnt == candle_last - 1
showTrace := true
showTrace
candle_htf4.CandleUpdateTime(candle_offset)
candle_htf4.CandleMonitor().CandleUpdate(candle_offset, showTrace).CandleFindImbalance()
candle_cnt := candle_cnt + 1
candle_offset := candle_offset + (candle_cnt > 0 ? candle_htf4.candles.size() * candle_settings.width + (candle_htf4.candles.size() > 0 ? (candle_htf4.candles.size() - 1) * candle_settings.buffer : 0) + candle_settings.htf_buffer : 0)
candle_offset
if candle_htf5.settings.show and candle_helper.CandleValidTimeframe(candle_htf5.settings.htf) and candle_cnt < candle_last
bool showTrace = false
if candle_settings.trace_anchor == 'First Timeframe' and candle_cnt == 0
showTrace := true
showTrace
if candle_settings.trace_anchor == 'Last Timeframe' and candle_cnt == candle_last - 1
showTrace := true
showTrace
candle_htf5.CandleUpdateTime(candle_offset)
candle_htf5.CandleMonitor().CandleUpdate(candle_offset, showTrace).CandleFindImbalance()
candle_cnt := candle_cnt + 1
candle_offset := candle_offset + (candle_cnt > 0 ? candle_htf5.candles.size() * candle_settings.width + (candle_htf5.candles.size() > 0 ? (candle_htf5.candles.size() - 1) * candle_settings.buffer : 0) + candle_settings.htf_buffer : 0)
candle_offset
if candle_htf6.settings.show and candle_helper.CandleValidTimeframe(candle_htf6.settings.htf) and candle_cnt < candle_last
bool showTrace = false
if candle_settings.trace_anchor == 'First Timeframe' and candle_cnt == 0
showTrace := true
showTrace
if candle_settings.trace_anchor == 'Last Timeframe'
showTrace := true
showTrace
candle_htf6.CandleUpdateTime(candle_offset)
candle_htf6.CandleMonitor().CandleUpdate(candle_offset, showTrace).CandleFindImbalance()
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Order Flow
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
type OFSettings
string liquidity_open_style
string liquidity_claimed_style
string ST_label
string IT_label
string LT_label
bool ST_show
string ST_text_size
color ST_color_bull
color ST_color_bear
color ST_label_color
bool ST_liquidity_show
color ST_liquidity_open_color
int ST_liquidity_size
color ST_liquidity_claimed_color
bool IT_show
string IT_text_size
color IT_color_bull
color IT_color_bear
color IT_label_color
bool IT_liquidity_show
color IT_liquidity_open_color
int IT_liquidity_size
color IT_liquidity_claimed_color
bool LT_show
string LT_text_size
color LT_color_bull
color LT_color_bear
color LT_label_color
bool LT_liquidity_show
color LT_liquidity_open_color
int LT_liquidity_size
color LT_liquidity_claimed_color
int max_labels
bool liquidity_open_show
int max_lines
int max_claimed_lines
int extend
bool EQ_show
int EQ_max
int EQ_max_claimed
bool EQ_link_show
color EQ_link_color
string EQ_link_style
int EQ_link_size
bool EQ_line_extend
color EQ_color_bull
color EQ_color_bear
string EQ_style
string EQ_claimed_style
int EQ_size
bool EQ_shade
color EQ_shade_bull
color EQ_shade_bear
int EQ_Tolerance
bool displacement_show
bool displacement_fvg
int displacement_length
int displacement_factor
color displacement_bull
color displacement_bear
type Pivot
int index = 0
int time = 0
float price = 0
int time_last = 0
bool claimed = false
bool isHigh = false
bool isLow = false
bool isSHigherHigh = false
bool isSLowerLow = false
bool isIHigherHigh = false
bool isILowerLow = false
bool isLHigherHigh = false
bool isLLowerLow = false
bool isST = true
bool isIT = false
bool isLT = false
label lbl = na
line ln = na
type MarketStructure
string name
array<Pivot> ST
array<Pivot> STH
array<Pivot> ITH
array<Pivot> LTH
array<Pivot> STL
array<Pivot> ITL
array<Pivot> LTL
OFSettings settings
type EqualLevels
float price
float start
float end
int start_time
int end_time
int start_index
int end_index
bool isHigh
bool isLow
bool isClaimed
int claimed_time
line line_eq
line line_link
box box_link
//-----------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------
int MAX_BUFFER = 1000 // internal maximum node count limit for performance
Market_Structure_Group = 'Market Structure ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
Label_Format_Group = 'Label Format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
settings_liquidity = 'Liquidity Levels ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
settings_liquidity_style = 'Liquidity Style ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
settings_eq = 'Relative Equal Highs and Lows ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
settings_displacement = 'Displacement ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
FVG_Group = 'Fair Value Gap ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
FVG_HP_Group = 'For High Probability Fair Value Gap ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
Imb_Group = 'Volume Imbalance ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
Gap_Group = 'Open Gaps ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'
inline_st = 'ST'
inline_st_liquidity = 'ST liquidity'
inline_it = 'IT'
inline_it_liquidity = 'IT liquidity'
inline_lt = 'LT'
inline_lt_liquidity = 'LT liquidity'
inline_liquidity_open = 'open liquidity'
inline_liquidity_claimed = 'claimed liquidity'
inline_eq = 'EQ'
inline_eq_link = 'EQ Link'
inline_eq_shade = 'EQ Shade'
inline_displacement = 'displacement'
OFSettings Trend_Settings = OFSettings.new()
Trend_Settings.ST_show := input.bool(false, 'Short', group = Market_Structure_Group, inline = inline_st)
Trend_Settings.ST_color_bull := input.color(color.black, '', group = Market_Structure_Group, inline = inline_st)
Trend_Settings.ST_color_bear := input.color(color.black, '', group = Market_Structure_Group, inline = inline_st)
Trend_Settings.ST_label_color := input.color(TRANSPARENT_COLOR, '', group = Market_Structure_Group, inline = inline_st)
Trend_Settings.IT_show := input.bool(false, 'Intermediate', group = Market_Structure_Group, inline = inline_it)
Trend_Settings.IT_color_bull := input.color(color.new(AQUA_COLOR, 0), '', group = Market_Structure_Group, inline = inline_it)
Trend_Settings.IT_color_bear := input.color(color.new(AQUA_COLOR, 0), '', group = Market_Structure_Group, inline = inline_it)
Trend_Settings.IT_label_color := input.color(TRANSPARENT_COLOR, '', group = Market_Structure_Group, inline = inline_it)
Trend_Settings.LT_show := input.bool(false, 'Long', group = Market_Structure_Group, inline = inline_lt)
Trend_Settings.LT_color_bull := input.color(color.new(PURPLE_COLOR, 0), '', group = Market_Structure_Group, inline = inline_lt)
Trend_Settings.LT_color_bear := input.color(color.new(PURPLE_COLOR, 0), '', group = Market_Structure_Group, inline = inline_lt)
Trend_Settings.LT_label_color := input.color(TRANSPARENT_COLOR, '', group = Market_Structure_Group, inline = inline_lt)
Trend_Settings.ST_label := input.string('High/Low', 'Short', options = ['■', '□', '▣', '◆', '◇', '◈', '●', '○', '◉', '▲▼', '△▽', '↑↓', 'S/I/L Term', 'High/Low'], group = Label_Format_Group, inline = '1')
Trend_Settings.ST_text_size := input.string(size.tiny, '', [size.tiny, size.small, size.normal, size.large, size.huge], group = Label_Format_Group, inline = '1')
Trend_Settings.IT_label := input.string('High/Low', 'Intermediate', options = ['■', '□', '▣', '◆', '◇', '◈', '●', '○', '◉', '▲▼', '△▽', '↑↓', 'S/I/L Term', 'High/Low'], group = Label_Format_Group, inline = '2')
Trend_Settings.IT_text_size := input.string(size.small, '', [size.tiny, size.small, size.normal, size.large, size.huge], group = Label_Format_Group, inline = '2')
Trend_Settings.LT_label := input.string('High/Low', 'Long', options = ['■', '□', '▣', '◆', '◇', '◈', '●', '○', '◉', '▲▼', '△▽', '↑↓', 'S/I/L Term', 'High/Low'], group = Label_Format_Group, inline = '3')
Trend_Settings.LT_text_size := input.string(size.normal, '', [size.tiny, size.small, size.normal, size.large, size.huge], group = Label_Format_Group, inline = '3')
Trend_Settings.max_labels := input.int(50, 'Maximum number of labels', group = Label_Format_Group)
Trend_Settings.ST_liquidity_show := input.bool(false, 'Short', group = settings_liquidity, inline = inline_st_liquidity)
Trend_Settings.ST_liquidity_open_color := input.color(color.new(color.black, 50), '', group = settings_liquidity, inline = inline_st_liquidity)
Trend_Settings.ST_liquidity_claimed_color := input.color(color.new(color.black, 50), '', group = settings_liquidity, inline = inline_st_liquidity)
Trend_Settings.ST_liquidity_size := input.int(1, '', options = [1, 2, 3, 4], group = settings_liquidity, inline = inline_st_liquidity)
Trend_Settings.IT_liquidity_show := input.bool(false, 'Intermediate', group = settings_liquidity, inline = inline_it_liquidity)
Trend_Settings.IT_liquidity_open_color := input.color(color.new(AQUA_COLOR, 60), '', group = settings_liquidity, inline = inline_it_liquidity)
Trend_Settings.IT_liquidity_claimed_color := input.color(color.new(AQUA_COLOR, 40), '', group = settings_liquidity, inline = inline_it_liquidity)
Trend_Settings.IT_liquidity_size := input.int(1, '', options = [1, 2, 3, 4], group = settings_liquidity, inline = inline_it_liquidity)
Trend_Settings.LT_liquidity_show := input.bool(true, 'Long', group = settings_liquidity, inline = inline_lt_liquidity)
Trend_Settings.LT_liquidity_open_color := input.color(color.new(PURPLE_COLOR, 60), '', group = settings_liquidity, inline = inline_lt_liquidity)
Trend_Settings.LT_liquidity_claimed_color := input.color(color.new(PURPLE_COLOR, 40), '', group = settings_liquidity, inline = inline_lt_liquidity)
Trend_Settings.LT_liquidity_size := input.int(1, '', options = [1, 2, 3, 4], group = settings_liquidity, inline = inline_lt_liquidity)
Trend_Settings.liquidity_open_style := input.string('⎯⎯⎯', 'Open', options = ['⎯⎯⎯', '----', '····'], group = settings_liquidity_style)
Trend_Settings.liquidity_claimed_style := input.string('----', 'Claimed', options = ['⎯⎯⎯', '----', '····'], group = settings_liquidity_style)
Trend_Settings.extend := input.int(2, title = 'Extend', minval = 1, group = settings_liquidity_style)
Trend_Settings.max_lines := input.int(50, 'Maximum number of lines', minval = 1, maxval = 250, group = settings_liquidity_style)
Trend_Settings.max_claimed_lines := input.int(5, 'Maximum number of claimed lines', minval = 0, maxval = 250, group = settings_liquidity_style)
Trend_Settings.EQ_show := input.bool(true, 'Equal Levels', group = settings_eq, inline = inline_eq)
Trend_Settings.EQ_color_bull := input.color(TRANSPARENT_COLOR, '', group = settings_eq, inline = inline_eq)
Trend_Settings.EQ_color_bear := input.color(TRANSPARENT_COLOR, '', group = settings_eq, inline = inline_eq)
Trend_Settings.EQ_size := input.int(1, '', options = [1, 2, 3, 4], group = settings_eq, inline = inline_eq)
Trend_Settings.EQ_style := input.string('⎯⎯⎯', '', options = ['⎯⎯⎯', '----', '····'], group = settings_eq, inline = inline_eq)
Trend_Settings.EQ_link_show := input.bool(true, 'Link Levels', group = settings_eq, inline = inline_eq_link)
Trend_Settings.EQ_link_color := input.color(LIGHT_GRAY_COLOR, '', group = settings_eq, inline = inline_eq_link)
Trend_Settings.EQ_link_size := input.int(1, '', options = [1, 2, 3, 4], group = settings_eq, inline = inline_eq_link)
Trend_Settings.EQ_link_style := input.string('····', '', options = ['⎯⎯⎯', '----', '····'], group = settings_eq, inline = inline_eq_link)
Trend_Settings.EQ_shade := input.bool(true, 'Highlight', group = settings_eq, inline = inline_eq_shade)
Trend_Settings.EQ_shade_bull := input.color(color.new(AQUA_COLOR, 95), '', group = settings_eq, inline = inline_eq_shade)
Trend_Settings.EQ_shade_bear := input.color(color.new(PURPLE_COLOR, 90), '', group = settings_eq, inline = inline_eq_shade)
Trend_Settings.EQ_claimed_style := input.string('····', 'Claimed Style', options = ['⎯⎯⎯', '----', '····'], group = settings_eq)
Trend_Settings.EQ_Tolerance := input.int(2, 'Distance Tolerance', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], group = settings_eq) / 10
Trend_Settings.EQ_max := input.int(20, 'Maximum number of Equal Levels', minval = 1, group = settings_eq)
Trend_Settings.EQ_max_claimed := input.int(5, 'Maximum number of Claimed Levels', minval = 1, group = settings_eq)
//-----------------------------------------------------------------------------
// Variables
//-----------------------------------------------------------------------------
Helper of_helper = Helper.new()
var MarketStructure Term = MarketStructure.new('Term')
var array<Pivot> ST_array = array.new<Pivot>()
var array<Pivot> IT_array = array.new<Pivot>()
var array<Pivot> LT_array = array.new<Pivot>()
var array<Pivot> STH_array = array.new<Pivot>()
var array<Pivot> ITH_array = array.new<Pivot>()
var array<Pivot> LTH_array = array.new<Pivot>()
var array<Pivot> STL_array = array.new<Pivot>()
var array<Pivot> ITL_array = array.new<Pivot>()
var array<Pivot> LTL_array = array.new<Pivot>()
Term.ST := ST_array
Term.STH := STH_array
Term.ITH := ITH_array
Term.LTH := LTH_array
Term.STL := STL_array
Term.ITL := ITL_array
Term.LTL := LTL_array
Term.settings := Trend_Settings
var array<EqualLevels> EQs = array.new<EqualLevels>()
var array<label> labels = array.new_label()
var array<EqualLevels> EQ_claimed = array.new<EqualLevels>()
var line tester = line.new(na, na, na, na, color = TRANSPARENT_COLOR)
body = math.abs(open - close)
std = ta.stdev(math.abs(open - close), Trend_Settings.displacement_length)
var array<float> median = array.new_float()
length = 14
median.unshift(ta.atr(length))
if median.size() > length
median.pop()
float spacing = median.median() * Trend_Settings.EQ_Tolerance
//-----------------------------------------------------------------------------
// Methods
//-----------------------------------------------------------------------------
// SkipEQHigh returns the first bar_index of before the equal highs
// This is used to compare pivot points, if two at equal levels
// then we need to compare it to previous high, otherwise it will
// not identify the right STH/STL
method SkipEQHigh(Helper helper, int idx) =>
helper.name := 'Skip EQ Highs'
i = idx
while high[i] == high[i - 1]
i := i + 1
i
i
// SkipEQLows returns the first bar_index of before the equal lows
method SkipEQLow(Helper helper, int idx) =>
helper.name := 'Skip EQ Lows'
i = idx
while low[i] == low[i - 1]
i := i + 1
i
i
// Same as above, but works on pivot points. it also doesn't care for
// high or low since Pivot is a single price point
method SkipEQPivot(array<Pivot> p, int idx) =>
i = idx
if p.size() >= i
while p.get(i).price == p.get(i - 1).price and p.size() <= i - 1
i := i + 1
i
i
method OFAddEQ(array<EqualLevels> this, Pivot p1, Pivot p2) =>
EqualLevels eq = EqualLevels.new()
eq.start := p1.price
eq.start_time := p1.time
eq.start_index := p1.index
eq.end := p2.price
eq.end_time := p2.time
eq.end_index := p2.index
eq.isHigh := p1.isHigh
eq.isLow := p1.isLow
if Trend_Settings.EQ_show
int start_time = 0
if eq.isHigh
eq.price := eq.start > eq.end ? eq.start : eq.end
start_time := eq.start > eq.end ? eq.start_time : eq.end_time
start_time
else
eq.price := eq.start < eq.end ? eq.start : eq.end
start_time := eq.start < eq.end ? eq.start_time : eq.end_time
start_time
eq.line_eq := line.new(eq.start_time, eq.price, time, eq.price, xloc = xloc.bar_time, style = of_helper.LineStyle(Trend_Settings.EQ_style), color = eq.isHigh ? Trend_Settings.EQ_color_bull : Trend_Settings.EQ_color_bear, width = Trend_Settings.EQ_size)
if Trend_Settings.EQ_link_show
eq.line_link := line.new(eq.start_time, eq.start, eq.end_time, eq.end, xloc = xloc.bar_time, style = of_helper.LineStyle(Trend_Settings.EQ_link_style), color = Trend_Settings.EQ_link_color, width = Trend_Settings.EQ_link_size)
eq.line_link
if Trend_Settings.EQ_shade
eq.box_link := box.new(eq.start_time, eq.start, eq.end_time, eq.end, xloc = xloc.bar_time, border_color = TRANSPARENT_COLOR, bgcolor = eq.isHigh ? Trend_Settings.EQ_shade_bull : Trend_Settings.EQ_shade_bear)
eq.box_link
this.unshift(eq)
if this.size() > Trend_Settings.EQ_max + Trend_Settings.EQ_max_claimed
EqualLevels t = this.pop()
t.line_eq.delete()
t.line_link.delete()
t.box_link.delete()
this
OFTestEQ(Pivot p1, Pivot p2) =>
bool valid = true
tester.set_xy1(p1.index, p1.price)
tester.set_xy2(p2.index, p2.price)
for i = p1.index + 1 to p2.index - 1 by 1
bool isHigh = p1.isHigh
float p = tester.get_price(i)
int j = bar_index - i
if isHigh and high[j] > p or not isHigh and low[j] < p
valid := false
valid
valid
method OFProcessEQ(array<EqualLevels> this, Pivot p1, Pivot p2) =>
bool matched = false
for p in this
if p.start_index == p1.index and not p.isClaimed
if p.end <= p2.price and p.isHigh or p.end >= p2.price and p.isLow
if OFTestEQ(p1, p2)
p.end := p2.price
p.end_time := p2.time
p.end_index := p2.index
p.line_link.set_xy2(p.end_time, p.end)
p.box_link.set_rightbottom(p.end_time, p.end)
matched := true
break
if (p.end_index == p2.index or p.end_index == p1.index) and (p.isLow == p1.isLow or p.isLow == p2.isLow)
matched := true
break
if not matched
if OFTestEQ(p1, p2)
this.OFAddEQ(p1, p2)
this
method OFFindEQ(MarketStructure MS, Pivot pivot) =>
if MS.settings.EQ_show or MS.settings.EQ_link_show
if MS.ST.size() > 2
for p in MS.ST
if (p.isHigh and pivot.isHigh or p.isLow and pivot.isLow) and p.index != pivot.index
if math.abs(p.price - pivot.price) < spacing
EQs.OFProcessEQ(p, pivot)
MS
method OfGetLabel(Pivot pivot) =>
string lbl = ''
if Trend_Settings.ST_show and pivot.isST and (not pivot.isIT or not Trend_Settings.IT_show) and (not pivot.isLT or not Trend_Settings.LT_show)
switch Trend_Settings.ST_label
'S/I/L Term' =>
lbl := lbl + 'ST'
lbl := lbl + (pivot.isHigh ? 'H' : 'L')
lbl
'High/Low' =>
lbl := lbl + 'ST'
lbl := lbl + (pivot.isHigh ? pivot.isSHigherHigh ? '-HH' : '-LH' : pivot.isSLowerLow ? '-LL' : '-HL')
lbl
=>
if str.length(Trend_Settings.ST_label) == 1
lbl := Trend_Settings.ST_label
lbl
else
array<string> symb = str.split(Trend_Settings.ST_label, '')
lbl := lbl + (pivot.isHigh ? symb.get(1) : symb.get(0))
lbl
if Trend_Settings.IT_show and pivot.isIT and (not pivot.isLT or not Trend_Settings.LT_show)
switch Trend_Settings.IT_label
'S/I/L Term' =>
lbl := lbl + 'IT'
lbl := lbl + (pivot.isHigh ? 'H' : 'L')
lbl
'High/Low' =>
lbl := lbl + 'IT'
lbl := lbl + (pivot.isHigh ? pivot.isIHigherHigh ? '-HH' : '-LH' : pivot.isILowerLow ? '-LL' : '-HL')
lbl
=>
if str.length(Trend_Settings.IT_label) == 1
lbl := Trend_Settings.IT_label
lbl
else
array<string> symb = str.split(Trend_Settings.IT_label, '')
lbl := lbl + (pivot.isHigh ? symb.get(1) : symb.get(0))
lbl
if Trend_Settings.LT_show and pivot.isLT
switch Trend_Settings.LT_label
'S/I/L Term' =>
lbl := lbl + 'LT'
lbl := lbl + (pivot.isHigh ? 'H' : 'L')
lbl
'High/Low' =>
lbl := lbl + 'LT'
lbl := lbl + (pivot.isHigh ? pivot.isLHigherHigh ? '-HH' : '-LH' : pivot.isLLowerLow ? '-LL' : '-HL')
lbl
=>
if str.length(Trend_Settings.LT_label) == 1
lbl := Trend_Settings.LT_label
lbl
else
array<string> symb = str.split(Trend_Settings.LT_label, '')
lbl := lbl + (pivot.isHigh ? symb.get(1) : symb.get(0))
lbl
lbl
// Calculates and returns the Pivot Point settings
// based on what is configured in the properties window
method OFGetLabelSettings(MarketStructure MS, Pivot pivot) =>
color lbl_color = na
string lbl_text_size = na
color txt_color = na
string lbl_style = na
if MS.settings.ST_show
lbl_color := MS.settings.ST_label_color
lbl_text_size := MS.settings.ST_text_size
txt_color := pivot.isHigh ? MS.settings.ST_color_bull : MS.settings.ST_color_bear
txt_color
if MS.settings.IT_show
if pivot.isIT
lbl_color := MS.settings.IT_label_color
lbl_text_size := MS.settings.IT_text_size
txt_color := pivot.isHigh ? MS.settings.IT_color_bull : MS.settings.IT_color_bear
txt_color
if MS.settings.LT_show
if pivot.isLT
lbl_color := MS.settings.LT_label_color
lbl_text_size := MS.settings.LT_text_size
txt_color := pivot.isHigh ? MS.settings.LT_color_bull : MS.settings.LT_color_bear
txt_color
if MS.settings.ST_show or MS.settings.IT_show or MS.settings.LT_show
lbl_style := pivot.isHigh ? label.style_label_down : label.style_label_up
lbl_style
[lbl_color, lbl_text_size, txt_color, lbl_style, pivot.OfGetLabel()]
// Displays the Pivot label with the proper settings. it is used for both adding the initial
// Pivot and renaming/adjusting it if it is converted from STH to ITH for example
method OFDrawLabel(MarketStructure MS, Pivot pivot) =>
[lbl_color, lbl_text_size, txt_color, lbl_style, lbl] = MS.OFGetLabelSettings(pivot)
if na(pivot.lbl)
pivot.lbl := label.new(pivot.time, pivot.price, xloc = xloc.bar_time, color = lbl_color, size = lbl_text_size, textcolor = txt_color, style = lbl_style, text = lbl)
else
label.set_style(pivot.lbl, lbl_style)
label.set_color(pivot.lbl, lbl_color)
label.set_size(pivot.lbl, lbl_text_size)
label.set_textcolor(pivot.lbl, txt_color)
label.set_text(pivot.lbl, lbl)
MS
// Adds the liquidity lines
method OFDrawLiquidity(MarketStructure MS, Pivot pivot) =>
color liquidity_open_color = pivot.isLT and MS.settings.LT_liquidity_show ? MS.settings.LT_liquidity_open_color : pivot.isIT and MS.settings.IT_liquidity_show ? MS.settings.IT_liquidity_open_color : MS.settings.ST_liquidity_open_color
color liquidity_claimed_color = pivot.isLT and MS.settings.LT_liquidity_show ? MS.settings.LT_liquidity_claimed_color : pivot.isIT and MS.settings.IT_liquidity_show ? MS.settings.IT_liquidity_claimed_color : MS.settings.ST_liquidity_claimed_color
int liquidity_size = pivot.isLT and MS.settings.LT_liquidity_show ? MS.settings.LT_liquidity_size : pivot.isIT and MS.settings.IT_liquidity_show ? MS.settings.IT_liquidity_size : MS.settings.ST_liquidity_size
if MS.settings.ST_liquidity_show or MS.settings.IT_liquidity_show and pivot.isIT or MS.settings.LT_liquidity_show and pivot.isLT
if na(pivot.ln)
pivot.ln := line.new(pivot.time, pivot.price, pivot.claimed ? pivot.time_last : time + (time - time[1]) * MS.settings.extend, pivot.price, xloc = xloc.bar_time, style = of_helper.LineStyle(pivot.claimed ? MS.settings.liquidity_claimed_style : MS.settings.liquidity_open_style), color = pivot.claimed ? liquidity_claimed_color : liquidity_open_color, width = liquidity_size)
pivot.ln
else
line.set_color(pivot.ln, pivot.claimed ? liquidity_claimed_color : liquidity_open_color)
line.set_width(pivot.ln, liquidity_size)
line.set_x2(pivot.ln, pivot.claimed ? pivot.time_last : time + (time - time[1]) * MS.settings.extend)
line.set_style(pivot.ln, of_helper.LineStyle(pivot.claimed ? MS.settings.liquidity_claimed_style : MS.settings.liquidity_open_style))
MS
// Handles the addition of newly discovered ST[H/L] Pivot Point
method OFAddMS(MarketStructure MS, float p_price, int p_time, int p_index, bool isHigh) =>
Pivot pivot = Pivot.new()
pivot.price := p_price
pivot.time := p_time
pivot.isST := true
pivot.index := p_index
MS.ST.unshift(pivot)
if isHigh
pivot.isHigh := true
if MS.STH.size() > 0
Pivot p = MS.STH.first()
if p.price <= p_price
pivot.isSHigherHigh := true
pivot.isSHigherHigh
MS.STH.unshift(pivot)
else
pivot.isLow := true
if MS.STL.size() > 0
Pivot p = MS.STL.first()
if p.price >= p_price
pivot.isSLowerLow := true
pivot.isSLowerLow
MS.STL.unshift(pivot)
MS.OFFindEQ(pivot)
if MS.ST.size() > MAX_BUFFER
Pivot temp = MS.ST.pop()
line.delete(temp.ln)
label.delete(temp.lbl)
MS
// Rechecks the Pivot points and renames the Pivot point from ST to IT
method OFFindIT(MarketStructure MS) =>
if MS.STH.size() > 3
h1 = MS.STH.first()
h2 = MS.STH.get(1)
h3 = MS.STH.get(MS.STH.SkipEQPivot(2))
if h2.price > h3.price and h2.price > h1.price and not h2.isIT
h2.isIT := true
if MS.ITH.size() > 0
Pivot p = MS.ITH.first()
if p.price <= h2.price
h2.isIHigherHigh := true
h2.isIHigherHigh
MS.ITH.unshift(h2)
if MS.STL.size() > 2
l1 = MS.STL.first()
l2 = MS.STL.get(1)
l3 = MS.STL.get(MS.STL.SkipEQPivot(2))
if l2.price < l3.price and l2.price < l1.price and not l2.isIT
l2.isIT := true
if MS.ITL.size() > 0
Pivot p = MS.ITL.first()
if p.price >= l2.price
l2.isILowerLow := true
l2.isILowerLow
MS.ITL.unshift(l2)
MS
// Rechecks the IT Pivot points and renames the Pivot point from IT to LT
method OFFindLT(MarketStructure MS) =>
if MS.ITH.size() > 2
h1 = MS.ITH.first()
h2 = MS.ITH.get(1)
h3 = MS.ITH.get(2)
if h2.price > h3.price and h2.price > h1.price and not h2.isLT
h2.isLT := true
if MS.LTH.size() > 0
Pivot p = MS.LTH.first()
if p.price <= h2.price
h2.isLHigherHigh := true
h2.isLHigherHigh
MS.LTH.unshift(h2)
if MS.ITL.size() > 2
l1 = MS.ITL.first()
l2 = MS.ITL.get(1)
l3 = MS.ITL.get(MS.ITL.SkipEQPivot(2))
if l2.price < l3.price and l2.price < l1.price and not l2.isLT
l2.isLT := true
if MS.LTL.size() > 0
Pivot p = MS.LTL.first()
if p.price >= l2.price
l2.isLLowerLow := true
l2.isLLowerLow
MS.LTL.unshift(l2)
MS
// Checks for ST[H/L] and calls the Add method
method OFFindST(MarketStructure MS) =>
h = high[1] > high[of_helper.SkipEQHigh(2)] and high[1] > high
l = low[1] < low[of_helper.SkipEQLow(2)] and low[1] < low
if h
MS.OFAddMS(high[1], time[1], bar_index[1], true)
if l
MS.OFAddMS(low[1], time[1], bar_index[1], false)
MS
// Checks if liquidity has been swept
method OFCheckClaimed(MarketStructure MS) =>
Pivot claimed = na
if MS.ST.size() > 0
for i = MS.ST.size() - 1 to 0 by 1
pivot = MS.ST.get(i)
if not pivot.claimed
if pivot.isHigh and high > pivot.price or pivot.isLow and low < pivot.price
pivot.claimed := true
pivot.time_last := time
pivot.time_last
for eq in EQs
if not eq.isClaimed
if eq.isHigh
eq.isClaimed := high > eq.price
eq.isClaimed
if eq.isLow
eq.isClaimed := low < eq.price
eq.isClaimed
if eq.isClaimed
eq.claimed_time := time
EQ_claimed.unshift(eq)
if EQ_claimed.size() > Trend_Settings.EQ_max_claimed
EqualLevels t = EQ_claimed.pop()
t.line_eq.delete()
t.line_link.delete()
t.box_link.delete()
if not na(eq.line_eq)
if not eq.isClaimed
eq.line_eq.set_x2(time + (time - time[1]) * MS.settings.extend)
else
eq.line_eq.set_x2(time)
eq.line_eq.set_style(of_helper.LineStyle(Trend_Settings.EQ_claimed_style))
claimed
method OFRenderMS(MarketStructure MS) =>
int add = 0
int claim = 0
for pivot in MS.ST
if pivot.claimed and claim < MS.settings.max_claimed_lines or not pivot.claimed and add < MS.settings.max_lines
MS.OFDrawLiquidity(pivot)
if pivot.claimed
claim := claim + 1
claim
else
add := add + 1
add
if claim == MS.settings.max_claimed_lines and add == MS.settings.max_lines
break
add := 0
for pivot in MS.ST
if MS.settings.ST_show or MS.settings.IT_show and pivot.isIT or MS.settings.LT_show and pivot.isLT and add < MS.settings.max_labels
MS.OFDrawLabel(pivot)
add := add + 1
if add == MS.settings.max_labels
break
//-----------------------------------------------------------------------------
// Process
//-----------------------------------------------------------------------------
if last_bar_index - bar_index < 1000
if barstate.isconfirmed
Term.OFFindST().OFFindIT().OFFindLT()
Term.OFCheckClaimed()
if barstate.islast
Term.OFRenderMS()
//-----------------------------------------------------------------------------
Show all 2,195 lines