Indicator

Indicator

Killzones EUR/GBP - Manuel De Jesus Leiva// This source code is subject to the terms of the Mozilla Public License 2.0 at mozilla.org
// © tradeforopp
//@version=6
indicator("Killzones EUR/GBP - Manuel De Jesus Leiva", "Killzones EUR/GBP - Manuel De Jesus Leiva", true, max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500)
// ---------------------------------------- Constant Functions --------------------------------------------------
get_line_type(_style) =>
switch _style
"Solid" => line.style_solid
"Dotted" => line.style_dotted
"Dashed" => line.style_dashed
get_size(x) =>
switch x
"Auto" => size.auto
"Tiny" => size.tiny
"Small" => size.small
"Normal" => size.normal
"Large" => size.large
"Huge" => size.huge
get_table_pos(pos) =>
switch pos
"Bottom Center" => position.bottom_center
"Bottom Left" => position.bottom_left
"Bottom Right" => position.bottom_right
"Middle Center" => position.middle_center
"Middle Left" => position.middle_left
"Middle Right" => position.middle_right
"Top Center" => position.top_center
"Top Left" => position.top_left
"Top Right" => position.top_right
// ---------------------------------------- Constant Functions --------------------------------------------------
// ---------------------------------------- Inputs --------------------------------------------------
var g_SETTINGS = "Settings"
max_days = input.int(1000, "Session Drawing Limit", 1, tooltip = "Only this many drawings will be kept on the chart, for each selected drawing type (killzone boxes, pivot lines, open lines, etc.). Set to 200 for ~6 months of sessions.", group = g_SETTINGS)
tf_limit = input.timeframe("60", "Timeframe Limit", tooltip = "Drawings will not appear on timeframes greater than or equal to this", group = g_SETTINGS)
gmt_tz = input.string('America/New_York', "Timezone", options = , tooltip = "Note GMT is not adjusted to reflect Daylight Saving Time changes", group = g_SETTINGS)
lbl_size = get_size(input.string('Normal', "Label Size", options = , tooltip = "The size of all labels", group = g_SETTINGS))
txt_color = input.color(color.black, "Text Color", tooltip = "The color of all label and table text", group = g_SETTINGS)
use_cutoff = input.bool(false, "Drawing Cutoff Time", inline = "CO", tooltip = "When enabled, all pivots and open price lines will stop extending at this time", group = g_SETTINGS)
cutoff = input.session("1800-1801", "", inline = "CO", group = g_SETTINGS)
var tf_limit_is_equal_or_more_chart_tf = timeframe.in_seconds('') <= timeframe.in_seconds(tf_limit)
var g_KZ = "Killzones"
// General Killzone Settings
show_kz = input.bool(true, "Show Killzone Boxes", inline = "KZ", group = g_KZ)
show_kz_text = input.bool(false, "Display Text", inline = "KZ", group = g_KZ)
box_transparency = input.int(70, "Box Transparency", 0, 100, group = g_KZ)
text_transparency = input.int(50, "Text Transparency", 0, 100, group = g_KZ)
// ==================== KILLZONE 01 ====================
use_kz01 = input.bool(true, "00:00-01:00", inline = "KZ01", group = g_KZ)
kz01_txt = input.string("00-01", "", inline = "KZ01", group = g_KZ)
kz01 = input.session("0000-0100", "", inline = "KZ01", group = g_KZ)
kz01_color = input.color(color.blue, "", inline = "KZ01", group = g_KZ)
// ==================== KILLZONE 02 ====================
use_kz02 = input.bool(true, "01:00-02:00", inline = "KZ02", group = g_KZ)
kz02_txt = input.string("01-02", "", inline = "KZ02", group = g_KZ)
kz02 = input.session("0100-0200", "", inline = "KZ02", group = g_KZ)
kz02_color = input.color(color.blue, "", inline = "KZ02", group = g_KZ)
// ==================== KILLZONE 03 ====================
use_kz03 = input.bool(true, "02:00-03:00", inline = "KZ03", group = g_KZ)
kz03_txt = input.string("02-03", "", inline = "KZ03", group = g_KZ)
kz03 = input.session("0200-0300", "", inline = "KZ03", group = g_KZ)
kz03_color = input.color(color.blue, "", inline = "KZ03", group = g_KZ)
// ==================== KILLZONE 04 ====================
use_kz04 = input.bool(true, "03:00-04:00", inline = "KZ04", group = g_KZ)
kz04_txt = input.string("03-04", "", inline = "KZ04", group = g_KZ)
kz04 = input.session("0300-0400", "", inline = "KZ04", group = g_KZ)
kz04_color = input.color(color.blue, "", inline = "KZ04", group = g_KZ)
// ==================== KILLZONE 05 ====================
use_kz05 = input.bool(true, "04:00-05:00", inline = "KZ05", group = g_KZ)
kz05_txt = input.string("04-05", "", inline = "KZ05", group = g_KZ)
kz05 = input.session("0400-0500", "", inline = "KZ05", group = g_KZ)
kz05_color = input.color(color.blue, "", inline = "KZ05", group = g_KZ)
// ==================== KILLZONE 06 ====================
use_kz06 = input.bool(true, "05:00-06:00", inline = "KZ06", group = g_KZ)
kz06_txt = input.string("05-06", "", inline = "KZ06", group = g_KZ)
kz06 = input.session("0500-0600", "", inline = "KZ06", group = g_KZ)
kz06_color = input.color(color.blue, "", inline = "KZ06", group = g_KZ)
// ==================== KILLZONE 07 ====================
use_kz07 = input.bool(true, "06:00-07:00", inline = "KZ07", group = g_KZ)
kz07_txt = input.string("06-07", "", inline = "KZ07", group = g_KZ)
kz07 = input.session("0600-0700", "", inline = "KZ07", group = g_KZ)
kz07_color = input.color(color.blue, "", inline = "KZ07", group = g_KZ)
// ==================== KILLZONE 08 ====================
use_kz08 = input.bool(true, "07:00-08:00", inline = "KZ08", group = g_KZ)
kz08_txt = input.string("07-08", "", inline = "KZ08", group = g_KZ)
kz08 = input.session("0700-0800", "", inline = "KZ08", group = g_KZ)
kz08_color = input.color(color.blue, "", inline = "KZ08", group = g_KZ)
// ==================== KILLZONE 09 ====================
use_kz09 = input.bool(true, "08:00-09:00", inline = "KZ09", group = g_KZ)
kz09_txt = input.string("08-09", "", inline = "KZ09", group = g_KZ)
kz09 = input.session("0800-0900", "", inline = "KZ09", group = g_KZ)
kz09_color = input.color(color.blue, "", inline = "KZ09", group = g_KZ)
// ==================== KILLZONE 10 ====================
use_kz10 = input.bool(true, "09:00-10:00", inline = "KZ10", group = g_KZ)
kz10_txt = input.string("09-10", "", inline = "KZ10", group = g_KZ)
kz10 = input.session("0900-1000", "", inline = "KZ10", group = g_KZ)
kz10_color = input.color(color.blue, "", inline = "KZ10", group = g_KZ)
// ==================== KILLZONE 11 ====================
use_kz11 = input.bool(true, "10:00-11:00", inline = "KZ11", group = g_KZ)
kz11_txt = input.string("10-11", "", inline = "KZ11", group = g_KZ)
kz11 = input.session("1000-1100", "", inline = "KZ11", group = g_KZ)
kz11_color = input.color(color.blue, "", inline = "KZ11", group = g_KZ)
// ==================== KILLZONE 12 ====================
use_kz12 = input.bool(true, "11:00-12:00", inline = "KZ12", group = g_KZ)
kz12_txt = input.string("11-12", "", inline = "KZ12", group = g_KZ)
kz12 = input.session("1100-1200", "", inline = "KZ12", group = g_KZ)
kz12_color = input.color(color.blue, "", inline = "KZ12", group = g_KZ)
// ==================== KILLZONE 13 ====================
use_kz13 = input.bool(true, "12:00-13:00", inline = "KZ13", group = g_KZ)
kz13_txt = input.string("12-13", "", inline = "KZ13", group = g_KZ)
kz13 = input.session("1200-1300", "", inline = "KZ13", group = g_KZ)
kz13_color = input.color(color.blue, "", inline = "KZ13", group = g_KZ)
// ==================== KILLZONE 14 ====================
use_kz14 = input.bool(true, "13:00-14:00", inline = "KZ14", group = g_KZ)
kz14_txt = input.string("13-14", "", inline = "KZ14", group = g_KZ)
kz14 = input.session("1300-1400", "", inline = "KZ14", group = g_KZ)
kz14_color = input.color(color.blue, "", inline = "KZ14", group = g_KZ)
// ==================== KILLZONE 15 ====================
use_kz15 = input.bool(true, "14:00-15:00", inline = "KZ15", group = g_KZ)
kz15_txt = input.string("14-15", "", inline = "KZ15", group = g_KZ)
kz15 = input.session("1400-1500", "", inline = "KZ15", group = g_KZ)
kz15_color = input.color(color.blue, "", inline = "KZ15", group = g_KZ)
// ==================== KILLZONE 16 ====================
use_kz16 = input.bool(true, "15:00-16:00", inline = "KZ16", group = g_KZ)
kz16_txt = input.string("15-16", "", inline = "KZ16", group = g_KZ)
kz16 = input.session("1500-1600", "", inline = "KZ16", group = g_KZ)
kz16_color = input.color(color.blue, "", inline = "KZ16", group = g_KZ)
// ==================== KILLZONE 17 ====================
use_kz17 = input.bool(true, "16:00-17:00", inline = "KZ17", group = g_KZ)
kz17_txt = input.string("16-17", "", inline = "KZ17", group = g_KZ)
kz17 = input.session("1600-1700", "", inline = "KZ17", group = g_KZ)
kz17_color = input.color(color.blue, "", inline = "KZ17", group = g_KZ)
// ==================== KILLZONE 18 ====================
use_kz18 = input.bool(true, "17:00-18:00", inline = "KZ18", group = g_KZ)
kz18_txt = input.string("17-18", "", inline = "KZ18", group = g_KZ)
kz18 = input.session("1700-1800", "", inline = "KZ18", group = g_KZ)
kz18_color = input.color(color.blue, "", inline = "KZ18", group = g_KZ)
// ==================== KILLZONE 19 ====================
use_kz19 = input.bool(true, "18:00-19:00", inline = "KZ19", group = g_KZ)
kz19_txt = input.string("18-19", "", inline = "KZ19", group = g_KZ)
kz19 = input.session("1800-1900", "", inline = "KZ19", group = g_KZ)
kz19_color = input.color(color.blue, "", inline = "KZ19", group = g_KZ)
// ==================== KILLZONE 20 ====================
use_kz20 = input.bool(true, "19:00-20:00", inline = "KZ20", group = g_KZ)
kz20_txt = input.string("19-20", "", inline = "KZ20", group = g_KZ)
kz20 = input.session("1900-2000", "", inline = "KZ20", group = g_KZ)
kz20_color = input.color(color.blue, "", inline = "KZ20", group = g_KZ)
// ==================== KILLZONE 21 ====================
use_kz21 = input.bool(true, "20:00-21:00", inline = "KZ21", group = g_KZ)
kz21_txt = input.string("20-21", "", inline = "KZ21", group = g_KZ)
kz21 = input.session("2000-2100", "", inline = "KZ21", group = g_KZ)
kz21_color = input.color(color.blue, "", inline = "KZ21", group = g_KZ)
// ==================== KILLZONE 22 ====================
use_kz22 = input.bool(true, "21:00-22:00", inline = "KZ22", group = g_KZ)
kz22_txt = input.string("21-22", "", inline = "KZ22", group = g_KZ)
kz22 = input.session("2100-2200", "", inline = "KZ22", group = g_KZ)
kz22_color = input.color(color.blue, "", inline = "KZ22", group = g_KZ)
// ==================== KILLZONE 23 ====================
use_kz23 = input.bool(true, "22:00-23:00", inline = "KZ23", group = g_KZ)
kz23_txt = input.string("22-23", "", inline = "KZ23", group = g_KZ)
kz23 = input.session("2200-2300", "", inline = "KZ23", group = g_KZ)
kz23_color = input.color(color.blue, "", inline = "KZ23", group = g_KZ)
// ==================== KILLZONE 24 ====================
use_kz24 = input.bool(true, "23:00-00:00", inline = "KZ24", group = g_KZ)
kz24_txt = input.string("23-00", "", inline = "KZ24", group = g_KZ)
kz24 = input.session("2300-0000", "", inline = "KZ24", group = g_KZ)
kz24_color = input.color(color.blue, "", inline = "KZ24", group = g_KZ)
// ==================== KILLZONE 25 ====================
use_kz25 = input.bool(true, "17:00-21:00", inline = "KZ25", group = g_KZ)
kz25_txt = input.string("17-21", "", inline = "KZ25", group = g_KZ)
kz25 = input.session("1700-2100", "", inline = "KZ25", group = g_KZ)
kz25_color = input.color(color.orange, "", inline = "KZ25", group = g_KZ)
// ==================== KILLZONE 26 ====================
use_kz26 = input.bool(true, "21:00-01:00", inline = "KZ26", group = g_KZ)
kz26_txt = input.string("21-01", "", inline = "KZ26", group = g_KZ)
kz26 = input.session("2100-0100", "", inline = "KZ26", group = g_KZ)
kz26_color = input.color(color.aqua, "", inline = "KZ26", group = g_KZ)
// ==================== KILLZONE 27 ====================
use_kz27 = input.bool(true, "01:00-05:00", inline = "KZ27", group = g_KZ)
kz27_txt = input.string("01-05", "", inline = "KZ27", group = g_KZ)
kz27 = input.session("0100-0500", "", inline = "KZ27", group = g_KZ)
kz27_color = input.color(color.green, "", inline = "KZ27", group = g_KZ)
// ==================== KILLZONE 28 ====================
use_kz28 = input.bool(true, "05:00-09:00", inline = "KZ28", group = g_KZ)
kz28_txt = input.string("05-09", "", inline = "KZ28", group = g_KZ)
kz28 = input.session("0500-0900", "", inline = "KZ28", group = g_KZ)
kz28_color = input.color(color.yellow, "", inline = "KZ28", group = g_KZ)
// ==================== KILLZONE 29 ====================
use_kz29 = input.bool(true, "09:00-13:00", inline = "KZ29", group = g_KZ)
kz29_txt = input.string("09-13", "", inline = "KZ29", group = g_KZ)
kz29 = input.session("0900-1300", "", inline = "KZ29", group = g_KZ)
kz29_color = input.color(color.red, "", inline = "KZ29", group = g_KZ)
// ==================== KILLZONE 30 ====================
use_kz30 = input.bool(true, "13:00-17:00", inline = "KZ30", group = g_KZ)
kz30_txt = input.string("13-17", "", inline = "KZ30", group = g_KZ)
kz30 = input.session("1300-1700", "", inline = "KZ30", group = g_KZ)
kz30_color = input.color(color.purple, "", inline = "KZ30", group = g_KZ)
var g_LABELS = "Killzone Pivots"
show_pivots = input.bool(false, "Show Pivots", inline = "PV", group = g_LABELS)
use_alerts = input.bool(false, "Alert Broken Pivots", inline = "PV", tooltip = "The desired killzones must be enabled at the time that an alert is created, along with the show pivots option, in order for alerts to work", group = g_LABELS)
show_midpoints = input.bool(false, "Show Pivot Midpoints", inline = "mp", group = g_LABELS)
stop_midpoints = input.bool(false, "Stop Once Mitigated", inline = "mp", group = g_LABELS)
show_labels = input.bool(false, "Show Pivot Labels", inline = "LB", tooltip = "Show labels denoting each killzone's high and low. Optionally choose to show the price of each level. Right side will show labels on the right-hand side of the chart until they are reached", group = g_LABELS)
label_price = input.bool(false, "Display Price", inline = "LB", group = g_LABELS)
label_right = input.bool(false, "Right Side", inline = "LB", group = g_LABELS)
ext_pivots = input.string("Until Mitigated", "Extend Pivots...", options = , group = g_LABELS)
ext_which = input.string("All", "...From Which Sessions", options = , group = g_LABELS)
ash_str = input.string("AS.H", "Killzone 1 Labels", inline = "L_AS", group = g_LABELS)
asl_str = input.string("AS.L", "", inline = "L_AS", group = g_LABELS)
loh_str = input.string("LO.H", "Killzone 2 Labels", inline = "L_LO", group = g_LABELS)
lol_str = input.string("LO.L", "", inline = "L_LO", group = g_LABELS)
nah_str = input.string("NYAM.H", "Killzone 3 Labels", inline = "L_NA", group = g_LABELS)
nal_str = input.string("NYAM.L", "", inline = "L_NA", group = g_LABELS)
nlh_str = input.string("NYL.H", "Killzone 4 Labels", inline = "L_NL", group = g_LABELS)
nll_str = input.string("NYL.L", "", inline = "L_NL", group = g_LABELS)
nph_str = input.string("NYPM.H", "Killzone 5 Labels", inline = "L_NP", group = g_LABELS)
npl_str = input.string("NYPM.L", "", inline = "L_NP", group = g_LABELS)
kzp_style = get_line_type(input.string(defval = 'Solid', title = "Pivot Style", options = , inline = "KZP", group = g_LABELS))
kzp_width = input.int(1, "", inline = "KZP", group = g_LABELS)
kzm_style = get_line_type(input.string(defval = 'Dotted', title = "Midpoint Style", options = , inline = "KZM", group = g_LABELS))
kzm_width = input.int(1, "", inline = "KZM", group = g_LABELS)
var g_RNG = "Killzone Range"
show_range = input.bool(false, "Show Killzone Range", tooltip = "Show the most recent ranges of each selected killzone, from high to low", group = g_RNG)
show_range_avg = input.bool(false, "Show Average", tooltip = "Show the average range of each selected killzone", group = g_RNG)
range_avg = input.int(5, "Average Length", 0, tooltip = "This many previous sessions will be used to calculate the average. If there isn't enough data on the current chart, it will use as many sessions as possible", group = g_RNG)
range_pos = get_table_pos(input.string('Top Right', "Table Position", options = , group = g_RNG))
range_size = get_size(input.string('Normal', "Table Size", options = , group = g_RNG))
var g_DWM = "Day - Week - Month"
sep_unlimited = input.bool(false, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_DWM)
alert_HL = input.bool(false, "Alert High/Low Break", tooltip = "Alert when any selected highs and lows are traded through. The desired timeframe's high/low option must be enabled at the time that an alert is created", group = g_DWM)
show_d_open = input.bool(false, "D Open", inline = "DO", group = g_DWM)
dhl = input.bool(false, "High/Low", inline = "DO", tooltip = "", group = g_DWM)
ds = input.bool(false, "Separators", inline = "DO", tooltip = "Mark where a new day begins", group = g_DWM)
d_color = input.color(color.blue, "", inline = "DO", group = g_DWM)
show_w_open = input.bool(false, "W Open", inline = "WO", group = g_DWM)
whl = input.bool(false, "High/Low", inline = "WO", tooltip = "", group = g_DWM)
ws = input.bool(false, "Separators", inline = "WO", tooltip = "Mark where a new week begins", group = g_DWM)
w_color = input.color(#089981, "", inline = "WO", group = g_DWM)
show_m_open = input.bool(false, "M Open", inline = "MO", group = g_DWM)
mhl = input.bool(false, "High/Low", inline = "MO", tooltip = "", group = g_DWM)
ms = input.bool(false, "Separators", inline = "MO", tooltip = "Mark where a new month begins", group = g_DWM)
m_color = input.color(color.red, "", inline = "MO", group = g_DWM)
htf_style = get_line_type(input.string(defval = 'Solid', title = "Style", options = , inline = "D0", group = g_DWM))
htf_width = input.int(1, "", inline = "D0", group = g_DWM)
dow_labels = input.bool(false, "Day of Week Labels", inline = "DOW", group = g_DWM)
dow_yloc = input.string('Bottom', "", options = , inline = "DOW", group = g_DWM)
dow_xloc = input.string('Midnight', "", options = , inline = "DOW", group = g_DWM)
dow_hide_wknd = input.bool(false, "Hide Weekend Labels", group = g_DWM)
var g_OPEN = "Opening Prices"
open_unlimited = input.bool(false, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_OPEN)
use_h1 = input.bool(false, "", inline = "H1", group = g_OPEN)
h1_text = input.string("17:00 H12/H8/H6/H4", "", inline = "H1", group = g_OPEN)
h1 = input.session("1700-1701", "", inline = "H1", group = g_OPEN)
h1_color = input.color(color.black, "", inline = "H1", group = g_OPEN)
use_h2 = input.bool(false, "", inline = "H2", group = g_OPEN)
h2_text = input.string("05:00 H12/H6/H4", "", inline = "H2", group = g_OPEN)
h2 = input.session("0500-0501", "", inline = "H2", group = g_OPEN)
h2_color = input.color(color.black, "", inline = "H2", group = g_OPEN)
use_h3 = input.bool(false, "", inline = "H3", group = g_OPEN)
h3_text = input.string("01:00 H8/H4", "", inline = "H3", group = g_OPEN)
h3 = input.session("0100-0101", "", inline = "H3", group = g_OPEN)
h3_color = input.color(color.black, "", inline = "H3", group = g_OPEN)
use_h4 = input.bool(false, "", inline = "H4", group = g_OPEN)
h4_text = input.string("09:00 H8/H4", "", inline = "H4", group = g_OPEN)
h4 = input.session("0900-0901", "", inline = "H4", group = g_OPEN)
h4_color = input.color(color.black, "", inline = "H4", group = g_OPEN)
use_h5 = input.bool(false, "", inline = "H5", group = g_OPEN)
h5_text = input.string("23:00 H6", "", inline = "H5", group = g_OPEN)
h5 = input.session("2300-2301", "", inline = "H5", group = g_OPEN)
h5_color = input.color(color.black, "", inline = "H5", group = g_OPEN)
use_h6 = input.bool(false, "", inline = "H6", group = g_OPEN)
h6_text = input.string("11:00 H6", "", inline = "H6", group = g_OPEN)
h6 = input.session("1100-1101", "", inline = "H6", group = g_OPEN)
h6_color = input.color(color.black, "", inline = "H6", group = g_OPEN)
use_h7 = input.bool(false, "", inline = "H7", group = g_OPEN)
h7_text = input.string("21:00 H4", "", inline = "H7", group = g_OPEN)
h7 = input.session("2100-2101", "", inline = "H7", group = g_OPEN)
h7_color = input.color(color.black, "", inline = "H7", group = g_OPEN)
use_h8 = input.bool(false, "", inline = "H8", group = g_OPEN)
h8_text = input.string("13:00 H4", "", inline = "H8", group = g_OPEN)
h8 = input.session("1300-1301", "", inline = "H8", group = g_OPEN)
h8_color = input.color(color.black, "", inline = "H8", group = g_OPEN)
hz_style = get_line_type(input.string(defval = 'Dotted', title = "Style", options = , inline = "H0", group = g_OPEN))
hz_width = input.int(1, "", inline = "H0", group = g_OPEN)
var g_VERTICAL = "Timestamps"
v_unlimited = input.bool(false, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_VERTICAL)
use_v1 = input.bool(false, "", inline = "V1", group = g_VERTICAL)
v1 = input.session("0000-0001", "", inline = "V1", group = g_VERTICAL)
v1_color = input.color(color.black, "", inline = "V1", group = g_VERTICAL)
use_v2 = input.bool(false, "", inline = "V2", group = g_VERTICAL)
v2 = input.session("0800-0801", "", inline = "V2", group = g_VERTICAL)
v2_color = input.color(color.black, "", inline = "V2", group = g_VERTICAL)
use_v3 = input.bool(false, "", inline = "V3", group = g_VERTICAL)
v3 = input.session("1000-1001", "", inline = "V3", group = g_VERTICAL)
v3_color = input.color(color.black, "", inline = "V3", group = g_VERTICAL)
use_v4 = input.bool(false, "", inline = "V4", group = g_VERTICAL)
v4 = input.session("1200-1201", "", inline = "V4", group = g_VERTICAL)
v4_color = input.color(color.black, "", inline = "V4", group = g_VERTICAL)
vl_style = get_line_type(input.string(defval = 'Dotted', title = "Style", options = , inline = "V0", group = g_VERTICAL))
vl_width = input.int(1, "", inline = "V0", group = g_VERTICAL)
// ---------------------------------------- Inputs --------------------------------------------------
// ---------------------------------------- Variables & Constants --------------------------------------------------
type kz
string _title
array _box
array _hi_line
array _md_line
array _lo_line
array _hi_label
array _lo_label
array _hi_valid
array _md_valid
array _lo_valid
array _range_store
float _range_current
type hz
array LN
array LB
array CO
type dwm_hl
array hi_line
array lo_line
array hi_label
array lo_label
bool hit_high = false
bool hit_low = false
type dwm_info
string tf
float o = na
float h = na
float l = na
float ph = na
float pl = na
type lines_helper
hz _hz
string h
string h_text
color h_color
initLines() =>
array res = array.new()
if use_h1
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h1, h1_text, h1_color))
if use_h2
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h2, h2_text, h2_color))
if use_h3
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h3, h3_text, h3_color))
if use_h4
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h4, h4_text, h4_color))
if use_h5
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h5, h5_text, h5_color))
if use_h6
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h6, h6_text, h6_color))
if use_h7
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h7, h7_text, h7_color))
if use_h8
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h8, h8_text, h8_color))
res
var array lines = initLines()
type kz_helper
kz _kz
string session
color c
string box_txt
string hi_txt
string lo_txt
initKZ() =>
array res = array.new()
if use_kz01
res.push(kz_helper.new(
kz.new(kz01_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz01, kz01_color, kz01_txt, "KZ01.H", "KZ01.L"
))
if use_kz02
res.push(kz_helper.new(
kz.new(kz02_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz02, kz02_color, kz02_txt, "KZ02.H", "KZ02.L"
))
if use_kz03
res.push(kz_helper.new(
kz.new(kz03_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz03, kz03_color, kz03_txt, "KZ03.H", "KZ03.L"
))
if use_kz04
res.push(kz_helper.new(
kz.new(kz04_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz04, kz04_color, kz04_txt, "KZ04.H", "KZ04.L"
))
if use_kz05
res.push(kz_helper.new(
kz.new(kz05_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz05, kz05_color, kz05_txt, "KZ05.H", "KZ05.L"
))
if use_kz06
res.push(kz_helper.new(
kz.new(kz06_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz06, kz06_color, kz06_txt, "KZ06.H", "KZ06.L"
))
if use_kz07
res.push(kz_helper.new(
kz.new(kz07_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz07, kz07_color, kz07_txt, "KZ07.H", "KZ07.L"
))
if use_kz08
res.push(kz_helper.new(
kz.new(kz08_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz08, kz08_color, kz08_txt, "KZ08.H", "KZ08.L"
))
if use_kz09
res.push(kz_helper.new(
kz.new(kz09_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz09, kz09_color, kz09_txt, "KZ09.H", "KZ09.L"
))
if use_kz10
res.push(kz_helper.new(
kz.new(kz10_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz10, kz10_color, kz10_txt, "KZ10.H", "KZ10.L"
))
if use_kz11
res.push(kz_helper.new(
kz.new(kz11_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz11, kz11_color, kz11_txt, "KZ11.H", "KZ11.L"
))
if use_kz12
res.push(kz_helper.new(
kz.new(kz12_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz12, kz12_color, kz12_txt, "KZ12.H", "KZ12.L"
))
if use_kz13
res.push(kz_helper.new(
kz.new(kz13_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz13, kz13_color, kz13_txt, "KZ13.H", "KZ13.L"
))
if use_kz14
res.push(kz_helper.new(
kz.new(kz14_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz14, kz14_color, kz14_txt, "KZ14.H", "KZ14.L"
))
if use_kz15
res.push(kz_helper.new(
kz.new(kz15_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz15, kz15_color, kz15_txt, "KZ15.H", "KZ15.L"
))
if use_kz16
res.push(kz_helper.new(
kz.new(kz16_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz16, kz16_color, kz16_txt, "KZ16.H", "KZ16.L"
))
if use_kz17
res.push(kz_helper.new(
kz.new(kz17_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz17, kz17_color, kz17_txt, "KZ17.H", "KZ17.L"
))
if use_kz18
res.push(kz_helper.new(
kz.new(kz18_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz18, kz18_color, kz18_txt, "KZ18.H", "KZ18.L"
))
if use_kz19
res.push(kz_helper.new(
kz.new(kz19_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz19, kz19_color, kz19_txt, "KZ19.H", "KZ19.L"
))
if use_kz20
res.push(kz_helper.new(
kz.new(kz20_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz20, kz20_color, kz20_txt, "KZ20.H", "KZ20.L"
))
if use_kz21
res.push(kz_helper.new(
kz.new(kz21_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz21, kz21_color, kz21_txt, "KZ21.H", "KZ21.L"
))
if use_kz22
res.push(kz_helper.new(
kz.new(kz22_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz22, kz22_color, kz22_txt, "KZ22.H", "KZ22.L"
))
if use_kz23
res.push(kz_helper.new(
kz.new(kz23_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz23, kz23_color, kz23_txt, "KZ23.H", "KZ23.L"
))
if use_kz24
res.push(kz_helper.new(
kz.new(kz24_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz24, kz24_color, kz24_txt, "KZ24.H", "KZ24.L"
))
if use_kz25
res.push(kz_helper.new(
kz.new(kz25_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz25, kz25_color, kz25_txt, "KZ25.H", "KZ25.L"
))
if use_kz26
res.push(kz_helper.new(
kz.new(kz26_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz26, kz26_color, kz26_txt, "KZ26.H", "KZ26.L"
))
if use_kz27
res.push(kz_helper.new(
kz.new(kz27_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz27, kz27_color, kz27_txt, "KZ27.H", "KZ27.L"
))
if use_kz28
res.push(kz_helper.new(
kz.new(kz28_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz28, kz28_color, kz28_txt, "KZ28.H", "KZ28.L"
))
if use_kz29
res.push(kz_helper.new(
kz.new(kz29_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz29, kz29_color, kz29_txt, "KZ29.H", "KZ29.L"
))
if use_kz30
res.push(kz_helper.new(
kz.new(kz30_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz30, kz30_color, kz30_txt, "KZ30.H", "KZ30.L"
))
res
var array _kz = initKZ()
var d_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var w_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var m_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var d_info = dwm_info.new("D")
var w_info = dwm_info.new("W")
var m_info = dwm_info.new("M")
t_co = not na(time("", cutoff, gmt_tz))
type ts_helper
string session
array lines
color c
initTS() =>
array res = array.new()
if use_v1
res.push(ts_helper.new(v1, array.new_line(), v1_color))
if use_v2
res.push(ts_helper.new(v2, array.new_line(), v2_color))
if use_v3
res.push(ts_helper.new(v3, array.new_line(), v3_color))
if use_v4
res.push(ts_helper.new(v4, array.new_line(), v4_color))
res
var array ts_data = initTS()
var d_sep_line = array.new_line()
var w_sep_line = array.new_line()
var m_sep_line = array.new_line()
var d_line = array.new_line()
var w_line = array.new_line()
var m_line = array.new_line()
var d_label = array.new_label()
var w_label = array.new_label()
var m_label = array.new_label()
var transparent = #ffffff00
var ext_current = ext_which == 'Most Recent'
var ext_past = ext_pivots == 'Past Mitigation'
update_dwm_info(dwm_info n) =>
if timeframe.change(n.tf)
n.ph := n.h
n.pl := n.l
n.o := open
n.h := high
n.l := low
else
n.h := math.max(high, n.h)
n.l := math.min(low, n.l)
if dhl or show_d_open
update_dwm_info(d_info)
if whl or show_w_open
update_dwm_info(w_info)
if mhl or show_m_open
update_dwm_info(m_info)
// ---------------------------------------- Variables & Constants --------------------------------------------------
// ---------------------------------------- Functions --------------------------------------------------
get_box_color(color c) =>
color.new(c, box_transparency)
get_text_color(color c) =>
color.new(c, text_transparency)
// ---------------------------------------- Functions --------------------------------------------------
// ---------------------------------------- Core Logic --------------------------------------------------
dwm_sep(string tf, bool use, array arr, color col) =>
if use
if timeframe.change(tf)
arr.unshift(line.new(bar_index, high * 1.0001, bar_index, low, style = htf_style, width = htf_width, extend = extend.both, color = col))
if not sep_unlimited and arr.size() > max_days
arr.pop().delete()
dwm_open(string tf, bool use, array lns, array lbls, dwm_info n, color col) =>
if use
if lns.size() > 0
lns.get(0).set_x2(time)
lbls.get(0).set_x(time)
if timeframe.change(tf)
lns.unshift(line.new(time, n.o, time, n.o, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
lbls.unshift(label.new(time, n.o, tf + " OPEN", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
if not sep_unlimited and lns.size() > max_days
lns.pop().delete()
lbls.pop().delete()
dwm_hl(string tf, bool use, dwm_hl hl, dwm_info n, color col) =>
if use
if hl.hi_line.size() > 0
hl.hi_line.get(0).set_x2(time)
hl.lo_line.get(0).set_x2(time)
hl.hi_label.get(0).set_x(time)
hl.lo_label.get(0).set_x(time)
if timeframe.change(tf)
hl.hi_line.unshift(line.new(time, n.ph, time, n.ph, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
hl.lo_line.unshift(line.new(time, n.pl, time, n.pl, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
hl.hi_label.unshift(label.new(time, n.ph, "P" + tf + "H", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
hl.lo_label.unshift(label.new(time, n.pl, "P" + tf + "L", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
hl.hit_high := false
hl.hit_low := false
if not sep_unlimited and hl.hi_line.size() > max_days
hl.hi_line.pop().delete()
hl.lo_line.pop().delete()
hl.hi_label.pop().delete()
hl.lo_label.pop().delete()
if hl.hi_line.size() > 0 and alert_HL
if not hl.hit_high and high > hl.hi_line.get(0).get_y1()
hl.hit_high := true
alert(str.format("Hit P{0}H", tf))
if not hl.hit_low and low < hl.lo_line.get(0).get_y1()
hl.hit_low := true
alert(str.format("Hit P{0}L", tf))
dwm() =>
if tf_limit_is_equal_or_more_chart_tf
// DWM - Separators
dwm_sep("D", ds, d_sep_line, d_color)
dwm_sep("W", ws, w_sep_line, w_color)
dwm_sep("M", ms, m_sep_line, m_color)
// DWM - Open Lines
dwm_open("D", show_d_open, d_line, d_label, d_info, d_color)
dwm_open("W", show_w_open, w_line, w_label, w_info, w_color)
dwm_open("M", show_m_open, m_line, m_label, m_info, m_color)
// DWM - Highs and Lows
dwm_hl("D", dhl, d_hl, d_info, d_color)
dwm_hl("W", whl, w_hl, w_info, w_color)
dwm_hl("M", mhl, m_hl, m_info, m_color)
method vline(ts_helper this) =>
bool t = not na(time("", this.session, gmt_tz))
bool t_prev = not na(time("", this.session, gmt_tz, bars_back = 1))
array arr = this.lines
color col = this.c
if t and not t_prev
arr.unshift(line.new(bar_index, high * 1.0001, bar_index, low, style = vl_style, width = vl_width, extend = extend.both, color = col))
if not v_unlimited
if arr.size() > max_days
arr.pop().delete()
vlines() =>
if tf_limit_is_equal_or_more_chart_tf
for in ts_data
vline(value)
method hz_line(lines_helper this) =>
bool t = not na(time("", this.h, gmt_tz))
bool t_prev = not na(time("", this.h, gmt_tz, bars_back = 1))
hz hz = this._hz
string txt = this.h_text
color col = this.h_color
if t and not t_prev
hz.LN.unshift(line.new(bar_index, open, bar_index, open, style = hz_style, width = hz_width, color = col))
hz.LB.unshift(label.new(bar_index, open, txt, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
array.unshift(hz.CO, false)
if not open_unlimited and hz.LN.size() > max_days
hz.LN.pop().delete()
hz.LB.pop().delete()
hz.CO.pop()
if not t and hz.CO.size() > 0
if not hz.CO.get(0)
hz.LN.get(0).set_x2(bar_index)
hz.LB.get(0).set_x(bar_index)
if (use_cutoff ? t_co : false)
hz.CO.set(0, true)
hz_lines() =>
if tf_limit_is_equal_or_more_chart_tf
for in lines
hz_line(value)
del_kz(kz k) =>
if k._box.size() > max_days
k._box.pop().delete()
if k._hi_line.size() > max_days
k._hi_line.pop().delete()
k._lo_line.pop().delete()
k._hi_valid.pop()
k._lo_valid.pop()
if show_midpoints
k._md_line.pop().delete()
k._md_valid.pop()
if k._hi_label.size() > max_days
k._hi_label.pop().delete()
k._lo_label.pop().delete()
update_price_string(label L, float P) =>
S = L.get_text()
pre = str.substring(S, 0, str.pos(S, " "))
str.trim(pre)
L.set_text(str.format("{0} ({1})", pre, P))
adjust_in_kz(kz kz, bool t) =>
if t
kzBox0 = kz._box.get(0)
kzBox0.set_right(time)
newTop = math.max(kzBox0.get_top(), high)
kzBox0.set_top(newTop)
newBottom = math.min(kzBox0.get_bottom(), low)
kzBox0.set_bottom(newBottom)
kz._range_current := newTop - newBottom
if show_pivots and kz._hi_line.size() > 0
kzHiLine0 = kz._hi_line.get(0)
kzHiLine0.set_x2(time)
if high > kzHiLine0.get_y1()
kzHiLine0.set_xy1(time, high)
kzHiLine0.set_xy2(time, high)
kzLoLine0 = kz._lo_line.get(0)
kzLoLine0.set_x2(time)
if low < kzLoLine0.get_y1()
kzLoLine0.set_xy1(time, low)
kzLoLine0.set_xy2(time, low)
if show_midpoints
kzMidLine0 = kz._md_line.get(0)
kzMidLine0.set_x2(time)
kzMidLine0.set_xy1(time, math.avg(kzHiLine0.get_y2(), kzLoLine0.get_y2()))
kzMidLine0.set_xy2(time, math.avg(kzHiLine0.get_y2(), kzLoLine0.get_y2()))
if show_labels and kz._hi_label.size() > 0
if label_right
kz._hi_label.get(0).set_x(time)
kz._lo_label.get(0).set_x(time)
if high > kz._hi_label.get(0).get_y()
kz._hi_label.get(0).set_xy(time, high)
if label_price
update_price_string(kz._hi_label.get(0), high)
if low < kz._lo_label.get(0).get_y()
kz._lo_label.get(0).set_xy(time, low)
if label_price
update_price_string(kz._lo_label.get(0), low)
adjust_out_kz(kz kz, bool t, bool t_prev) =>
boxCount = kz._box.size()
if not t and boxCount > 0
if t_prev
array.unshift(kz._range_store, kz._range_current)
if kz._range_store.size() > range_avg
kz._range_store.pop()
if show_pivots and boxCount > 0
for i = 0 to boxCount - 1 by 1
if not ext_current or i == 0
kzHiValid = kz._hi_valid.get(i)
if ext_past or kzHiValid
kz._hi_line.get(i).set_x2(time)
if show_labels and label_right
kz._hi_label.get(i).set_x(time)
if kzHiValid and high > kz._hi_line.get(i).get_y1()
if use_alerts and i == 0
alert('Broke ' + kz._title + ' High', alert.freq_once_per_bar)
kz._hi_valid.set(i, false)
if show_labels and label_right
kz._hi_label.get(i).set_style(label.style_label_down)
else if use_cutoff ? t_co : false
kz._hi_valid.set(i, false)
kzLoValid = kz._lo_valid.get(i)
if ext_past or kzLoValid
kz._lo_line.get(i).set_x2(time)
if show_labels and label_right
kz._lo_label.get(i).set_x(time)
if kzLoValid and low < kz._lo_line.get(i).get_y1()
if use_alerts and i == 0
alert("Broke " + kz._title + " Low", alert.freq_once_per_bar)
kz._lo_valid.set(i, false)
if show_labels and label_right
kz._lo_label.get(i).set_style(label.style_label_up)
else if use_cutoff ? t_co : false
kz._lo_valid.set(i, false)
if show_midpoints and not t
if stop_midpoints ? kz._md_valid.get(i) : true
kz._md_line.get(i).set_x2(time)
if kz._md_valid.get(i) and low <= kz._md_line.get(i).get_y1() and high >= kz._md_line.get(i).get_y1()
kz._md_valid.set(i, false)
else
break
method manage_kz(kz_helper this) =>
kz kz = this._kz
c = this.c
string box_txt = this.box_txt
string hi_txt = this.hi_txt
string lo_txt = this.lo_txt
if tf_limit_is_equal_or_more_chart_tf
t = not na(time("", this.session, gmt_tz))
t_prev = not na(time("", this.session, gmt_tz, bars_back = 1))
if t and not t_prev
_c = get_box_color(c)
_t = get_text_color(c)
kz._box.unshift(box.new(time, high, time, low, xloc = xloc.bar_time, border_color = show_kz ? _c : na, bgcolor = show_kz ? _c : na, text = show_kz and show_kz_text ? box_txt : na, text_color = _t))
if show_pivots
kz._hi_line.unshift(line.new(time, high, time, high, xloc = xloc.bar_time, style = kzp_style, color = c, width = kzp_width))
kz._lo_line.unshift(line.new(time, low, time, low, xloc = xloc.bar_time, style = kzp_style, color = c, width = kzp_width))
if show_midpoints
kz._md_line.unshift(line.new(time, math.avg(high, low), time, math.avg(high, low), xloc = xloc.bar_time, style = kzm_style, color = c, width = kzm_width))
array.unshift(kz._md_valid, true)
array.unshift(kz._hi_valid, true)
array.unshift(kz._lo_valid, true)
if show_labels
_hi_txt = label_price ? str.format('{0} ({1})', hi_txt, high) : hi_txt
_lo_txt = label_price ? str.format('{0} ({1})', lo_txt, low) : lo_txt
if label_right
kz._hi_label.unshift(label.new(time, high, _hi_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_left, size = lbl_size))
kz._lo_label.unshift(label.new(time, low, _lo_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_left, size = lbl_size))
else
kz._hi_label.unshift(label.new(time, high, _hi_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_down, size = lbl_size))
kz._lo_label.unshift(label.new(time, low, _lo_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_up, size = lbl_size))
del_kz(kz)
adjust_in_kz(kz, t)
adjust_out_kz(kz, t, t_prev)
for in _kz
manage_kz(value)
dwm()
vlines()
hz_lines()
new_dow_time = dow_xloc == 'Midday' ? time - timeframe.in_seconds("D") / 2 * 1000 : time
new_day = dayofweek(new_dow_time, gmt_tz) != dayofweek(new_dow_time, gmt_tz)
var dow_top = dow_yloc == 'Top'
var saturday = "SATURDAY"
var sunday = "SUNDAY"
var monday = "MONDAY"
var tuesday = "TUESDAY"
var wednesday = "WEDNESDAY"
var thursday = "THURSDAY"
var friday = "FRIDAY"
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 1 and new_day and not dow_hide_wknd, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = sunday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 2 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = monday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 3 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = tuesday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 4 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = wednesday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 5 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = thursday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 6 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = friday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 7 and new_day and not dow_hide_wknd, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = saturday)
get_min_days_stored() =>
store = array.new_int()
for in _kz
int tmpStoreSize = value._kz._range_store.size()
if tmpStoreSize > 0
store.push(tmpStoreSize)
store.min()
method set_table(table tbl, kz kz, int row, string txt, bool t, color col) =>
table.cell(tbl, 0, row, txt, text_size = range_size, bgcolor = get_box_color(col), text_color = txt_color)
table.cell(tbl, 1, row, str.tostring(kz._range_current), text_size = range_size, bgcolor = t ? get_box_color(col) : na, text_color = txt_color)
if show_range_avg
table.cell(tbl, 2, row, str.tostring(kz._range_store.avg()), text_size = range_size, text_color = txt_color)
if show_range and barstate.islast
var tbl = table.new(range_pos, 10, 10, chart.bg_color, chart.fg_color, 2, chart.fg_color, 1)
table.cell(tbl, 0, 0, "Killzone", text_size = range_size, text_color = txt_color)
table.cell(tbl, 1, 0, "Range", text_size = range_size, text_color = txt_color)
if show_range_avg
table.cell(tbl, 2, 0, "Avg (" + str.tostring(get_min_days_stored()) + ")", text_size = range_size, text_color = txt_color)
for in _kz
set_table(tbl, value._kz, index + 1, value.box_txt, not na(time("", value.session, gmt_tz)), value.c)
// ---------------------------------------- Core Logic --------------------------------------------------
Indicator

Killzones US100/SP500 - Manuel De Jesus Leiva// This source code is subject to the terms of the Mozilla Public License 2.0 at mozilla.org
// © tradeforopp
//@version=6
indicator("Killzones US100/SP500 - Manuel De Jesus Leiva", "Killzones US100/SP500 - Manuel De Jesus Leiva", true, max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500)
// ---------------------------------------- Constant Functions --------------------------------------------------
get_line_type(_style) =>
switch _style
"Solid" => line.style_solid
"Dotted" => line.style_dotted
"Dashed" => line.style_dashed
get_size(x) =>
switch x
"Auto" => size.auto
"Tiny" => size.tiny
"Small" => size.small
"Normal" => size.normal
"Large" => size.large
"Huge" => size.huge
get_table_pos(pos) =>
switch pos
"Bottom Center" => position.bottom_center
"Bottom Left" => position.bottom_left
"Bottom Right" => position.bottom_right
"Middle Center" => position.middle_center
"Middle Left" => position.middle_left
"Middle Right" => position.middle_right
"Top Center" => position.top_center
"Top Left" => position.top_left
"Top Right" => position.top_right
// ---------------------------------------- Constant Functions --------------------------------------------------
// ---------------------------------------- Inputs --------------------------------------------------
var g_SETTINGS = "Settings"
max_days = input.int(1000, "Session Drawing Limit", 1, tooltip = "Only this many drawings will be kept on the chart, for each selected drawing type (killzone boxes, pivot lines, open lines, etc.). Set to 200 for ~6 months of sessions.", group = g_SETTINGS)
tf_limit = input.timeframe("60", "Timeframe Limit", tooltip = "Drawings will not appear on timeframes greater than or equal to this", group = g_SETTINGS)
gmt_tz = input.string('America/New_York', "Timezone", options = , tooltip = "Note GMT is not adjusted to reflect Daylight Saving Time changes", group = g_SETTINGS)
lbl_size = get_size(input.string('Normal', "Label Size", options = , tooltip = "The size of all labels", group = g_SETTINGS))
txt_color = input.color(color.black, "Text Color", tooltip = "The color of all label and table text", group = g_SETTINGS)
use_cutoff = input.bool(false, "Drawing Cutoff Time", inline = "CO", tooltip = "When enabled, all pivots and open price lines will stop extending at this time", group = g_SETTINGS)
cutoff = input.session("1800-1801", "", inline = "CO", group = g_SETTINGS)
var tf_limit_is_equal_or_more_chart_tf = timeframe.in_seconds('') <= timeframe.in_seconds(tf_limit)
var g_KZ = "Killzones"
// General Killzone Settings
show_kz = input.bool(true, "Show Killzone Boxes", inline = "KZ", group = g_KZ)
show_kz_text = input.bool(false, "Display Text", inline = "KZ", group = g_KZ)
box_transparency = input.int(70, "Box Transparency", 0, 100, group = g_KZ)
text_transparency = input.int(50, "Text Transparency", 0, 100, group = g_KZ)
// ==================== KILLZONE 01 ====================
use_kz01 = input.bool(true, "00:00-01:00", inline = "KZ01", group = g_KZ)
kz01_txt = input.string("00-01", "", inline = "KZ01", group = g_KZ)
kz01 = input.session("0000-0100", "", inline = "KZ01", group = g_KZ)
kz01_color = input.color(color.blue, "", inline = "KZ01", group = g_KZ)
// ==================== KILLZONE 02 ====================
use_kz02 = input.bool(true, "01:00-02:00", inline = "KZ02", group = g_KZ)
kz02_txt = input.string("01-02", "", inline = "KZ02", group = g_KZ)
kz02 = input.session("0100-0200", "", inline = "KZ02", group = g_KZ)
kz02_color = input.color(color.blue, "", inline = "KZ02", group = g_KZ)
// ==================== KILLZONE 03 ====================
use_kz03 = input.bool(true, "02:00-03:00", inline = "KZ03", group = g_KZ)
kz03_txt = input.string("02-03", "", inline = "KZ03", group = g_KZ)
kz03 = input.session("0200-0300", "", inline = "KZ03", group = g_KZ)
kz03_color = input.color(color.blue, "", inline = "KZ03", group = g_KZ)
// ==================== KILLZONE 04 ====================
use_kz04 = input.bool(true, "03:00-04:00", inline = "KZ04", group = g_KZ)
kz04_txt = input.string("03-04", "", inline = "KZ04", group = g_KZ)
kz04 = input.session("0300-0400", "", inline = "KZ04", group = g_KZ)
kz04_color = input.color(color.blue, "", inline = "KZ04", group = g_KZ)
// ==================== KILLZONE 05 ====================
use_kz05 = input.bool(true, "04:00-05:00", inline = "KZ05", group = g_KZ)
kz05_txt = input.string("04-05", "", inline = "KZ05", group = g_KZ)
kz05 = input.session("0400-0500", "", inline = "KZ05", group = g_KZ)
kz05_color = input.color(color.blue, "", inline = "KZ05", group = g_KZ)
// ==================== KILLZONE 06 ====================
use_kz06 = input.bool(true, "05:00-06:00", inline = "KZ06", group = g_KZ)
kz06_txt = input.string("05-06", "", inline = "KZ06", group = g_KZ)
kz06 = input.session("0500-0600", "", inline = "KZ06", group = g_KZ)
kz06_color = input.color(color.blue, "", inline = "KZ06", group = g_KZ)
// ==================== KILLZONE 07 ====================
use_kz07 = input.bool(true, "06:00-07:00", inline = "KZ07", group = g_KZ)
kz07_txt = input.string("06-07", "", inline = "KZ07", group = g_KZ)
kz07 = input.session("0600-0700", "", inline = "KZ07", group = g_KZ)
kz07_color = input.color(color.blue, "", inline = "KZ07", group = g_KZ)
// ==================== KILLZONE 08 ====================
use_kz08 = input.bool(true, "07:00-08:00", inline = "KZ08", group = g_KZ)
kz08_txt = input.string("07-08", "", inline = "KZ08", group = g_KZ)
kz08 = input.session("0700-0800", "", inline = "KZ08", group = g_KZ)
kz08_color = input.color(color.blue, "", inline = "KZ08", group = g_KZ)
// ==================== KILLZONE 09 ====================
use_kz09 = input.bool(true, "08:00-09:00", inline = "KZ09", group = g_KZ)
kz09_txt = input.string("08-09", "", inline = "KZ09", group = g_KZ)
kz09 = input.session("0800-0900", "", inline = "KZ09", group = g_KZ)
kz09_color = input.color(color.blue, "", inline = "KZ09", group = g_KZ)
// ==================== KILLZONE 10 ====================
use_kz10 = input.bool(true, "09:00-10:00", inline = "KZ10", group = g_KZ)
kz10_txt = input.string("09-10", "", inline = "KZ10", group = g_KZ)
kz10 = input.session("0900-1000", "", inline = "KZ10", group = g_KZ)
kz10_color = input.color(color.blue, "", inline = "KZ10", group = g_KZ)
// ==================== KILLZONE 11 ====================
use_kz11 = input.bool(true, "10:00-11:00", inline = "KZ11", group = g_KZ)
kz11_txt = input.string("10-11", "", inline = "KZ11", group = g_KZ)
kz11 = input.session("1000-1100", "", inline = "KZ11", group = g_KZ)
kz11_color = input.color(color.blue, "", inline = "KZ11", group = g_KZ)
// ==================== KILLZONE 12 ====================
use_kz12 = input.bool(true, "11:00-12:00", inline = "KZ12", group = g_KZ)
kz12_txt = input.string("11-12", "", inline = "KZ12", group = g_KZ)
kz12 = input.session("1100-1200", "", inline = "KZ12", group = g_KZ)
kz12_color = input.color(color.blue, "", inline = "KZ12", group = g_KZ)
// ==================== KILLZONE 13 ====================
use_kz13 = input.bool(true, "12:00-13:00", inline = "KZ13", group = g_KZ)
kz13_txt = input.string("12-13", "", inline = "KZ13", group = g_KZ)
kz13 = input.session("1200-1300", "", inline = "KZ13", group = g_KZ)
kz13_color = input.color(color.blue, "", inline = "KZ13", group = g_KZ)
// ==================== KILLZONE 14 ====================
use_kz14 = input.bool(true, "13:00-14:00", inline = "KZ14", group = g_KZ)
kz14_txt = input.string("13-14", "", inline = "KZ14", group = g_KZ)
kz14 = input.session("1300-1400", "", inline = "KZ14", group = g_KZ)
kz14_color = input.color(color.blue, "", inline = "KZ14", group = g_KZ)
// ==================== KILLZONE 15 ====================
use_kz15 = input.bool(true, "14:00-15:00", inline = "KZ15", group = g_KZ)
kz15_txt = input.string("14-15", "", inline = "KZ15", group = g_KZ)
kz15 = input.session("1400-1500", "", inline = "KZ15", group = g_KZ)
kz15_color = input.color(color.blue, "", inline = "KZ15", group = g_KZ)
// ==================== KILLZONE 16 ====================
use_kz16 = input.bool(true, "15:00-16:00", inline = "KZ16", group = g_KZ)
kz16_txt = input.string("15-16", "", inline = "KZ16", group = g_KZ)
kz16 = input.session("1500-1600", "", inline = "KZ16", group = g_KZ)
kz16_color = input.color(color.blue, "", inline = "KZ16", group = g_KZ)
// ==================== KILLZONE 17 ====================
use_kz17 = input.bool(true, "16:00-17:00", inline = "KZ17", group = g_KZ)
kz17_txt = input.string("16-17", "", inline = "KZ17", group = g_KZ)
kz17 = input.session("1600-1700", "", inline = "KZ17", group = g_KZ)
kz17_color = input.color(color.blue, "", inline = "KZ17", group = g_KZ)
// ==================== KILLZONE 18 ====================
use_kz18 = input.bool(true, "17:00-18:00", inline = "KZ18", group = g_KZ)
kz18_txt = input.string("17-18", "", inline = "KZ18", group = g_KZ)
kz18 = input.session("1700-1800", "", inline = "KZ18", group = g_KZ)
kz18_color = input.color(color.blue, "", inline = "KZ18", group = g_KZ)
// ==================== KILLZONE 19 ====================
use_kz19 = input.bool(true, "18:00-19:00", inline = "KZ19", group = g_KZ)
kz19_txt = input.string("18-19", "", inline = "KZ19", group = g_KZ)
kz19 = input.session("1800-1900", "", inline = "KZ19", group = g_KZ)
kz19_color = input.color(color.blue, "", inline = "KZ19", group = g_KZ)
// ==================== KILLZONE 20 ====================
use_kz20 = input.bool(true, "19:00-20:00", inline = "KZ20", group = g_KZ)
kz20_txt = input.string("19-20", "", inline = "KZ20", group = g_KZ)
kz20 = input.session("1900-2000", "", inline = "KZ20", group = g_KZ)
kz20_color = input.color(color.blue, "", inline = "KZ20", group = g_KZ)
// ==================== KILLZONE 21 ====================
use_kz21 = input.bool(true, "20:00-21:00", inline = "KZ21", group = g_KZ)
kz21_txt = input.string("20-21", "", inline = "KZ21", group = g_KZ)
kz21 = input.session("2000-2100", "", inline = "KZ21", group = g_KZ)
kz21_color = input.color(color.blue, "", inline = "KZ21", group = g_KZ)
// ==================== KILLZONE 22 ====================
use_kz22 = input.bool(true, "21:00-22:00", inline = "KZ22", group = g_KZ)
kz22_txt = input.string("21-22", "", inline = "KZ22", group = g_KZ)
kz22 = input.session("2100-2200", "", inline = "KZ22", group = g_KZ)
kz22_color = input.color(color.blue, "", inline = "KZ22", group = g_KZ)
// ==================== KILLZONE 23 ====================
use_kz23 = input.bool(true, "22:00-23:00", inline = "KZ23", group = g_KZ)
kz23_txt = input.string("22-23", "", inline = "KZ23", group = g_KZ)
kz23 = input.session("2200-2300", "", inline = "KZ23", group = g_KZ)
kz23_color = input.color(color.blue, "", inline = "KZ23", group = g_KZ)
// ==================== KILLZONE 24 ====================
use_kz24 = input.bool(true, "23:00-00:00", inline = "KZ24", group = g_KZ)
kz24_txt = input.string("23-00", "", inline = "KZ24", group = g_KZ)
kz24 = input.session("2300-0000", "", inline = "KZ24", group = g_KZ)
kz24_color = input.color(color.blue, "", inline = "KZ24", group = g_KZ)
// ==================== KILLZONE 25 ====================
use_kz25 = input.bool(true, "17:00-21:00", inline = "KZ25", group = g_KZ)
kz25_txt = input.string("17-21", "", inline = "KZ25", group = g_KZ)
kz25 = input.session("1700-2100", "", inline = "KZ25", group = g_KZ)
kz25_color = input.color(color.orange, "", inline = "KZ25", group = g_KZ)
// ==================== KILLZONE 26 ====================
use_kz26 = input.bool(true, "21:00-01:00", inline = "KZ26", group = g_KZ)
kz26_txt = input.string("21-01", "", inline = "KZ26", group = g_KZ)
kz26 = input.session("2100-0100", "", inline = "KZ26", group = g_KZ)
kz26_color = input.color(color.aqua, "", inline = "KZ26", group = g_KZ)
// ==================== KILLZONE 27 ====================
use_kz27 = input.bool(true, "01:00-05:00", inline = "KZ27", group = g_KZ)
kz27_txt = input.string("01-05", "", inline = "KZ27", group = g_KZ)
kz27 = input.session("0100-0500", "", inline = "KZ27", group = g_KZ)
kz27_color = input.color(color.green, "", inline = "KZ27", group = g_KZ)
// ==================== KILLZONE 28 ====================
use_kz28 = input.bool(true, "05:00-09:00", inline = "KZ28", group = g_KZ)
kz28_txt = input.string("05-09", "", inline = "KZ28", group = g_KZ)
kz28 = input.session("0500-0900", "", inline = "KZ28", group = g_KZ)
kz28_color = input.color(color.yellow, "", inline = "KZ28", group = g_KZ)
// ==================== KILLZONE 29 ====================
use_kz29 = input.bool(true, "09:00-13:00", inline = "KZ29", group = g_KZ)
kz29_txt = input.string("09-13", "", inline = "KZ29", group = g_KZ)
kz29 = input.session("0900-1300", "", inline = "KZ29", group = g_KZ)
kz29_color = input.color(color.red, "", inline = "KZ29", group = g_KZ)
// ==================== KILLZONE 30 ====================
use_kz30 = input.bool(true, "13:00-17:00", inline = "KZ30", group = g_KZ)
kz30_txt = input.string("13-17", "", inline = "KZ30", group = g_KZ)
kz30 = input.session("1300-1700", "", inline = "KZ30", group = g_KZ)
kz30_color = input.color(color.purple, "", inline = "KZ30", group = g_KZ)
var g_LABELS = "Killzone Pivots"
show_pivots = input.bool(false, "Show Pivots", inline = "PV", group = g_LABELS)
use_alerts = input.bool(false, "Alert Broken Pivots", inline = "PV", tooltip = "The desired killzones must be enabled at the time that an alert is created, along with the show pivots option, in order for alerts to work", group = g_LABELS)
show_midpoints = input.bool(false, "Show Pivot Midpoints", inline = "mp", group = g_LABELS)
stop_midpoints = input.bool(false, "Stop Once Mitigated", inline = "mp", group = g_LABELS)
show_labels = input.bool(false, "Show Pivot Labels", inline = "LB", tooltip = "Show labels denoting each killzone's high and low. Optionally choose to show the price of each level. Right side will show labels on the right-hand side of the chart until they are reached", group = g_LABELS)
label_price = input.bool(false, "Display Price", inline = "LB", group = g_LABELS)
label_right = input.bool(false, "Right Side", inline = "LB", group = g_LABELS)
ext_pivots = input.string("Until Mitigated", "Extend Pivots...", options = , group = g_LABELS)
ext_which = input.string("All", "...From Which Sessions", options = , group = g_LABELS)
ash_str = input.string("AS.H", "Killzone 1 Labels", inline = "L_AS", group = g_LABELS)
asl_str = input.string("AS.L", "", inline = "L_AS", group = g_LABELS)
loh_str = input.string("LO.H", "Killzone 2 Labels", inline = "L_LO", group = g_LABELS)
lol_str = input.string("LO.L", "", inline = "L_LO", group = g_LABELS)
nah_str = input.string("NYAM.H", "Killzone 3 Labels", inline = "L_NA", group = g_LABELS)
nal_str = input.string("NYAM.L", "", inline = "L_NA", group = g_LABELS)
nlh_str = input.string("NYL.H", "Killzone 4 Labels", inline = "L_NL", group = g_LABELS)
nll_str = input.string("NYL.L", "", inline = "L_NL", group = g_LABELS)
nph_str = input.string("NYPM.H", "Killzone 5 Labels", inline = "L_NP", group = g_LABELS)
npl_str = input.string("NYPM.L", "", inline = "L_NP", group = g_LABELS)
kzp_style = get_line_type(input.string(defval = 'Solid', title = "Pivot Style", options = , inline = "KZP", group = g_LABELS))
kzp_width = input.int(1, "", inline = "KZP", group = g_LABELS)
kzm_style = get_line_type(input.string(defval = 'Dotted', title = "Midpoint Style", options = , inline = "KZM", group = g_LABELS))
kzm_width = input.int(1, "", inline = "KZM", group = g_LABELS)
var g_RNG = "Killzone Range"
show_range = input.bool(false, "Show Killzone Range", tooltip = "Show the most recent ranges of each selected killzone, from high to low", group = g_RNG)
show_range_avg = input.bool(false, "Show Average", tooltip = "Show the average range of each selected killzone", group = g_RNG)
range_avg = input.int(5, "Average Length", 0, tooltip = "This many previous sessions will be used to calculate the average. If there isn't enough data on the current chart, it will use as many sessions as possible", group = g_RNG)
range_pos = get_table_pos(input.string('Top Right', "Table Position", options = , group = g_RNG))
range_size = get_size(input.string('Normal', "Table Size", options = , group = g_RNG))
var g_DWM = "Day - Week - Month"
sep_unlimited = input.bool(false, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_DWM)
alert_HL = input.bool(false, "Alert High/Low Break", tooltip = "Alert when any selected highs and lows are traded through. The desired timeframe's high/low option must be enabled at the time that an alert is created", group = g_DWM)
show_d_open = input.bool(false, "D Open", inline = "DO", group = g_DWM)
dhl = input.bool(false, "High/Low", inline = "DO", tooltip = "", group = g_DWM)
ds = input.bool(false, "Separators", inline = "DO", tooltip = "Mark where a new day begins", group = g_DWM)
d_color = input.color(color.blue, "", inline = "DO", group = g_DWM)
show_w_open = input.bool(false, "W Open", inline = "WO", group = g_DWM)
whl = input.bool(false, "High/Low", inline = "WO", tooltip = "", group = g_DWM)
ws = input.bool(false, "Separators", inline = "WO", tooltip = "Mark where a new week begins", group = g_DWM)
w_color = input.color(#089981, "", inline = "WO", group = g_DWM)
show_m_open = input.bool(false, "M Open", inline = "MO", group = g_DWM)
mhl = input.bool(false, "High/Low", inline = "MO", tooltip = "", group = g_DWM)
ms = input.bool(false, "Separators", inline = "MO", tooltip = "Mark where a new month begins", group = g_DWM)
m_color = input.color(color.red, "", inline = "MO", group = g_DWM)
htf_style = get_line_type(input.string(defval = 'Solid', title = "Style", options = , inline = "D0", group = g_DWM))
htf_width = input.int(1, "", inline = "D0", group = g_DWM)
dow_labels = input.bool(false, "Day of Week Labels", inline = "DOW", group = g_DWM)
dow_yloc = input.string('Bottom', "", options = , inline = "DOW", group = g_DWM)
dow_xloc = input.string('Midnight', "", options = , inline = "DOW", group = g_DWM)
dow_hide_wknd = input.bool(false, "Hide Weekend Labels", group = g_DWM)
var g_OPEN = "Opening Prices"
open_unlimited = input.bool(false, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_OPEN)
use_h1 = input.bool(false, "", inline = "H1", group = g_OPEN)
h1_text = input.string("18:00 H12/H8/H6/H4", "", inline = "H1", group = g_OPEN)
h1 = input.session("1800-1801", "", inline = "H1", group = g_OPEN)
h1_color = input.color(color.black, "", inline = "H1", group = g_OPEN)
use_h2 = input.bool(false, "", inline = "H2", group = g_OPEN)
h2_text = input.string("06:00 H12/H6/H4", "", inline = "H2", group = g_OPEN)
h2 = input.session("0600-0601", "", inline = "H2", group = g_OPEN)
h2_color = input.color(color.black, "", inline = "H2", group = g_OPEN)
use_h3 = input.bool(false, "", inline = "H3", group = g_OPEN)
h3_text = input.string("10:00 H8/H4", "", inline = "H3", group = g_OPEN)
h3 = input.session("1000-1001", "", inline = "H3", group = g_OPEN)
h3_color = input.color(color.black, "", inline = "H3", group = g_OPEN)
use_h4 = input.bool(false, "", inline = "H4", group = g_OPEN)
h4_text = input.string("02:00 H8/H4", "", inline = "H4", group = g_OPEN)
h4 = input.session("0200-0201", "", inline = "H4", group = g_OPEN)
h4_color = input.color(color.black, "", inline = "H4", group = g_OPEN)
use_h5 = input.bool(false, "", inline = "H5", group = g_OPEN)
h5_text = input.string("00:00 H6", "", inline = "H5", group = g_OPEN)
h5 = input.session("0000-0001", "", inline = "H5", group = g_OPEN)
h5_color = input.color(color.black, "", inline = "H5", group = g_OPEN)
use_h6 = input.bool(false, "", inline = "H6", group = g_OPEN)
h6_text = input.string("12:00 H6", "", inline = "H6", group = g_OPEN)
h6 = input.session("1200-1201", "", inline = "H6", group = g_OPEN)
h6_color = input.color(color.black, "", inline = "H6", group = g_OPEN)
use_h7 = input.bool(false, "", inline = "H7", group = g_OPEN)
h7_text = input.string("22:00 H4", "", inline = "H7", group = g_OPEN)
h7 = input.session("2200-2201", "", inline = "H7", group = g_OPEN)
h7_color = input.color(color.black, "", inline = "H7", group = g_OPEN)
use_h8 = input.bool(false, "", inline = "H8", group = g_OPEN)
h8_text = input.string("14:00 H4", "", inline = "H8", group = g_OPEN)
h8 = input.session("1400-1401", "", inline = "H8", group = g_OPEN)
h8_color = input.color(color.black, "", inline = "H8", group = g_OPEN)
hz_style = get_line_type(input.string(defval = 'Dotted', title = "Style", options = , inline = "H0", group = g_OPEN))
hz_width = input.int(1, "", inline = "H0", group = g_OPEN)
var g_VERTICAL = "Timestamps"
v_unlimited = input.bool(false, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_VERTICAL)
use_v1 = input.bool(false, "", inline = "V1", group = g_VERTICAL)
v1 = input.session("0000-0001", "", inline = "V1", group = g_VERTICAL)
v1_color = input.color(color.black, "", inline = "V1", group = g_VERTICAL)
use_v2 = input.bool(false, "", inline = "V2", group = g_VERTICAL)
v2 = input.session("0800-0801", "", inline = "V2", group = g_VERTICAL)
v2_color = input.color(color.black, "", inline = "V2", group = g_VERTICAL)
use_v3 = input.bool(false, "", inline = "V3", group = g_VERTICAL)
v3 = input.session("1000-1001", "", inline = "V3", group = g_VERTICAL)
v3_color = input.color(color.black, "", inline = "V3", group = g_VERTICAL)
use_v4 = input.bool(false, "", inline = "V4", group = g_VERTICAL)
v4 = input.session("1200-1201", "", inline = "V4", group = g_VERTICAL)
v4_color = input.color(color.black, "", inline = "V4", group = g_VERTICAL)
vl_style = get_line_type(input.string(defval = 'Dotted', title = "Style", options = , inline = "V0", group = g_VERTICAL))
vl_width = input.int(1, "", inline = "V0", group = g_VERTICAL)
// ---------------------------------------- Inputs --------------------------------------------------
// ---------------------------------------- Variables & Constants --------------------------------------------------
type kz
string _title
array _box
array _hi_line
array _md_line
array _lo_line
array _hi_label
array _lo_label
array _hi_valid
array _md_valid
array _lo_valid
array _range_store
float _range_current
type hz
array LN
array LB
array CO
type dwm_hl
array hi_line
array lo_line
array hi_label
array lo_label
bool hit_high = false
bool hit_low = false
type dwm_info
string tf
float o = na
float h = na
float l = na
float ph = na
float pl = na
type lines_helper
hz _hz
string h
string h_text
color h_color
initLines() =>
array res = array.new()
if use_h1
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h1, h1_text, h1_color))
if use_h2
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h2, h2_text, h2_color))
if use_h3
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h3, h3_text, h3_color))
if use_h4
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h4, h4_text, h4_color))
if use_h5
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h5, h5_text, h5_color))
if use_h6
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h6, h6_text, h6_color))
if use_h7
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h7, h7_text, h7_color))
if use_h8
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h8, h8_text, h8_color))
res
var array lines = initLines()
type kz_helper
kz _kz
string session
color c
string box_txt
string hi_txt
string lo_txt
initKZ() =>
array res = array.new()
if use_kz01
res.push(kz_helper.new(
kz.new(kz01_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz01, kz01_color, kz01_txt, "KZ01.H", "KZ01.L"
))
if use_kz02
res.push(kz_helper.new(
kz.new(kz02_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz02, kz02_color, kz02_txt, "KZ02.H", "KZ02.L"
))
if use_kz03
res.push(kz_helper.new(
kz.new(kz03_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz03, kz03_color, kz03_txt, "KZ03.H", "KZ03.L"
))
if use_kz04
res.push(kz_helper.new(
kz.new(kz04_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz04, kz04_color, kz04_txt, "KZ04.H", "KZ04.L"
))
if use_kz05
res.push(kz_helper.new(
kz.new(kz05_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz05, kz05_color, kz05_txt, "KZ05.H", "KZ05.L"
))
if use_kz06
res.push(kz_helper.new(
kz.new(kz06_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz06, kz06_color, kz06_txt, "KZ06.H", "KZ06.L"
))
if use_kz07
res.push(kz_helper.new(
kz.new(kz07_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz07, kz07_color, kz07_txt, "KZ07.H", "KZ07.L"
))
if use_kz08
res.push(kz_helper.new(
kz.new(kz08_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz08, kz08_color, kz08_txt, "KZ08.H", "KZ08.L"
))
if use_kz09
res.push(kz_helper.new(
kz.new(kz09_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz09, kz09_color, kz09_txt, "KZ09.H", "KZ09.L"
))
if use_kz10
res.push(kz_helper.new(
kz.new(kz10_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz10, kz10_color, kz10_txt, "KZ10.H", "KZ10.L"
))
if use_kz11
res.push(kz_helper.new(
kz.new(kz11_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz11, kz11_color, kz11_txt, "KZ11.H", "KZ11.L"
))
if use_kz12
res.push(kz_helper.new(
kz.new(kz12_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz12, kz12_color, kz12_txt, "KZ12.H", "KZ12.L"
))
if use_kz13
res.push(kz_helper.new(
kz.new(kz13_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz13, kz13_color, kz13_txt, "KZ13.H", "KZ13.L"
))
if use_kz14
res.push(kz_helper.new(
kz.new(kz14_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz14, kz14_color, kz14_txt, "KZ14.H", "KZ14.L"
))
if use_kz15
res.push(kz_helper.new(
kz.new(kz15_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz15, kz15_color, kz15_txt, "KZ15.H", "KZ15.L"
))
if use_kz16
res.push(kz_helper.new(
kz.new(kz16_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz16, kz16_color, kz16_txt, "KZ16.H", "KZ16.L"
))
if use_kz17
res.push(kz_helper.new(
kz.new(kz17_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz17, kz17_color, kz17_txt, "KZ17.H", "KZ17.L"
))
if use_kz18
res.push(kz_helper.new(
kz.new(kz18_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz18, kz18_color, kz18_txt, "KZ18.H", "KZ18.L"
))
if use_kz19
res.push(kz_helper.new(
kz.new(kz19_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz19, kz19_color, kz19_txt, "KZ19.H", "KZ19.L"
))
if use_kz20
res.push(kz_helper.new(
kz.new(kz20_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz20, kz20_color, kz20_txt, "KZ20.H", "KZ20.L"
))
if use_kz21
res.push(kz_helper.new(
kz.new(kz21_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz21, kz21_color, kz21_txt, "KZ21.H", "KZ21.L"
))
if use_kz22
res.push(kz_helper.new(
kz.new(kz22_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz22, kz22_color, kz22_txt, "KZ22.H", "KZ22.L"
))
if use_kz23
res.push(kz_helper.new(
kz.new(kz23_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz23, kz23_color, kz23_txt, "KZ23.H", "KZ23.L"
))
if use_kz24
res.push(kz_helper.new(
kz.new(kz24_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz24, kz24_color, kz24_txt, "KZ24.H", "KZ24.L"
))
if use_kz25
res.push(kz_helper.new(
kz.new(kz25_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz25, kz25_color, kz25_txt, "KZ25.H", "KZ25.L"
))
if use_kz26
res.push(kz_helper.new(
kz.new(kz26_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz26, kz26_color, kz26_txt, "KZ26.H", "KZ26.L"
))
if use_kz27
res.push(kz_helper.new(
kz.new(kz27_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz27, kz27_color, kz27_txt, "KZ27.H", "KZ27.L"
))
if use_kz28
res.push(kz_helper.new(
kz.new(kz28_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz28, kz28_color, kz28_txt, "KZ28.H", "KZ28.L"
))
if use_kz29
res.push(kz_helper.new(
kz.new(kz29_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz29, kz29_color, kz29_txt, "KZ29.H", "KZ29.L"
))
if use_kz30
res.push(kz_helper.new(
kz.new(kz30_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz30, kz30_color, kz30_txt, "KZ30.H", "KZ30.L"
))
res
var array _kz = initKZ()
var d_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var w_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var m_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var d_info = dwm_info.new("D")
var w_info = dwm_info.new("W")
var m_info = dwm_info.new("M")
t_co = not na(time("", cutoff, gmt_tz))
type ts_helper
string session
array lines
color c
initTS() =>
array res = array.new()
if use_v1
res.push(ts_helper.new(v1, array.new_line(), v1_color))
if use_v2
res.push(ts_helper.new(v2, array.new_line(), v2_color))
if use_v3
res.push(ts_helper.new(v3, array.new_line(), v3_color))
if use_v4
res.push(ts_helper.new(v4, array.new_line(), v4_color))
res
var array ts_data = initTS()
var d_sep_line = array.new_line()
var w_sep_line = array.new_line()
var m_sep_line = array.new_line()
var d_line = array.new_line()
var w_line = array.new_line()
var m_line = array.new_line()
var d_label = array.new_label()
var w_label = array.new_label()
var m_label = array.new_label()
var transparent = #ffffff00
var ext_current = ext_which == 'Most Recent'
var ext_past = ext_pivots == 'Past Mitigation'
update_dwm_info(dwm_info n) =>
if timeframe.change(n.tf)
n.ph := n.h
n.pl := n.l
n.o := open
n.h := high
n.l := low
else
n.h := math.max(high, n.h)
n.l := math.min(low, n.l)
if dhl or show_d_open
update_dwm_info(d_info)
if whl or show_w_open
update_dwm_info(w_info)
if mhl or show_m_open
update_dwm_info(m_info)
// ---------------------------------------- Variables & Constants --------------------------------------------------
// ---------------------------------------- Functions --------------------------------------------------
get_box_color(color c) =>
color.new(c, box_transparency)
get_text_color(color c) =>
color.new(c, text_transparency)
// ---------------------------------------- Functions --------------------------------------------------
// ---------------------------------------- Core Logic --------------------------------------------------
dwm_sep(string tf, bool use, array arr, color col) =>
if use
if timeframe.change(tf)
arr.unshift(line.new(bar_index, high * 1.0001, bar_index, low, style = htf_style, width = htf_width, extend = extend.both, color = col))
if not sep_unlimited and arr.size() > max_days
arr.pop().delete()
dwm_open(string tf, bool use, array lns, array lbls, dwm_info n, color col) =>
if use
if lns.size() > 0
lns.get(0).set_x2(time)
lbls.get(0).set_x(time)
if timeframe.change(tf)
lns.unshift(line.new(time, n.o, time, n.o, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
lbls.unshift(label.new(time, n.o, tf + " OPEN", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
if not sep_unlimited and lns.size() > max_days
lns.pop().delete()
lbls.pop().delete()
dwm_hl(string tf, bool use, dwm_hl hl, dwm_info n, color col) =>
if use
if hl.hi_line.size() > 0
hl.hi_line.get(0).set_x2(time)
hl.lo_line.get(0).set_x2(time)
hl.hi_label.get(0).set_x(time)
hl.lo_label.get(0).set_x(time)
if timeframe.change(tf)
hl.hi_line.unshift(line.new(time, n.ph, time, n.ph, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
hl.lo_line.unshift(line.new(time, n.pl, time, n.pl, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
hl.hi_label.unshift(label.new(time, n.ph, "P" + tf + "H", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
hl.lo_label.unshift(label.new(time, n.pl, "P" + tf + "L", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
hl.hit_high := false
hl.hit_low := false
if not sep_unlimited and hl.hi_line.size() > max_days
hl.hi_line.pop().delete()
hl.lo_line.pop().delete()
hl.hi_label.pop().delete()
hl.lo_label.pop().delete()
if hl.hi_line.size() > 0 and alert_HL
if not hl.hit_high and high > hl.hi_line.get(0).get_y1()
hl.hit_high := true
alert(str.format("Hit P{0}H", tf))
if not hl.hit_low and low < hl.lo_line.get(0).get_y1()
hl.hit_low := true
alert(str.format("Hit P{0}L", tf))
dwm() =>
if tf_limit_is_equal_or_more_chart_tf
// DWM - Separators
dwm_sep("D", ds, d_sep_line, d_color)
dwm_sep("W", ws, w_sep_line, w_color)
dwm_sep("M", ms, m_sep_line, m_color)
// DWM - Open Lines
dwm_open("D", show_d_open, d_line, d_label, d_info, d_color)
dwm_open("W", show_w_open, w_line, w_label, w_info, w_color)
dwm_open("M", show_m_open, m_line, m_label, m_info, m_color)
// DWM - Highs and Lows
dwm_hl("D", dhl, d_hl, d_info, d_color)
dwm_hl("W", whl, w_hl, w_info, w_color)
dwm_hl("M", mhl, m_hl, m_info, m_color)
method vline(ts_helper this) =>
bool t = not na(time("", this.session, gmt_tz))
bool t_prev = not na(time("", this.session, gmt_tz, bars_back = 1))
array arr = this.lines
color col = this.c
if t and not t_prev
arr.unshift(line.new(bar_index, high * 1.0001, bar_index, low, style = vl_style, width = vl_width, extend = extend.both, color = col))
if not v_unlimited
if arr.size() > max_days
arr.pop().delete()
vlines() =>
if tf_limit_is_equal_or_more_chart_tf
for in ts_data
vline(value)
method hz_line(lines_helper this) =>
bool t = not na(time("", this.h, gmt_tz))
bool t_prev = not na(time("", this.h, gmt_tz, bars_back = 1))
hz hz = this._hz
string txt = this.h_text
color col = this.h_color
if t and not t_prev
hz.LN.unshift(line.new(bar_index, open, bar_index, open, style = hz_style, width = hz_width, color = col))
hz.LB.unshift(label.new(bar_index, open, txt, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
array.unshift(hz.CO, false)
if not open_unlimited and hz.LN.size() > max_days
hz.LN.pop().delete()
hz.LB.pop().delete()
hz.CO.pop()
if not t and hz.CO.size() > 0
if not hz.CO.get(0)
hz.LN.get(0).set_x2(bar_index)
hz.LB.get(0).set_x(bar_index)
if (use_cutoff ? t_co : false)
hz.CO.set(0, true)
hz_lines() =>
if tf_limit_is_equal_or_more_chart_tf
for in lines
hz_line(value)
del_kz(kz k) =>
if k._box.size() > max_days
k._box.pop().delete()
if k._hi_line.size() > max_days
k._hi_line.pop().delete()
k._lo_line.pop().delete()
k._hi_valid.pop()
k._lo_valid.pop()
if show_midpoints
k._md_line.pop().delete()
k._md_valid.pop()
if k._hi_label.size() > max_days
k._hi_label.pop().delete()
k._lo_label.pop().delete()
update_price_string(label L, float P) =>
S = L.get_text()
pre = str.substring(S, 0, str.pos(S, " "))
str.trim(pre)
L.set_text(str.format("{0} ({1})", pre, P))
adjust_in_kz(kz kz, bool t) =>
if t
kzBox0 = kz._box.get(0)
kzBox0.set_right(time)
newTop = math.max(kzBox0.get_top(), high)
kzBox0.set_top(newTop)
newBottom = math.min(kzBox0.get_bottom(), low)
kzBox0.set_bottom(newBottom)
kz._range_current := newTop - newBottom
if show_pivots and kz._hi_line.size() > 0
kzHiLine0 = kz._hi_line.get(0)
kzHiLine0.set_x2(time)
if high > kzHiLine0.get_y1()
kzHiLine0.set_xy1(time, high)
kzHiLine0.set_xy2(time, high)
kzLoLine0 = kz._lo_line.get(0)
kzLoLine0.set_x2(time)
if low < kzLoLine0.get_y1()
kzLoLine0.set_xy1(time, low)
kzLoLine0.set_xy2(time, low)
if show_midpoints
kzMidLine0 = kz._md_line.get(0)
kzMidLine0.set_x2(time)
kzMidLine0.set_xy1(time, math.avg(kzHiLine0.get_y2(), kzLoLine0.get_y2()))
kzMidLine0.set_xy2(time, math.avg(kzHiLine0.get_y2(), kzLoLine0.get_y2()))
if show_labels and kz._hi_label.size() > 0
if label_right
kz._hi_label.get(0).set_x(time)
kz._lo_label.get(0).set_x(time)
if high > kz._hi_label.get(0).get_y()
kz._hi_label.get(0).set_xy(time, high)
if label_price
update_price_string(kz._hi_label.get(0), high)
if low < kz._lo_label.get(0).get_y()
kz._lo_label.get(0).set_xy(time, low)
if label_price
update_price_string(kz._lo_label.get(0), low)
adjust_out_kz(kz kz, bool t, bool t_prev) =>
boxCount = kz._box.size()
if not t and boxCount > 0
if t_prev
array.unshift(kz._range_store, kz._range_current)
if kz._range_store.size() > range_avg
kz._range_store.pop()
if show_pivots and boxCount > 0
for i = 0 to boxCount - 1 by 1
if not ext_current or i == 0
kzHiValid = kz._hi_valid.get(i)
if ext_past or kzHiValid
kz._hi_line.get(i).set_x2(time)
if show_labels and label_right
kz._hi_label.get(i).set_x(time)
if kzHiValid and high > kz._hi_line.get(i).get_y1()
if use_alerts and i == 0
alert('Broke ' + kz._title + ' High', alert.freq_once_per_bar)
kz._hi_valid.set(i, false)
if show_labels and label_right
kz._hi_label.get(i).set_style(label.style_label_down)
else if use_cutoff ? t_co : false
kz._hi_valid.set(i, false)
kzLoValid = kz._lo_valid.get(i)
if ext_past or kzLoValid
kz._lo_line.get(i).set_x2(time)
if show_labels and label_right
kz._lo_label.get(i).set_x(time)
if kzLoValid and low < kz._lo_line.get(i).get_y1()
if use_alerts and i == 0
alert("Broke " + kz._title + " Low", alert.freq_once_per_bar)
kz._lo_valid.set(i, false)
if show_labels and label_right
kz._lo_label.get(i).set_style(label.style_label_up)
else if use_cutoff ? t_co : false
kz._lo_valid.set(i, false)
if show_midpoints and not t
if stop_midpoints ? kz._md_valid.get(i) : true
kz._md_line.get(i).set_x2(time)
if kz._md_valid.get(i) and low <= kz._md_line.get(i).get_y1() and high >= kz._md_line.get(i).get_y1()
kz._md_valid.set(i, false)
else
break
method manage_kz(kz_helper this) =>
kz kz = this._kz
c = this.c
string box_txt = this.box_txt
string hi_txt = this.hi_txt
string lo_txt = this.lo_txt
if tf_limit_is_equal_or_more_chart_tf
t = not na(time("", this.session, gmt_tz))
t_prev = not na(time("", this.session, gmt_tz, bars_back = 1))
if t and not t_prev
_c = get_box_color(c)
_t = get_text_color(c)
kz._box.unshift(box.new(time, high, time, low, xloc = xloc.bar_time, border_color = show_kz ? _c : na, bgcolor = show_kz ? _c : na, text = show_kz and show_kz_text ? box_txt : na, text_color = _t))
if show_pivots
kz._hi_line.unshift(line.new(time, high, time, high, xloc = xloc.bar_time, style = kzp_style, color = c, width = kzp_width))
kz._lo_line.unshift(line.new(time, low, time, low, xloc = xloc.bar_time, style = kzp_style, color = c, width = kzp_width))
if show_midpoints
kz._md_line.unshift(line.new(time, math.avg(high, low), time, math.avg(high, low), xloc = xloc.bar_time, style = kzm_style, color = c, width = kzm_width))
array.unshift(kz._md_valid, true)
array.unshift(kz._hi_valid, true)
array.unshift(kz._lo_valid, true)
if show_labels
_hi_txt = label_price ? str.format('{0} ({1})', hi_txt, high) : hi_txt
_lo_txt = label_price ? str.format('{0} ({1})', lo_txt, low) : lo_txt
if label_right
kz._hi_label.unshift(label.new(time, high, _hi_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_left, size = lbl_size))
kz._lo_label.unshift(label.new(time, low, _lo_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_left, size = lbl_size))
else
kz._hi_label.unshift(label.new(time, high, _hi_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_down, size = lbl_size))
kz._lo_label.unshift(label.new(time, low, _lo_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_up, size = lbl_size))
del_kz(kz)
adjust_in_kz(kz, t)
adjust_out_kz(kz, t, t_prev)
for in _kz
manage_kz(value)
dwm()
vlines()
hz_lines()
new_dow_time = dow_xloc == 'Midday' ? time - timeframe.in_seconds("D") / 2 * 1000 : time
new_day = dayofweek(new_dow_time, gmt_tz) != dayofweek(new_dow_time, gmt_tz)
var dow_top = dow_yloc == 'Top'
var saturday = "SATURDAY"
var sunday = "SUNDAY"
var monday = "MONDAY"
var tuesday = "TUESDAY"
var wednesday = "WEDNESDAY"
var thursday = "THURSDAY"
var friday = "FRIDAY"
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 1 and new_day and not dow_hide_wknd, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = sunday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 2 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = monday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 3 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = tuesday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 4 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = wednesday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 5 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = thursday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 6 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = friday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 7 and new_day and not dow_hide_wknd, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = saturday)
get_min_days_stored() =>
store = array.new_int()
for in _kz
int tmpStoreSize = value._kz._range_store.size()
if tmpStoreSize > 0
store.push(tmpStoreSize)
store.min()
method set_table(table tbl, kz kz, int row, string txt, bool t, color col) =>
table.cell(tbl, 0, row, txt, text_size = range_size, bgcolor = get_box_color(col), text_color = txt_color)
table.cell(tbl, 1, row, str.tostring(kz._range_current), text_size = range_size, bgcolor = t ? get_box_color(col) : na, text_color = txt_color)
if show_range_avg
table.cell(tbl, 2, row, str.tostring(kz._range_store.avg()), text_size = range_size, text_color = txt_color)
if show_range and barstate.islast
var tbl = table.new(range_pos, 10, 10, chart.bg_color, chart.fg_color, 2, chart.fg_color, 1)
table.cell(tbl, 0, 0, "Killzone", text_size = range_size, text_color = txt_color)
table.cell(tbl, 1, 0, "Range", text_size = range_size, text_color = txt_color)
if show_range_avg
table.cell(tbl, 2, 0, "Avg (" + str.tostring(get_min_days_stored()) + ")", text_size = range_size, text_color = txt_color)
for in _kz
set_table(tbl, value._kz, index + 1, value.box_txt, not na(time("", value.session, gmt_tz)), value.c)
// ---------------------------------------- Core Logic --------------------------------------------------
Indicator

AlgoStorm Institutional Session Structure (ISS)AlgoStorm Institutional Session Structure (ISS)
A complete intraday auction-structure engine that maps global session boxes (Asia, London, New York), the Globex overnight range, the Initial Balance with day-type extension targets, the Opening Range, and an automated overnight-inventory classification of the RTH open — directly onto your intraday charts.
The AlgoStorm Institutional Session Structure (ISS) indicator is designed for index futures and intraday traders who read the market through the auction lens: where overnight inventory built, whether the open printed inside or outside that inventory, whether the Initial Balance is containing rotation or the day is extending toward trend, and which session built the reference high or low everyone now trades against. It answers those questions structurally instead of drawing decorative boxes.
TIMEFRAME REQUIREMENT — READ BEFORE LOADING
This is an intraday tool. It refuses to run on 1D charts and above, and the chart timeframe should stay at or below the Opening Range length (the Opening Range and Initial Balance locks resolve at bar granularity). All session windows are DST-aware through a configurable IANA timezone, defaulting to New York time.
Technical Architecture: Fixed-Pool Session Engine
Session-structure indicators commonly rebuild their drawings on every bar, bloating chart performance and churning objects. ISS uses a different execution model:
Per-Session Box Engines: Each session runs its own tracking engine with a private box history. The active box updates its high/low boundary in place as the session develops; boxes older than the history cap (default five days, configurable to twenty) are evicted automatically.
Time-Window Lock Pipeline: The overnight range, Initial Balance, and Opening Range each accumulate in staging registers, then lock permanently the moment their window closes — the overnight at the RTH open, the IB and OR when their configurable minute-windows complete. Locked levels cannot move for the rest of the day.
Extension Mathematics: Extension targets use the classic day-type formula, extension(m) = IB low + m × IB range above the market and IB high − m × IB range below it, with 1.5× and 2.0× defaults. A 1.5× tag means price has traveled 150% of the IB range from the opposite IB boundary.
Zero-Churn Drawing Pool: Every level line and label is created exactly once at initialization and repositioned in place afterward. No per-bar create/delete cycles, no garbage-collection artifacts.
Label Anti-Overlap Engine: Right-edge labels (ON, IB, extensions, OR) are sorted by price each bar and automatically spaced apart whenever two or more sit within a configurable minimum gap (default 0.05% of price). Level lines always stay locked to the true price — only the label text position shifts to stay readable. On by default; fully optional.
Confirmed-Bar Alert Gate: Every alert condition is gated on confirmed bar closes inside RTH. Nothing repaints, and no alert can fire intra-bar and then vanish.
Features & Functionality
Session Boxes: Asia, London, and New York boxes with running high/low, dotted session-open line, and session label. Defaults cover the full sessions (18:00–03:00, 03:00–09:30, 09:30–16:00 New York time); killzone-style alternatives are documented in the input tooltips.
Overnight Range Lock: Globex high/low accumulated through the overnight window and held through the trading day — the reference frame for gap and inventory reads.
Initial Balance + Extension Targets: First 60 minutes of RTH (configurable 15–120) with configurable extension multiples for day-type classification: containment inside the IB, 1.5× tests, or 2× trend extension.
Opening Range: First 15 minutes of RTH (configurable 1–60) — the breakout reference for the open drive.
Overnight Inventory Read: At the RTH open, the engine classifies the print: above the ON high, upper half of the ON range, lower half, or below the ON low — the gap-risk context before the first rotation completes.
Session State Table: Active session, ON high/low, open-vs-ON classification, IB range (shows "forming…" while building, then the locked H/L) with a separate breakout status (inside IB vs. breakout ▲/▼), OR range and status, and which IB extensions have been tested — the whole auction state in one glance.
Alert Suite: Eight conditions — Opening Range breakout up/down, Initial Balance breakout up/down, overnight high/low break, and upper/lower reach of the second IB extension multiple (default 2.0×, trend-day behavior). The first multiple (default 1.5×) is tracked live in the state table but does not carry its own alert.
Honest limitations: ISS is structural context, not a signal system — no entries, no exits, no arrows . Intraday levels draw for the current day only by design; historical context comes from the session boxes. If you also run our Institutional Key Levels (IKL) script, keep IKL's Initial Balance, Opening Range, and Overnight toggles off so nothing double-plots — ISS is the time-anchored view, IKL is the right-edge level strip.
Open-source under CC BY-NC-SA 4.0. Educational tool — not financial advice. Indicator

Zero Noise KillzonesThe Killzones, outlined. Nothing else. The ICT killzones drawn cleanly, with each one's high and low carried forward as levels.
What it does
- Outlines the killzones: Asia (20:00–00:00), London (02:00–05:00), New York AM (09:30–11:00), New York Lunch (12:00–13:00, off by default), and New York PM (13:30–16:00) — all pinned to New York time, so daylight-saving changes are handled automatically on any chart, in any timezone.
- A separate forex set — Asia, London Open, New York Open (07:00–10:00), London Close (10:00–12:00) — off by default, so forex traders have the complete set in one place. NY AM and NY Open overlap by design: different windows that share 30 minutes.
- When a killzone closes, its high and low carry forward as levels. A level stays lit and keeps extending until price trades through it — then it greys out and stops. A sweep counts on the wick: any trade through the level retires it, even if the candle closes back inside. A wick through a level is information — that's the definition, on purpose.
- Days Kept bounds how long anything lives on the chart. Nothing accumulates forever.
- Custom windows: up to seven of your own sessions, any HHMM–HHMM window (midnight wraps handled), in any timezone.
What it deliberately doesn't do
- No signals, no alerts, no arrows — a deliberate omission in the free tools, not an oversight. A killzone high is context, not a trade call. The trade is yours.
Settings
- Killzones: five futures windows plus the four-window forex set, each an independent toggle
- Extend Highs & Lows: Until Swept (levels carry forward) or Session End (outlines only)
- Custom: timezone + up to seven custom windows
- Theme: Auto / Dark / Light — change any swatch and your color wins on every theme
- Line width, fill, tags, Days Kept (1–5), watermark — all optional
Futures, stocks, and FX, on any intraday chart up to 1h — above 5m, windows are rebuilt from 1-minute data for exact alignment.
For informational and educational purposes only — not financial advice. Trading involves substantial risk of loss; past performance does not guarantee future results. Indicator

Session Liquidity Architecture [MQLSoftware]Session Liquidity Architecture reads the trading day as a repeating structure of sessions — and instead of restating fixed session folklore, it measures how the instrument on your chart actually behaves inside that structure.
Most session tools draw boxes and stop there. This indicator adds three algorithmic elements on top of the session-box base, and every number it prints is derived from the chart's own history.
Key Features
Self-calibrating session range model — every completed session range is ranked as a percentile of that session's own trailing distribution. The active session shows a live read: current range, % of its median, and the percentile it has already reached. No pip or point thresholds, no magic numbers — the model adapts to any symbol and timeframe by construction.
Session liquidity state machine — each session's High and Low arm at session close and are then tracked through explicit states: armed → swept → rejected or accepted. A sweep is only registered on a confirmed bar; the rejection read compares the sweep bar's close against the level. Levels that survive until the next same-session open are marked expired.
Measured base rates — the panel reports observed frequencies from the loaded history: how often London actually sweeps the Asia High or Low on this chart, how often New York sweeps the London extremes, and how often price closes back inside after each sweep. These are counted events with the sample size shown (n), not assumptions — and below a minimum sample the panel says "collecting" instead of quoting a percentage.
Three configurable sessions (Asia, London, New York) with per-session IANA timezones, so daylight-saving shifts are handled automatically.
Previous Day High / Low tracked through the same armed → swept state machine.
Day separators, per-session colors, and a compact statistics panel.
Core Concept — what is original here
Session boxes are common. The original contribution of this script is that it treats the session map as a measurement problem :
1. Percentile-ranked session ranges. A "big" or "quiet" session is only meaningful relative to that session's own recent distribution. Ranking the live range against the last N completed ranges of the same session produces a self-calibrating expansion read that works identically on FX majors, indices, or crypto — without any instrument-specific settings.
2. A liquidity state machine instead of static lines. Session extremes are treated as objects with a lifecycle (armed, swept, rejected/accepted, expired). Because state transitions happen only on confirmed bars, the sweep history you see on the chart is exactly the history the statistics are built from.
3. Base rates instead of narratives. The common claims about session behavior ("London takes out the Asia range", "the sweep reverses") become testable numbers here. A counted event is strictly defined: a sweep is the first confirmed-bar break of an armed level while the later session is active, and it counts as "rejected" when the sweep bar closes back inside the level. On some instruments the measured frequencies are strongly asymmetric; on others (for example 24/7 crypto) they hover near a coin flip — and the panel will honestly show you that. The point is to replace assumption with measurement on the exact chart you trade.
Anatomy of the Display
Session boxes — one box per session per day, labelled with the session name; completed boxes append the final range and its percentile (e.g. "LONDON 0.00421 · P63").
Level lines — each session's High/Low extends right from the moment it arms at session close. A red ✕ mark shows where it was swept. Untouched levels turn dotted when they expire at the next same-session open.
PDH / PDL — dashed lines for the previous day's extremes, same sweep marking.
Statistics panel — one row per session (live or last range + percentile, and the state of its levels; states shown during a live session are prefixed "prev" because they belong to the previous cycle), followed by the measured base-rate block with sample sizes.
Notes on Repainting
Sweep events, rejection reads, base-rate counters and all alerts fire on confirmed bars only and do not repaint.
Session boxes, the live range and the live percentile update intrabar while a session is open — they are visual context for the current session, not signals.
No security() calls, no lookahead: everything is computed from the chart's own bars.
Boxes and level lines are drawing objects anchored to past bars by design (a session box spans its session, a level line starts at the bar of the extreme). This affects only how history is displayed, never the event logic.
Typical Analysis Workflow
Check the panel: how much of its typical range has the active session already used? A session at 40% of median is quiet by its own history; one at P90 has already been unusually wide for that session. These numbers describe the distribution so far — they do not predict what the next bar will do.
Watch the armed levels from the prior session and the previous day: they are the objective reference points the state machine is tracking.
When a sweep prints, read the rejection/acceptance tag and compare it with the measured base rate for that exact scenario on this chart.
Configuration
Session hours and timezone per session (defaults: Tokyo 09:00–18:00 JST, London 08:00–17:00 UK, New York 09:30–16:00 ET). Futures/FX traders can widen them or repurpose a slot as a killzone.
Rendering depth, box transparency, day separators, PDH/PDL on/off.
Sweep marks: Minimal (small ✕ text) or Pill, and how many days of marks to keep.
Stats lookback (sessions) for the percentile model; panel position and text size.
Markets and Timeframes
Intraday timeframes only (the script tells you if the chart is not intraday). Best readability from 5m to 1h. Works on FX, indices, futures, stocks and crypto — on 24/7 markets the session definitions matter more than the defaults, so adjust the hours to your venue.
Alerts
Liquidity swept — any session extreme or PDH/PDL taken (confirmed bar). The alert() message names the exact level and outcome, e.g. "EURUSD 60 — liquidity swept: ASIA H (rejected)".
Session range expansion — the active session crossed the 80th percentile of its own history.
Session opened.
This is a visual analytical tool for chart reading and session-structure context. It does not generate buy/sell signals, does not execute trades, and does not provide financial advice. Indicator

OmniSync Sessions📊 OmniSync Sessions
A complete session-based trading toolkit combining Asia/London/NY session levels, first-FVG-per-session tracking with history & mitigation, and multi-timeframe previous high/low levels — all in one indicator.
🌏 Session Highs & Lows
Tracks Asia, London, and NY session highs/lows in real time
Fully customizable session times (built around New York time by default)
Independent master toggle per session — turn any session's lines on/off entirely
Smart decluttering: your current session's own prior-day line automatically hides while you're inside that session (no redundant overlap with the live line), while the other two sessions' most recent levels stay visible
Optional live-updating lines that track to current price, with labels that can stay fixed to avoid clutter near price action
💎 Session-Based Fair Value Gaps
Captures the first FVG of each session — Asia, London, NY — independently
Dotted midpoint (equilibrium) line through every FVG
Configurable history: keep the last N FVGs per session instead of just the current one
Full mitigation tracking — active and historical FVGs fade automatically once price closes through them
Toggle live-extension on/off, or cap FVGs to end at session close
📅 Previous Day / Week / Month Levels
Non-repainting previous D/W/M high & low
Optional 50% Equilibrium line for each timeframe
Fully custom colors per timeframe
⏱️ Intraday & Custom Timeframe Levels
Previous 4H and 1H high/low, independently toggleable
Pick any timeframe you want with a native TF selector — get previous high/low for whatever period matters to you
✍️ Custom Manual Levels
Draw your own high/low levels at any price you choose — great for marking news levels, targets, or manual S/R (Support and Resistance)
⚙️ Built for Reliability
All levels use direct bar-by-bar tracking rather than higher-timeframe lookups — consistent, accurate results across every chart resolution
Every module has its own toggle, so you can run this as a full session/FVG/level suite or strip it down to just what you use
Indicator

Indicator

ICT Killzones | EonMetricsICT Killzones by EonMetrics
WHAT IT DOES
This indicator draws colored boxes on your chart during the hours when big institutional traders are historically most active — these time windows are called "killzones." Each box tracks the highest and lowest price reached while that session is open. When the session ends, the box "seals" and its high and low turn into lines that stretch forward — these are levels price is likely to react to later, so you can see them long after the session is over.
It also draws simple opening-price and high/low lines for the Day, Week and Month, plus the previous day/week/month's numbers. These are shown in the same script as the killzones because they answer the same question at two different zoom levels: "where is the market's attention right now" — killzones tell you that at the hour-by-hour level, and Day/Week/Month tell you that at the bigger-picture level. Traders normally watch both together, which is why they're combined here instead of split into two separate tools.
HOW TO ACTUALLY USE IT (STEP BY STEP)
1. Watch the Asian session box first. It's usually a quiet, narrow range — this range often becomes the "bait" that later sessions test.
2. When London or New York opens, watch for a fast move that quickly reverses (price pokes above/below the recent range and snaps back). This fake-out is common at session opens — the real move often goes the opposite way.
3. Use the high/low lines left behind by earlier sessions as your targets. If price is moving up, the next line above it (an earlier session's high, or the day/week open) is a natural place price may reach and react.
4. Check the Previous Day Close and Week Open lines for context — is today trading above or below yesterday's close? Above or below this week's open? That tells you the bigger picture bias.
5. Turn on "Show Yesterday" if you want to compare today's session ranges against yesterday's.
EVERY SETTING EXPLAINED
Killzones group
- Show Asian / London Open / NY Pre-Market / NY Open / London Close / NY Lunch / NY PM — turns each individual session box on or off. All times are New York time and automatically adjust for Daylight Saving.
- Show Yesterday — also draws all the above boxes for the previous trading day.
Custom Killzone group
- Show Custom KZ — turns on an extra session box that you define yourself (for a market's own open, a prop-firm trading window, or any other hours you want tracked).
- Custom Session — the start-end time of your custom window (24-hour format). If the end time is earlier than the start time, it automatically understands the session crosses midnight.
- Session Timezone — which timezone your custom time window is read in. "Exchange" uses the timezone of whatever symbol you have open.
- Label Name — the name shown on your custom box and its high/low lines.
- Custom Color — the color of your custom box and lines.
Colors group
- One color picker per killzone — sets the fill color of that session's box.
Style group
- Show Box Label — shows the session's name written inside its box while it's still active.
- Show Pivots (H/L) — after a session ends, draws its high and low as lines going forward. Turn this off if you only want the boxes, no forward lines.
- Show Midpoint (50%) — also draws a line at the exact halfway point of each finished session's range.
- Pivot Line Width — how thick the high/low lines are.
- Pivot Style — solid, dashed, or dotted line for the high/low lines.
- Midpoint Style — solid, dashed, or dotted line for the halfway line.
- Show Pivot Labels — shows small text tags (like "London H") at the end of each line.
- After Mitigation — choose what happens once price actually breaks through a level: "Stop at mitigation" freezes the line exactly where it was broken (so you keep a record of where it happened), or "Delete on mitigation" removes it completely for a cleaner chart.
- Alert Broken Pivots — sends you an alert whenever price breaks through one of these levels.
Day / Week / Month group
- Day Open / High-Low, with its own color — today's opening price, and optionally today's high/low, updating live.
- Prev Day Open / Close / High-Low, with its own color — yesterday's numbers, useful as reference points for today.
- The same three lines (Open, High/Low, and Previous versions of each) are repeated for Week and Month.
- Line Style / Line Width — applies to all of the Day/Week/Month lines at once.
- Show Labels — turns the text tags for these lines on or off.
Indicator

Indicator

ICT Sessions & Killzones - Asia London NY + Liquidity[LunqFX]ICT Sessions & Killzones is a modern smart-money session indicator for PulseWire that maps the three global trading sessions — Asia, London and New York — as clean, colour-coded ranges and, unlike most session tools, automatically detects liquidity sweeps: the exact moment price raids a previous session's high or low and rejects it. It turns the daily rhythm of the market — the ICT killzones, session opens, and the liquidity pools left behind — into a clear, actionable map. Works on forex, crypto, indices, futures and gold (XAUUSD), on any intraday timeframe. Built in Pine Script v6. Keywords: ICT, killzones, sessions, Asia session, London session, New York session, liquidity, liquidity sweep, stop hunt, smart money concepts, SMC, session high low, opening range, forex, crypto, day trading, scalping.
◆ WHY SESSIONS MATTER
Price does not move randomly — it moves in sessions. Asia sets the range, London expands it, New York reverses or continues it. The highs and lows each session leaves behind become liquidity pools — resting stop orders that smart money targets. Knowing where those levels are, which session is active, and when a level gets swept is the core of session-based and ICT trading. This tool puts all of that on your chart automatically.
◆ WHAT IT DRAWS
Session boxes — Asia (violet), London (teal) and New York (gold) ranges drawn automatically from each session's high and low, kept across history so you can study the pattern.
Previous-session liquidity levels — the last completed session's high and low extended forward as dashed lines. These are the magnets price hunts next.
Liquidity sweep markers — a compact, colour-coded arrow (▲/▼ with the session code A / L / NY) printed when price wicks beyond a prior session extreme and closes back inside — a real stop-raid / rejection. Hover any marker for the full detail.
Neon gradient candles — turquoise up / magenta down, intensity scaled by momentum.
◆ THE LIVE DASHBOARD
A clean, colour-railed panel that reads the sessions at a glance:
Active session — which session is open right now (● marks any that are live; London and New York overlap in real hours, so both can be active).
Range per session — each session's high–low.
Range in pips — how far each session actually moved.
★ Widest range — the session that dominated the day (the "power session").
Timezone readout, fully themeable, adjustable text size.
◆ HOW IT WORKS
Every bar is assigned to a session from its own timestamp (no repainting from higher-timeframe data). The session's running high and low build the box in real time. When a new session opens, the previous session's extremes are locked in as liquidity levels. A liquidity sweep is flagged only when price trades beyond a prior session's high/low and then closes back inside it — a genuine rejection — so a clean break straight through does not trigger a false signal. This keeps the chart clean and every sweep meaningful.
◆ HOW TO USE IT
Trade the killzones. The London and New York opens produce the biggest, cleanest moves — focus your entries there.
Use prior session highs/lows as targets. Untapped levels act as magnets; price often runs them before reversing.
Fade or follow sweeps. When a sweep prints, the raid has taken liquidity — fade it back into range, or trade the reversal in the opposite direction.
Read the dashboard for context. Know which session is active and which had the widest range before you commit.
Set your times/timezone. Adjust each session's hours and the timezone in the settings to match your market and broker.
Combine with your own market structure, order blocks or bias for higher-probability confluence.
◆ SETTINGS
Session times & colours (Asia / London / New York), timezone, session boxes (soft fill or outline), previous-session levels with adjustable extension, liquidity sweep markers, neon candles, and a dashboard (show/hide, position, text size, background).
◆ ALERTS
Liquidity sweep — fires when any previous-session high or low is swept.
◆ LIMITATIONS
Sessions are an intraday concept — use a 1m to 4h timeframe. On daily or higher the panel shows a reminder and no sessions are drawn.
Default session times are in GMT; set the timezone and hours to match your instrument and broker feed, as session boundaries vary by symbol.
A liquidity sweep shows that a level was raided and rejected — it is context and confluence, not a standalone buy/sell signal.
Session ranges reflect the data of your chart's feed; different brokers can differ slightly.
◆ ORIGINALITY & NON-REPAINTING
Original work — the session engine, the rejection-based liquidity-sweep detection, the previous-session liquidity levels and the dashboard are all my own implementation; no third-party code is used. Sessions and levels are built from each bar's own timestamp with no higher-timeframe lookahead, so a sweep printed on a closed bar stays.
Educational analysis tool, not financial advice. Trading involves risk. Always do your own research and manage risk. © LunqFX. Indicator

Sessionscope [Quantum Algo]Sessionscope is a time-based ICT killzone tool that plots the four primary intraday
killzones, projects the liquidity each one creates, and then measures what happens after
that liquidity is taken. It is built for traders who use Smart Money / ICT concepts and
want session context plus a quantified read on how each killzone behaves on their specific
instrument.
It is not a buy/sell signal system. It is a context and statistics tool.
WHAT IT PLOTS
- Four killzone range boxes, each with its high, low and equilibrium (50%) level.
- Forward-projected session liquidity: each closed killzone's high as buy-side liquidity
(BSL) and its low as sell-side liquidity (SSL).
- Liquidity sweep marks, recolored by outcome (reversal vs continuation).
- The New York midnight open (00:00 ET) as a daily reference line.
- A statistics dashboard summarizing each killzone over the full chart history.
THE FOUR KILLZONES
Default windows, in New York time (America/New_York):
- Asia 20:00 - 00:00
- London Open 02:00 - 05:00
- New York AM 07:00 - 10:00
- London Close 10:00 - 12:00
These are the conventional ICT killzone windows. Because the timezone is anchored to
America/New_York rather than a fixed UTC offset, the windows automatically follow US
daylight saving (EST/EDT) and stay aligned year-round. All four windows, names and colors
are fully editable, so you can shift them, repurpose one (for example to a New York PM or
Silver Bullet window), or adapt the New York window to index timing (08:30 - 11:00) if you
trade futures rather than forex.
SESSION LIQUIDITY (BSL / SSL)
While a killzone is open, the box tracks its developing high and low in real time. When the
killzone closes, those extremes are frozen and projected forward as horizontal liquidity
levels - the high as buy-side liquidity, the low as sell-side liquidity - and extended until
the next instance of that same session. A sweep is registered when price trades through a
projected level (a wick or close beyond the high, or beyond the low). The level can be frozen
at the moment of the sweep to keep the chart clean.
SWEEP OUTCOME ENGINE (the core idea)
Marking a sweep is common. Sessionscope goes further and classifies the outcome of every
sweep:
- High sweep -> REVERSAL if price closes back below the swept high within a configurable
number of bars; otherwise CONTINUATION.
- Low sweep -> REVERSAL if price closes back above the swept low within that window;
otherwise CONTINUATION.
A reversal is the classic ICT liquidity-grab outcome (the level is run, then rejected). A
continuation means the level broke and held (a genuine expansion). Each sweep mark is
recolored to its resolved outcome, and the result feeds the Rev% statistic below. This turns
the qualitative liquidity-grab premise into a measured, per-session number.
NEW YORK MIDNIGHT OPEN
The first traded price after 00:00 America/New_York is captured each day and drawn as a
horizontal reference for that session - a level many ICT traders use as a daily equilibrium
anchor. It is fixed once printed and does not move.
STATISTICS DASHBOARD
For each enabled killzone, accumulated over the entire visible chart history:
- Avg Rng : average high-to-low range of the session, in price.
- xATR : that average range expressed as a multiple of the daily ATR(14), so you can see
which killzone expands most relative to typical daily volatility.
- Swept% : how often the session's liquidity is taken - the share of its high and low
levels that get swept before the session next reopens.
- Rev% : of the sweeps that occurred, how often price reversed back inside the range
(a grab) rather than continuing through (a breakout).
- Bias% : share of sessions that closed above their open (directional tendency).
- n : number of completed sessions in the sample.
Read together, Swept% and Rev% answer two distinct questions: how often does this killzone's
liquidity get run, and when it does, how often does it snap back? Bias% and xATR add the
session's directional lean and its size relative to the day.
HOW IT WORKS (calculation notes)
- Sessions are detected with Pine's time/session function in the chosen timezone; the box
high/low are running extremes of the bars inside each window.
- The daily ATR used for xATR is requested from the 1D timeframe using an offset expression
with lookahead disabled, so it is fully confirmed and constant intraday (no lookahead bias).
- Sweep outcomes are evaluated only on confirmed price relative to fixed, already-closed
levels.
- Statistics are accumulated over the full chart history independently of what is drawn.
- To keep the price scale anchored to current price, only a configurable number of recent
sessions of boxes and levels are kept on the chart (older drawings are removed); this does
not affect the statistics, which always use full history.
WHAT MAKES IT DIFFERENT
Most session and killzone tools stop at colored boxes, session highs/lows, midpoints and a
basic range table. Sessionscope adds the outcome layer: it does not just show that liquidity
was swept, it measures whether each session's sweeps tend to reverse or continue, and colors
them accordingly. The Rev% metric, combined with Swept%, is the part that goes beyond a
standard session-range tool.
SETTINGS
Grouped for clarity: Timezone; Sessions / Killzones (per-session enable, name, window,
color); Box & Level Visuals (boxes, fills, high/low, equilibrium, labels, history cap);
Session Liquidity & Sweeps (projection, sweep marks, freeze-on-sweep, line style, reversal
window, outcome coloring); New York Midnight Open; Statistics Dashboard (position, size);
and Alerts.
HOW TO USE
- Apply on an intraday timeframe; 1m to 1h work best (5m or 15m for clean session structure).
- Mark your higher-timeframe bias first, then use the killzone windows to time entries.
- When a killzone level is swept, read the outcome color and that session's historical Rev%
to gauge whether a reversal back inside the range is the higher-probability path.
- Use xATR to see which session is statistically the most active on your instrument, and
Bias% for its directional lean.
REPAINTING
Boxes and the live high/low update in real time while the current session is forming - this
is expected real-time behavior, not lookahead. Once a session closes, its levels are fixed;
sweeps are detected on price crossing those fixed levels; and an outcome, once resolved on a
closed bar, does not change. No lookahead is used anywhere in the script.
CONCEPTS AND CREDIT
The concepts used here - killzones, buy-side and sell-side liquidity, liquidity sweeps, the
midnight open, and premium/discount equilibrium - originate with the Inner Circle Trader
(Michael J. Huddleston) and the wider Smart Money Concepts / price-action community, where
they are taught and discussed openly. The session window defaults follow the killzone times
commonly used by that community. All code in this script - the session detection, liquidity
projection, sweep-outcome classification and statistics engine - is written independently and
reuses no third-party code. It is published open-source so anyone can read, verify and modify
it under PulseWire's House Rules.
DISCLAIMER
This script is provided for educational and informational purposes only. It is not financial,
investment or trading advice, and it does not produce buy or sell recommendations. All
statistics are descriptive measurements of historical data on the current chart and do not
predict future price behavior; past behavior of a session or level does not guarantee future
results. Trading involves substantial risk of loss. You are solely responsible for your own
decisions and risk management. Test any tool thoroughly on your own markets and timeframes
before relying on it. Indicator

ICT Sessions & Killzones - VWAP + Asia Mid [Dots3Red]█ ICT SESSIONS & KILLZONES — VWAP + ASIA MID
This script visualizes the four major forex trading sessions alongside the four ICT killzone windows, with three analytical additions that most session scripts do not include: a per-session VWAP line, a Daily Open reference, and an Asia range midpoint that extends forward into the London and New York sessions.
It works on intraday timeframes. The number of historical session days displayed is configurable.
█ SESSIONS
Four sessions are available, each independently toggleable:
• Tokyo — 09:00–18:00 Asia/Tokyo
• London — 08:00–17:00 Europe/London
• New York — 09:30–16:00 America/New_York
• Sydney — 07:00–16:00 Australia/Sydney (off by default)
Each session draws a high/low line pair with a soft glow layer behind it, a midpoint dotted line at 50% of the session range, and optional quartile lines at 25% and 75%. A semi-transparent fill box covers the active session range and fades when the session closes. Historical sessions are preserved as lighter boxes and lines, controlled by the Historical Sessions (days) setting.
Session labels are positioned at the horizontal midpoint of the session and display the session name, current range in points, the range as a percentage of ATR(14), and the live VWAP value.
When two sessions are active simultaneously — London and New York from approximately 13:00–17:00 UTC, or Tokyo and London around 07:00–09:00 UTC — an overlap box is drawn over that window in a distinct color.
█ ICT KILLZONES
All four ICT killzone windows are implemented, each individually toggleable under a master switch:
• Asia KZ — 20:00–00:00 America/New_York
• London Open KZ — 02:00–05:00 America/New_York
• NY Open KZ — 07:00–10:00 America/New_York
• London Close KZ — 10:00–12:00 America/New_York
Each killzone box uses a dotted border when closed and switches to a solid border while the window is currently active. This makes it immediately clear at a glance whether a killzone is live or historical.
Most published session scripts include only two killzones (London Open and NY Open). The Asia and London Close windows are included here because they are part of the complete ICT framework — the Asia killzone in particular is where a significant portion of daily liquidity is engineered before the London session opens.
█ SESSION VWAP
A VWAP line is calculated independently for each session. It resets to zero at each session open and accumulates using the standard (High + Low + Close) / 3 × Volume formula throughout the session. This is not a daily or weekly VWAP — it is a session-scoped VWAP that resets with each new Tokyo, London, and New York open.
Price above the session VWAP indicates the session is currently net bullish in terms of volume-weighted price. Price below indicates net bearish. The VWAP value is also shown in the live metrics table and in the session label.
Sydney VWAP is not calculated as volume data on that session is generally unreliable outside of ASX-listed instruments.
█ DAILY OPEN LINE
A horizontal line is drawn at the price level at which the new day opened — specifically at midnight New York time (00:00 America/New_York). This corresponds to the ICT "00:00 line" or daily open reference, which is used in ICT methodology as a key intraday reference level for assessing whether price is trading at a premium or discount relative to the daily range.
The line extends forward through the trading day and refreshes at each midnight NY transition.
█ ASIA RANGE MIDPOINT EXTENSION
When the Tokyo session closes, the midpoint of its high-low range is calculated and projected forward as a dashed line into the London and New York sessions. This level — the 50% point of the Asian range — is referenced in ICT methodology as a key intraday equilibrium. London and New York sessions frequently interact with this level before establishing directional bias.
This extension is drawn automatically and requires no manual input. It is toggled by the Asia Range Mid Extension setting.
█ LIVE METRICS TABLE
A table in the corner of the chart displays eight columns for each active session:
• SESSION — name, color-coded to the session
• STATUS — ACTIVE or CLOSED
• RANGE (PTS) — current range in price ticks
• % ATR — range expressed as a percentage of ATR(14)
• VWAP DEV — current close deviation from session VWAP in percent (green = above, red = below)
• VS PREV % — current session range versus the equivalent previous session's range (green = larger, red = smaller)
• HIGH / LOW — current session extremes
The bottom row shows whether a session overlap is currently active.
█ HISTORICAL DISPLAY
The Historical Sessions (days) input controls how many past session blocks remain visible. The script uses a millisecond-based time window rather than a bar count, so the lookback is stable across different timeframes. Setting this to 1 shows only the current day's sessions. Setting it to 5 retains the last five days. Objects beyond the limit are deleted automatically to manage Pine's drawing object limits.
█ ALERTS
Eleven alert conditions are available:
• Tokyo, London, New York session opens and closes (6 alerts)
• Asia KZ, London Open KZ, NY Open KZ, London Close KZ starts (4 alerts)
• London + New York overlap start (1 alert)
█ NOTES
• Designed for intraday timeframes. Most useful at 5-minute through 1-hour.
• Session times adjust automatically for daylight saving time because timezone identifiers (America/New_York, Europe/London, etc.) are used rather than fixed UTC offsets.
• The Tokyo session uses Asia/Tokyo exchange hours (09:00–18:00). Forex traders who prefer the broader Asian session window (00:00–09:00 UTC) can adjust the time string in the source code.
• All session boxes and killzone boxes are gated to the historical window. Objects outside the configured lookback are not drawn, which keeps performance stable on lower timeframes with many bars.
█ DISCLAIMER
This is a visualization tool for session timing and reference levels. It does not generate trade signals and does not constitute financial advice. Past price behavior within or around session windows does not predict future results. Indicator

Sessions + Killzones [HermesCore]WHAT THIS INDICATOR DOES
Sessions + Killzones tracks the three desk sessions: Asia, London and New York, plus an optional custom window. While a session is open you see it as a live box. When it closes, its high and low become levels. Each level gets a simple 0 to 6 quality score, and from then on the script tracks what price does with it: swept, run, or held.
Every outcome feeds a statistics engine. It answers the core question of this script: what does the next session usually do with the levels of the previous one? Measured on your own chart, with sample sizes shown.
Killzones are the windows where institutional activity concentrates, around the desk opens. They render as background shading, set in New York time per ICT convention (Inner Circle Trader, the school this session vocabulary comes from). The dashboard shows which session and which killzone are active right now, each with a countdown. It also covers the daily window where nothing is open. I gave that window a name: the Dead Zone.
WHY IT IS DIFFERENT
Most session indicators draw boxes and stop. The few that score sessions usually hide how the score works. My rules are:
- A level gets its score at birth and the score never changes. It is built only from facts about how the session formed: range, volume, how clean the extreme was, and confluence with key levels. What happens later is shown by the lifecycle markings, not by changing the score.
- A sweep and a run are two different events. A wick beyond the level that closes back inside is a sweep. That is information: stops were taken and price came back. A close beyond the level plus a 0.1 ATR buffer (Average True Range, a standard volatility measure) is a run. The level is consumed.
- The statistics are counted honestly. A pair like "AS.H in LDN" only counts what happens while London is actually open. Levels that die before their judging session opens are not counted at all. The dashboard shows the n for every pair, so you always see how much evidence sits behind a percentage.
- Sessions are boxes, because their range matters: it becomes levels. Killzones are background shading, because only their timing matters. Two layers, two visual languages.
- Everything updates on confirmed bars only. No intrabar flicker. No levels that appear and disappear within the same candle.
HOW TO READ THE CHART
- Live session box: bright, thick border, session tag in the corner. Closed boxes fade into quiet history.
- Session levels: horizontal lines starting at the bar that set the extreme. A label like "LDN.H A S:5" reads: London session high, grade A, score 5. The abbreviations: AS is Asia, LDN is London, NY is New York, .H is the high, .L is the low.
- Gold color with a soft glow and larger text: the grade is A or S. Those are the premium sessions.
- Thick border on a level: it was swept. The label gets a "swept" suffix.
- Grey line without text: the level was run. It stays as quiet history, or you can have runs deleted.
- Levels expire when the next session of the same type closes. Yesterday's Asia high stops mattering once today's Asia delivers a fresh one.
- Killzone shading: vertical background bands for Asia, London, NY AM, and optionally London Close. All set in New York time.
- Dotted horizontal line: the midnight open at 00:00 New York.
- Dotted vertical lines to the right of price: the projected next open of each session, in session color. The chart version of the dashboard countdown. They respect the Weekdays Only filter.
- Neutral horizontal lines: previous day high and low (PDH, PDL) and previous week high and low (PWH, PWL), always from the last completed day and week. When a daily and a weekly level are equal they merge into one line with a combined label.
- Session midlines (CE, consequent encroachment, simply the middle of the range): dotted at the middle of each closed session, turning solid gold with a label like "AS CE" on the first touch. On by default.
- Killzone range lines: when a killzone closes, its high and low freeze as dashed lines in the killzone color. They carry no score, no lifecycle and no statistics. They are pure context and expire when the next killzone of the same type closes. On by default.
THE SCORE
Every component is measured at session close against the average of the last 20 sessions of the same type. Asia is always compared with Asia, London with London.
- Range: the session range is more than 1.2x its own average, +2
- Volume: the session volume is above its own average, +2
- Clean extreme: the high or low was set in the first half of the session and never revisited within 0.1 ATR, +1
- Key confluence: the level lies within 0.25 ATR of PDH, PDL, PWH or PWL, +1
Grades: S (6), A (5), B (4), C (3), D (0 to 2). There is no strength filter on purpose. A day produces at most six levels, which is scarce enough to show them all and let the grade speak.
SEQUENCE STATISTICS
Six pairs, following the natural hand-off: Asia levels are judged by London, London levels by New York, New York levels by the next Asia. For each pair the dashboard shows the swept share, run share, held share, and n, the number of judged levels behind those percentages. Held means the judging session closed without resolving the level. The optional custom session gets the full level lifecycle but stays out of these statistics.
This is regime information. If "AS.H in LDN" shows 36 percent swept while the lifetime base is 45, London is currently respecting Asia highs more than usual. An alert can warn you when a pair crosses 70 percent swept.
THE DEAD ZONE
Between the New York close and the Asia open, nothing is open. I named that window the Dead Zone, and it does real work here. Liquidity is thinnest there. A New York level that gets run inside the Dead Zone disappears before Asia ever gets to judge it. That is why the New York pairs always show a smaller n: n only counts levels that survived until their judging session opened. The dashboard names the Dead Zone when you are in it and counts down to the next open. Neutral shading, on by default, makes it visible on the chart. It is defined as "no session live", so it stays correct through every daylight saving (DST) change, and with Weekdays Only on, the whole weekend becomes one long Dead Zone.
DASHBOARD
Session now with a closing countdown, or Dead Zone with an opening countdown. Range and volume of each session against its own average, live sessions marked. The six pairs with percentages and n. Active level count, the lifetime swept versus run ratio, and Killzone now with its own countdown. Heat bars are proportional everywhere.
HOW I USE IT
My preferred timeframes, in order:
- 15m is the home base. Sessions are 30 plus bars wide, so the clean extreme component means something. The 09:30 New York open lands exactly on a bar. And the chart loads the most history, which gives the statistics their highest n.
- 5m is the execution frame. Sweeps and runs resolve on bar closes, so 5m shows the fight around a level in finer detail, and killzones become readable blocks. The cost is sample size: the statistics run on roughly a third of the history, so I treat those percentages as indicative and keep the regime read on 15m.
- 1h works but is the edge case. Hourly bars cut off the 09:30 New York open, and a six bar session makes the score coarse. Above 1h the script draws nothing on purpose.
On 15m I read the dashboard first: which session is live, how its range compares with average, and what the pair stats say about the current regime. Levels graded A or S from a session that expanded on volume are the ones I treat as real liquidity references, especially with key confluence. Then I watch how the next session treats them. A sweep, thick border, stops taken and price rejected, is a different trade than a clean run. I drop to 5m for execution around those levels and during killzones. I do not use this above 1h, and the script will tell you the same.
The way I think about it: session highs and lows are liquidity pools with a clock attached. Equal highs can form anywhere, but a session extreme tells you which desk made the level, when it stops being defended, and, through the statistics, what usually happens to it next.
SETTINGS THAT MATTER
- Sessions: four windows, each with its own IANA timezone (Asia/Tokyo, Europe/London, America/New_York by default). These are real timezone names, not UTC offsets, so daylight saving is handled automatically. The sessions simply follow their local clocks.
- Weekdays Only: off by default. Crypto trades the weekend, and weekend sessions usually grade D by themselves on thin range and volume. Turn this on and everything restricts to Monday through Friday: the weekend becomes one long Dead Zone, Friday New York levels wait for Monday Asia, and the countdown switches to a days format.
- Max Session Boxes: 42 keeps two weeks of session history for a zoomed-out view, 6 keeps two days for intraday focus.
- Run Levels Become: greyed history or deleted. Your choice of how loud the past is.
- Focus Fade: levels more than 6 ATR away from price render dimmed, gold glow included, so your eye goes to what is in play.
- Killzones: four windows in New York time, each with its own color. London Close is off by default. Killzone Range Lines adds the frozen high and low of each completed killzone as dashed lines.
- Timeframe guard: above 60 minutes the script draws nothing and says why. This is an intraday tool, and pretending otherwise would only produce misleading levels.
ALERTS
Session Opened, Session Closed, New A/S Session Level, Session Level Swept, Session Level Run, Killzone Started, Session Midline Tapped, Sweep Rate Threshold (a pair crossing 70 percent swept with n of at least 10).
CALCULATION DETAILS
- All state changes happen on confirmed bars. Sweeps, runs and statistics never repaint within a bar.
- Sessions use Pine session strings with full IANA timezone support. Without a day filter, Pine fires sessions on all seven days. That is correct for 24/7 markets, and it is what the Weekdays Only toggle changes.
- The rolling averages for range and volume use the last 20 completed sessions of the same type, calculated before the current session is added. A session is never compared with itself.
- A sweep needs a wick beyond the level with the close back inside the 0.1 ATR buffer. A run needs a close beyond the level plus the buffer. A first sweep marks the level, a later run still resolves it.
- Outcomes are only recorded while the judging session is open. A level that survives its judge counts as held at the judge's close.
- The statistics are computed from the bars your chart loads. They reload per chart timeframe. 15m loads the most history and gives the highest n. On 5m the same engine runs on roughly a third of the sample, treat those percentages as indicative.
HONEST LIMITATIONS
- The statistics describe the past, they do not predict. They tell you what this chart did over the loaded history, not what it will do next.
- n differs per pair by design. Levels run inside the Dead Zone leave the population before their judging session opens, which is why the New York pairs carry a smaller n. That is honest counting, not a bug.
- Statistics depend on the chart timeframe and the loaded history, so two timeframes show different percentages. Neither is wrong, they measure different samples.
- With Weekdays Only off, weekend sessions are part of the statistics. With it on, both n and the percentages change, because you measure a different market. Neither setting is the truth, they answer different questions.
- Scores compare a session with its own rolling history, so the first 20 sessions of each type on a fresh chart carry less reliable scores while the averages fill up.
- On 1h charts bar alignment can cut off session opens (there is no 09:30 bar on an hourly chart). That is part of why the timeframe guard sits at 60 minutes.
ORIGINALITY
The session and killzone concepts come from the public ICT vocabulary and from years of session-based intraday trading. Every line of code, the scoring system, the sweep versus run grammar, the judged-while-open statistics engine, the Dead Zone concept and the visual language are my own work.
Questions and suggestions are welcome in the comments. If the stats surprise you on your market, that is usually the most interesting place to start reading.
Indicator

Indicator

Market Sessions + Killzones [Income Statement]A persistent challenge in intraday trading is that price behaviour is not uniform across the 24-hour clock. Volatility, liquidity, and directional bias are heavily concentrated in specific windows tied to the opening and closing of major financial centres.
Market Sessions + Killzones indicator maps those windows directly onto the chart, layers in the structural tools that ICT-based traders use to read them, and combines everything into a single cohesive visual so traders do not need to manage multiple overlapping indicators.
WHY THESE FEATURES ARE COMBINED
Session ranges, killzones, overlap periods, and previous session highs/lows are not independent ideas — they are sequential layers of the same framework. The session range defines the pool of liquidity that formed during a given market period. The previous session high and low represent the edges of that pool (similar to support and resistance) and become magnets for price in the following session. Killzones are the time windows within which institutional order flow is most likely to be active and capable of driving price through those levels. The overlap periods are where two separate liquidity pools interact simultaneously, producing the conditions most likely to generate sharp directional moves.
Combining all four in one indicator preserves the cause-and-effect relationship between them. Displaying sessions without killzones, or killzones without previous session levels, loses the context that makes each layer meaningful.
HOW THE INDICATOR WORKS
Session Boundaries
Each session (Tokyo, London, New York, optional Sydney) is tracked using the exchange's native timezone, not a fixed UTC offset. This matters because major sessions observe daylight saving time on different schedules, and a fixed-offset approach will silently drift by an hour during DST transitions. The script uses Pine's time() function with named timezone strings (Asia/Tokyo, Europe/London, etc.) to handle this automatically.
As each session progresses, the script tracks the running high and low bar-by-bar and extends the boundary lines to the current bar. At session close, the lines are locked in place and faded to indicate a completed session — distinguishing live sessions from historical ones at a glance.
Midpoint and Quartile Lines
Within each session, the script calculates the 50% midpoint and the 25%/75% quartile levels of the live range. These levels are drawn not because they are support/resistance in the classical sense, but because they divide the session's range into statistically meaningful zones. In ICT methodology, the midpoint (sometimes called the equilibrium) is a commonly referenced level for entries and targets. The quartiles indicate whether price is in the upper or lower half of the session's distribution.
Previous Session Highs and Lows
When a new session opens, the script saves the completed session's high and low and draws them forward as dashed lines into the new session. These levels represent the most visible liquidity pools from the prior period — stop-losses from traders who traded that session cluster above and below them. Price frequently targets these levels before establishing a new directional move.
ICT Killzones
Killzones are specific time windows identified in ICT methodology as high-probability trading periods:
• London Killzone: 02:00–05:00 New York time — the pre-London and early London open window, a period of frequent liquidity grabs before the main London trend establishes.
• New York Killzone: 07:00–10:00 New York time — encompasses the NY pre-market and the first 30 minutes of the NY open, the most liquid window of the trading day for USD pairs and US indices.
Each killzone is rendered as a box that expands dynamically with price throughout the window and locks when the window closes. The box captures the exact range of price movement during that period, making it easy to measure killzone expansion and compare it to the current session range.
Overlap Periods
Two overlap windows are detected and highlighted:
• Tokyo + London overlap: the brief window where Asian and European institutional flow intersect.
• London + New York overlap (08:30–12:00 ET approximately): historically the highest-volume period of the trading day for most major pairs. This overlap frequently produces the session's largest directional move or the strongest reversal of an earlier London move.
The overlap boxes expand dynamically with price, making it simple to see how much range was generated during the high-liquidity window versus the rest of the session.
Live Statistics Table
The table in the top-right corner displays the live session high, low, range in points, and range as a percentage of the 14-period ATR. The ATR ratio is the key metric here: it tells you not just how far price has moved, but how that move compares to recent volatility. A session range at 120% ATR suggests an unusually expansive session; one at 40% suggests compression that may precede a breakout.
SETTINGS GUIDE
Swing Length: Not applicable to this indicator.
Show Midpoint / Quartile Lines: Toggle to reduce visual noise on lower timeframes where the chart is already dense.
Show Prev Session H/L: Disable if you only want the current session boundaries and killzones without the historical dashed levels.
Show Overlap Zones: Disable for cleaner charts on assets where overlap volatility is less relevant (e.g. Asian equity CFDs).
Show ICT Killzones: Toggle independently of sessions — useful if you want session ranges as context but only want to trade the killzone windows.
Range as % ATR: Enables the ATR normalisation column in the table.
TIMEFRAME
This indicator is intentionally restricted to timeframes below 1 hour. Session structure and killzones are intraday concepts — applying them to daily or weekly charts produces meaningless output. Recommended: 1m, 3m, 5m, 15m, or 30m.
USAGE NOTES
This indicator provides structural context, not signals. A common workflow is to identify the previous session high or low as a liquidity target, wait for price to enter a killzone, then use a separate entry model (e.g. order block, fair value gap, or market structure shift) to time the trade. The indicator does not generate buy or sell signals on its own. Indicator

Compass | AnonycryptousCompass | Anonycryptous
Description & user manual
Credits
The weekly psychological level calculation in this indicator is based on open-source code originally published on PulseWire. The original script was created by plasmapug. Continued development was done by infernixx, Peshocore, and xtech5192 in collaboration with TradersReality. Significant modifications have been made to integrate this component into the Compass framework.
Why this indicator is different
Most indicators answer one question. A moving average tells you the trend direction. An oscillator tells you momentum. A session box tells you the time. A volume indicator tells you participation. Each one is useful. None of them tells you where you are.
Before placing a trade, a trader needs to answer several questions simultaneously. What session is active and what does that mean for the type of price action to expect? Where does the macro trend stand? Is volume confirming the move or contradicting it? Are there open imbalances nearby that price may return to? How much of the day's expected range has already been consumed? Where are the key structural levels — pivots, the daily open, prior week references?
Answering each of these questions separately requires stacking tool after tool until the chart becomes unreadable. Compass answers all of them at once.
It is not a signal indicator. It does not fire arrows or tell you when to buy or sell. What it does is something more fundamental: it gives you a complete read of the market environment before any decision is made. Sessions, trend, volume, imbalances, range levels, pivots, psychological references — all in one overlay, all configurable, all on one chart.
The design philosophy is orientation first. Decision second. Compass tells you where you are. What you do with that is your responsibility.
Important notice
Compass does not generate trading signals.
It does not tell you when to buy or sell.
It does not predict market direction.
It does not replace your trading strategy or your own analysis.
All illustrative examples in this manual are for educational purposes only and are not trading recommendations.
All trading decisions remain entirely with the user.
Always apply your own judgment and manage your own risk.
1. Overview
Compass is a comprehensive market context indicator that combines eleven independent analysis frameworks into one unified overlay. Every component is individually toggleable. Six presets are included for different trading styles, from fast scalping to full multi-component analysis.
What it includes:
- Five-EMA suite with adaptive cloud around the EMA 50
- EMA crossover system with configurable signals and candle coloring
- Stochastic RSI background alerts with four alert types and RSI divergence detection
- PVSRA volume vector candle analysis with zone tracking and configurable thresholds
- Eight global market sessions with automatic DST awareness
- Average daily, weekly, and monthly range levels with 50% midpoints
- Classic pivot points with mid-point levels
- Daily open reference line with historical opens
- Fair value gap detection with partial absorption tracking
- Weekly psychological level tracking
- Live dashboard with eighteen data points across all active components
2. EMA suite
Five exponential moving averages are plotted simultaneously: EMA 5, EMA 13, EMA 50, EMA 200, and EMA 800. Together they cover short-term momentum, medium-term trend direction, macro trend, and long-term structural bias.
The EMA 50 is wrapped in a dynamic cloud calculated from two standard deviations of price. The cloud expands during volatility and contracts during consolidation. A widening cloud indicates active price discovery. A thinning cloud indicates equilibrium or compression before a directional move.
The EMA 200 is the primary macro bias filter. Price above it defines a broadly bullish environment. Price below it defines a broadly bearish environment. This is shown in the dashboard at all times.
The EMA 800 provides long-term structural context, particularly useful on mid to higher timeframes where it marks the gravitational center of multi-month price structure.
All five EMA lengths are configurable. Each has individual color and transparency controls. An EMA label option displays the current value at the right edge of each line.
3. EMA cross system
The EMA cross tracks a configurable fast EMA crossing a configurable slow EMA and marks the crossover bar. All candles after a cross continue in the direction of that cross until the opposite cross fires.
Three display modes are available: show both the fast and slow EMA lines, show a single consolidated EMA line, or hide the EMA lines entirely while keeping the crossover signals visible.
This component is a trend state indicator, not a trade trigger. A bull cross does not mean buy. It means the short-term trend has shifted upward relative to the medium-term average.
Signals and candle coloring can be toggled independently.
4. Stochastic RSI
The stochastic RSI component runs a standard stochastic RSI calculation and generates background color alerts based on crossover conditions at configurable band levels.
Four alert types are available, each independently toggleable:
Middle band crossover — K line crosses D line near the 50 level. Indicates a possible trend shift in momentum.
Overbought/oversold crossover — K line crosses D line from overbought or oversold territory. Indicates a potential reversal from an extreme.
Entering overbought — K line crosses above the upper band. Indicates that momentum has moved into overbought territory.
Entering oversold — K line crosses below the lower band. Indicates that momentum has moved into oversold territory.
The dashboard displays the current stochastic RSI state and the RSI value. RSI appears in green when above the midline and in red when below. Regular bullish and bearish divergence is detected automatically and shown in the dashboard as a directional label. When divergence is active, a thin reference line appears on the price chart marking the divergence candles.
5. PVSRA volume vector analysis
PVSRA analysis colors candles based on volume relative to the 10-bar average and the relationship between volume and candle spread.
Four vector types:
Green vector — bullish bar where volume is at or above the green/red threshold (default 200% of the 10-bar average), or where volume multiplied by spread is the highest of the last 10 bars. Indicates strong bullish institutional participation.
Red vector — same conditions on a bearish bar. Indicates strong bearish institutional participation.
Blue vector — bullish bar where volume is at or above the blue/violet threshold (default 150% of average). Indicates elevated bullish volume below the institutional threshold.
Violet vector — same conditions on a bearish bar. Indicates elevated bearish volume.
Grey — no vector conditions met. Normal volume.
Both thresholds are configurable directly from the settings panel. Blue and violet signals are strictly exclusive from green and red — a bar cannot qualify for both simultaneously.
Vector candle zones draw boxes at each vector candle location and remain active until price moves through the zone, marking areas where elevated institutional activity was detected at the time the candle formed.
The PVSRA override input allows a different symbol to be used for the volume calculation. This is useful when the charted instrument has unreliable volume data, such as CFDs, perpetual swaps, or instruments where the primary volume is on a related market.
6. Market sessions
Eight global trading sessions are tracked simultaneously, each with automatic DST awareness. Sessions are displayed as expanding boxes with high and low lines and a real-time label showing the session open.
Sessions included:
- London: 08:00–16:30 UTC
- New York: 14:30–21:00 UTC
- Tokyo: 00:00–06:00 UTC
- Hong Kong: 01:30–08:00 UTC
- Sydney: 22:00–06:00 UTC
- EU brinks: 08:00–09:00 UTC
- US brinks: 14:00–15:00 UTC
- Frankfurt: 07:00–16:30 UTC
DST is handled automatically for London, New York, and Sydney. No manual adjustment is needed. Each session can be toggled individually, and box color, transparency, and label color are fully configurable per session.
Session context matters because market behavior differs significantly depending on which participants are active. London and New York overlap produces the highest volume and fastest price movement. Tokyo and Sydney sessions tend to consolidate. The brinks windows mark the transition periods where session highs and lows often form.
7. Range levels
Three statistical range frameworks measure the expected price range for the current period based on historical averages.
Average daily range (ADR) — the expected high and low for the current trading day. When price reaches the ADR level, the day's expected range has been consumed. Moves beyond the ADR are extension moves that occur with lower statistical probability and often mean-revert. The dashboard shows ADR % used — how much of today's expected range has already been consumed. Above 80% indicates the day is approaching its expected limit.
Average weekly range (AWR) — the same concept applied to the current week. Useful for assessing how much room the week has left to move.
Average monthly range (AMR) — the same concept applied to the current month. Provides macro context for position sizing and target expectations.
Each framework includes a 50% midpoint level marking the center of the expected range. The ADR measure from daily open option calculates the range starting from that day's open price rather than the statistical high, making the levels static for the entire day.
All three frameworks have individual lookback period inputs, color controls, line styles, and label toggles.
8. Pivot points
Classic pivot points are calculated from the prior day's high, low, and close. Levels include PP, R1/S1, R2/S2, R3/S3, and M mid-point levels between each major level.
Pivot points provide structural reference for the current session. Price above PP defines a broadly bullish day structure. R levels act as potential resistance targets. S levels act as potential support targets. M levels provide intermediate precision references between major pivots.
All levels can be toggled individually. Lines extend rightward from the prior session and can optionally extend in both directions. Each level has individual color and line style controls.
9. Daily open
A horizontal line marks the current day's opening price. This is one of the most referenced structural levels among short-term traders because it defines the starting point for the day's price discovery.
Price above the daily open reflects a bullish session bias. Price below reflects a bearish session bias. When price oscillates around the daily open without committing direction, the session is in balance — a lower probability environment for trend trades.
Historical daily opens can optionally be shown as reference for prior day context.
10. Fair value gaps
A fair value gap is a three-bar imbalance where price moved through a range without leaving two-sided trade — the low of the upper candle is above the high of the lower candle (bullish gap) or vice versa (bearish gap). These areas represent unfinished business where the market may return to achieve balance.
Gaps are filtered by a minimum width threshold expressed as a multiple of ATR. Gaps narrower than the threshold are excluded. Partial absorption is tracked — as price returns into the gap, the fill color changes to show how much of the imbalance has been recovered.
Fully mitigated gaps can be kept on the chart as historical reference or deleted automatically to maintain a clean view.
11. Psychological levels
Weekly psychological levels mark the prior week's high and low as calculated by a specific session-anchored method. These levels represent deliberate structural references where participants have previously committed size — breakouts and rejections around these levels tend to be more intentional than random price noise.
Three GMT offset options accommodate the session anchor calculation for different global market structures. Two mode options are available: crypto (weekly reset on Saturday Sydney open) and forex (weekly reset on Monday Tokyo open).
12. Settings reference
Preset
- Custom: full manual control over all settings.
- Clean scalper: sessions, EMA suite, FVG, subtle candle coloring. Low noise.
- Full context: everything on, medium transparency. Best for analysis.
- Signal focus: EMA cross, stoch RSI background, PVSRA bar color prominent. Rest subtle.
- Minimal: sessions, daily open, ADR only. No signals.
- PVSRA pro: PVSRA and vector candle zones central. EMA 200 and 800 only.
Global settings
- Master opacity offset (custom preset only): shifts all transparency values simultaneously.
- Show bull/bear label text: shows or hides text on EMA cross signal triangles.
EMA suite
- Show EMA suite and labels
- Individual EMA color and transparency controls
- EMA cloud fill and border transparency
- EMA line width
EMA cross
- Show EMA cross signals
- Fast EMA, slow EMA, and consolidated EMA lengths
- Show both EMAs or consolidated only
- Bull, bear, and neutral colors and transparency
- Cross EMA line width
Stochastic RSI
- Show stochastic RSI background alerts
- RSI length and stochastic length
- Overbought and oversold band levels
- Individual alert type toggles (four types)
- Alert colors and transparency
- RSI divergence lookback period
- Divergence line color and width
PVSRA
- Vector colors (red, green, violet, blue, regular up/down)
- Green/red threshold (× average volume, default 2.0)
- Blue/violet threshold (× average volume, default 1.5)
- Include spread filter for green/red classification
- Override symbol toggle and input
- Show vector candle zones with transparency and width settings
Candle coloring
- Enable candle coloring
- Coloring mode: EMA cross / PVSRA / EMA 200 / off
- Bull and bear candle color and transparency
Market sessions
- Show market sessions
- Session timezone
- Show sessions on weekends
- Session high/low line style and width
- Per session: toggle, box color, transparency, label color
Range levels
- Show ADR, AWR, AMR (individual toggles)
- Lookback periods for each
- Show 50% midpoint levels
- Measure from daily open (ADR only)
- Color, transparency, line width, line style, labels
Pivot points
- Show PP, R1/S1, R2/S2, R3/S3, M levels individually
- Show labels
- Extend lines both directions
- Individual level colors and line styles
- Pivot line width
Daily open
- Show daily open
- Show label
- Show historical daily opens
- Color, transparency, line width
Fair value gaps
- Show fair value gaps
- Width filter (ATR multiplier)
- Extend to current bar
- Bullish and bearish FVG colors
- Mitigation fill colors
- Keep historical FVGs after mitigation
Psychological levels
- Show psy levels and labels
- Show historical psy levels
- GMT offset (GMT+1, GMT+2, GMT+3)
- Psy type: crypto or forex
- High and low colors and transparency
Dashboard
- Show dashboard
- Position: top left, top right, bottom left, bottom right
- Size: tiny, small, normal
13. Dashboard reference
The dashboard provides eighteen live data points across all active components:
Session — the currently active market session.
EMA cross — current EMA cross direction: bull or bear.
EMA 200 — whether price is above or below the EMA 200.
Stoch RSI — current stochastic RSI condition.
RSI — current RSI value, colored green above midline and red below.
RSI divergence — active bullish or bearish divergence, or none.
PVSRA — current candle vector type.
ADR % used — how much of today's expected daily range has been consumed.
FVG active — count of open unmitigated fair value gaps and mitigation percentage.
Psy level — whether price is above or below the prior week's psychological level.
Timezone — active session timezone setting.
VCZ active — count of active vector candle zones above and below current price.
Pivot PP — current pivot point value.
Daily open — current daily open price and direction.
14. How to use
14.1 Initial setup
Select a preset that matches your primary trading style. Adjust the session timezone to match your location or your primary exchange. If you trade an instrument with unreliable volume data, enable the PVSRA override and set it to a correlated liquid instrument. Set the ADR lookback period to your preference — 14 days is a standard starting point. For FVGs, set the width filter to 0.5 or higher to exclude minor gaps.
14.2 Reading the dashboard
The dashboard is the fastest way to orient yourself on a new chart or a new session. Check session, EMA cross direction, EMA 200 position, stoch RSI state, and ADR consumed before anything else. Five seconds to a full picture of where the market stands.
14.3 Reading the chart
Check EMA alignment. When EMA 13, EMA 50, and EMA 200 are stacked in the same direction, the trend is more significant than a single crossover. Divergence between them reflects a transition or competing timeframe pressures.
Check ADR percentage. Below 50% means the day has statistical room to move. Above 80% means the day is near its expected limit and extension moves are less probable.
Look for open FVGs near current price. An unmitigated FVG in the direction of the prevailing trend is a precision reference area where price has historically returned.
Check the psy level. If price is approaching the prior week's high or low, be aware that participant behavior around those references tends to be deliberate.
14.4 Timeframe guide
1 minute to 3 minutes — clean scalper preset, candle coloring set to EMA cross.
5 minutes to 15 minutes — clean scalper or signal focus preset.
30 minutes to 1 hour — full context preset, use ADR and pivot points.
4 hours to daily — full context or minimal preset.
14.5 Tips
PVSRA override — use when your broker's volume data is unreliable, when you trade a CFD or derivative with synthetic volume, or when you want spot market volume for a futures chart.
Master opacity offset — adding 10 to 20 increases overall transparency and dims the chart if it feels cluttered. Subtracting 10 to 20 makes all elements more prominent. This shifts all transparency values simultaneously without changing individual settings. Only active in custom preset.
Not every component needs to be active at once. Most traders will find three to four components provide the context they need for their specific setup.
15. Disclaimer
This indicator is provided for educational and informational purposes only.
Nothing in this document constitutes financial advice or any form of trading recommendation.
Trading financial instruments involves substantial risk of loss.
Past performance is not indicative of future results.
You may lose all of your invested capital.
All trading decisions are made entirely by the user.
Use at your own discretion.
Indicator

Indicator

Indicator

CandelaCharts - Killzone HTF Candles📝 Overview
The Killzone HTF Candles indicator is a professional visual tool designed for ICT and SMC traders who prioritize session-based price action. It bridges the gap between Lower Timeframe (LTF) execution and Higher Timeframe (HTF) context by projecting session-specific data (Asia, London, New York) directly onto your chart as discrete candles.
This tool allows you to monitor the "Daily Narrative" by seeing how session ranges interact without ever leaving your execution timeframe, helping you identify liquidity sweeps and trend transitions at a glance.
📦 Features
Multi-Session Tracking : Pre-configured with 8 primary Killzones: Asia (AS), London Open (LO), NY AM, NY Lunch (LA), NY PM, and 3 additional custom sessions.
Dual Projection Logic :
Mapped to Chart : Overlays HTF boxes and wicks directly on the price action for historical study and zone identification.
Ghost Display : Projects the most recent sessions as a "Rolling Dashboard" on the right side of the chart, keeping your current price action clear.
Dynamic Chronology : Ghost candles automatically rotate, ensuring the most recent session is always positioned on the far right.
Premium Aesthetics : Built with glassmorphism design principles, featuring customizable body opacity, line widths, and font styles.
Timezone Sync : Integrated timezone support (Default: America/New_York) ensures your sessions align perfectly with global markets.
⚙️ Settings
HTF Candle Mechanics
Candle Size : Adjusts the width of the ghost candles.
Bull/Bear Colors : Set your preferred color scheme for bullish/bearish closes.
Ghost Offset/Spacing : Fine-tune the position and gap of the ghost candles on the right side.
Line Width : Controls the thickness of wicks and candle borders.
Opacity : Adjust the transparency of the candle body fills.
Session Configuration (I - VIII)
Show Session : Enable/Disable tracking for specific Killzones.
Display Name : Customize labels (e.g., "LO", "NY AM").
Session Time : Define precise time ranges for each session.
Map to Chart : Toggle the HTF candle overlay for specific sessions.
⚡️ Showcase
The "Session Transfer" Logic
By using the Ghost Candles , you can quickly identify the relationship between different trading periods:
AS Range : Often sets the initial consolidation or liquidity pool.
LO Expansion : Typically creates the high or low of the day.
NY AM Reversal : Often trades back into the LO or AS ranges to fill gaps or sweep liquidity.
Highly customizable, build your own custom killzones
🚨 Alerts
This version is optimized for visual analysis. While it does not include internal logic alerts, it provides a comprehensive real-time dashboard for manual confluence and bias confirmation.
⚠️ Disclaimer
Trading involves significant risk, and many participants may incur losses. The content on this site is not intended as financial advice and should not be interpreted as such. Decisions to buy, sell, hold, or trade securities, commodities, or other financial instruments carry inherent risks and are best made with guidance from qualified financial professionals. Past performance is not indicative of future results.
Indicator

IRL ERL Liquidity MapIRL ERL Liquidity Map is an original multi-timeframe orderflow and liquidity mapping tool designed to help traders organize internal liquidity zones and external liquidity objectives on one clean chart.
The script focuses on the relationship between IRL and ERL:
IRL, or Internal Range Liquidity, is represented by imbalance-style zones such as Fair Value Gaps (FVG) and Breakaway Gaps (BAG). These zones mark areas where price may return before continuing toward a larger liquidity objective.
ERL, or External Range Liquidity, is represented by swing highs, swing lows, and previous high/low levels from higher timeframes. These levels act as possible draw-on-liquidity objectives once price reacts from an internal zone.
The purpose of combining these components is not to create separate signals, but to show one complete liquidity workflow:
1. Identify an internal liquidity zone.
2. Watch whether price reacts from it or closes through it.
3. Track the likely external liquidity objective.
4. Use higher-timeframe levels and session ranges for context.
Main Features
Multi-Timeframe IRL Zones:
The indicator tracks FVG and BAG zones across selected timeframes including 15m, 1h, 4h, Daily, Weekly, and Monthly. Each timeframe can be enabled or disabled separately. Bias can be left on Auto or manually filtered to bullish or bearish.
FVG and BAG Detection:
A bullish FVG is detected when the current candle leaves an imbalance above the candle two bars back. A bearish FVG is detected when the current candle leaves an imbalance below the candle two bars back. BAG zones are stricter gap conditions where the displacement candle also breaks beyond the prior candle structure.
Zone Validation:
Zones remain active until price invalidates them by closing through the zone body on the related timeframe, or until the related external liquidity target is reached. This helps separate a simple wick reaction from a stronger body-close invalidation.
ERL Targets:
The script uses swing highs and swing lows as external liquidity targets. When price reacts from an IRL zone, the nearest relevant swing objective helps define where the current context may complete.
Swing Points:
Tiny swing dots and optional ERL swing lines can be displayed on the chart. These are intended to make local liquidity points easier to see without adding heavy visual clutter.
Higher-Timeframe Liquidity Levels:
Previous Day High/Low, Previous Week High/Low, and Previous Month High/Low can be displayed. These levels are commonly used as external liquidity references and can be automatically removed once swept.
Session Killzones:
The script includes configurable session ranges for London, New York, Asia, and Sydney. These ranges help traders study when liquidity runs, reactions, and displacement are occurring during active market windows.
Dashboard:
A compact dashboard summarizes the current orderflow state for each enabled timeframe. It shows whether price is reacting from an IRL zone, whether a zone is failing, or whether no active context is present. The dashboard uses matching timeframe colors for easier reading:
4h = orange
Daily = blue
Weekly = yellow
Monthly = red
Chart Clarity:
The script includes display controls to reduce clutter, including maximum active zones per timeframe, maximum total zones, fixed-width zone boxes, dashed zone borders, label controls, and opacity settings.
How To Use
Use higher timeframes first to identify major liquidity context. For example, Daily, Weekly, or Monthly zones can show larger areas where price may react or rebalance.
Use lower timeframes to refine entries and observe whether price is respecting or failing an internal liquidity zone.
A reacting state means price has entered an active IRL zone without yet invalidating it by body close.
A failing state means price has closed through the IRL zone according to the selected timeframe logic.
An ERL completion means price has reached the related swing or external liquidity objective after the IRL context was active.
This tool does not predict price direction by itself. It is designed as a visual framework for studying liquidity, imbalance, session timing, and higher-timeframe objectives. Traders should combine it with their own risk management, market structure analysis, and confirmation rules.
Recommended Chart Setup
For publication or clean analysis, use this indicator by itself on the chart, with minimal drawings. Keep the chart background clean so the FVG/BAG zones, ERL targets, session ranges, and higher-timeframe levels are easy to identify.
Indicator

Better Sessions [CantoLab]This session indicator plots Asia, London and New York sessions, with 3 extra fully customisable sessions. Includes sweep detection to automatically track if price has swept session highs/lows, and a visual dashboard to identify overlapping sessions.
Features :
Sessions
Up to 6 sessions can be configured with custom times, colors and labels. By default the indicator comes set to Asia, London and NY stock exchange timings. The 3 additional sessions can be set to anything.
A common use case is replicating ICT killzones by adjusting the session times in settings to London , NY-AM , NY-PM , Asia
The overlapping window between London and New York is highlighted automatically in the dashboard, signifying the period of potential high volume and volatility traders watch closely.
Sweep Detection
On session close, lines are drawn automatically from the session high and low. They extend forward bar by bar and mark as swept the moment price crosses them. No manual drawing or monitoring needed.
Daily Dividers
Vertical lines at each day boundary to separate trading days.
Settings:
Sessions — toggle, time, color and label per session
Sweep Detection — toggle in settings (off by default)
CE Line — session equilibrium/midpoint, toggle in settings
Daily Dividers — toggle, color, style and width
Session Table — 24hr overlap dashboard, 9 position options
Label Size — Tiny / Small / Normal / Large
Notes:
Best used on timeframes at or below 1 hour
Sweep lines reset at the start of each new day
UTC offset applies globally — adjust manually for DST
Indicator
