Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //@version=6
- indicator("Session Breakout Boxes- The BTC Beast", overlay = true, max_boxes_count = 500, max_labels_count = 500, max_lines_count = 500)
- crypto_mode = input.bool(false, "Enable Weekend Trading (Crypto 24/7 Mode)", group="Global Mode Switch")
- overnight_mode = input.bool(true, "Enable US Futures Overnight Session Tracking (1800-0930 NY)", group="Global Mode Switch")
- lookback_days = input.int(7, "Session History Lookback (Days)", minval=1, maxval=60, group="Global Mode Switch")
- show_ovn_rays = input.bool(true, "Show White Overnight High/Low Rays", group="Overnight Ray Custom Settings")
- break_tf = input.timeframe("60", "Breakin' Candle Timeframe (e.g. 5, 15, 60, D)", group="Overnight Ray Custom Settings")
- nz_show = input.bool(true, "Show NZ/Sydney Session", group="1. NZ & Sydney Session")
- nz_hours = input.string("0700-1600", "Base Hours (NZ Open to Sydney Close)", group="1. NZ & Sydney Session")
- nz_tz = input.string("Pacific/Auckland", "Timezone Anchor", group="1. NZ & Sydney Session")
- nz_color = input.color(#00f2ff, "Session Color", group="1. NZ & Sydney Session")
- nz_trans = input.int(93, "Transparency (0-100)", minval=0, maxval=100, group="1. NZ & Sydney Session")
- tok_show = input.bool(true, "Show Tokyo Session", group="2. Tokyo Session")
- tok_hours = input.string("0900-1800", "Base Hours (Tokyo Open to Close)", group="2. Tokyo Session")
- tok_tz = input.string("Asia/Tokyo", "Timezone Anchor", group="2. Tokyo Session")
- tok_color = input.color(#ffd700, "Session Color", group="2. Tokyo Session")
- tok_trans = input.int(93, "Transparency (0-100)", minval=0, maxval=100, group="2. Tokyo Session")
- euro_show = input.bool(true, "Show Europe Session", group="3. Europe Session")
- euro_hours = input.string("0700-1630", "Base Hours (Frankfurt Open to London Close)", group="3. Europe Session")
- euro_tz = input.string("Europe/Berlin", "Timezone Anchor (Frankfurt)", group="3. Europe Session")
- euro_color = input.color(#ff007c, "Session Color", group="3. Europe Session")
- euro_trans = input.int(93, "Transparency (0-100)", minval=0, maxval=100, group="3. Europe Session")
- ny_show = input.bool(true, "Show New York Session", group="4. New York Session")
- ny_hours = input.string("0800-1700", "Base Hours (NY Time)", group="4. New York Session")
- ny_tz = input.string("America/New_York", "Timezone Anchor", group="4. New York Session")
- ny_color = input.color(#00ff6a, "Session Color", group="4. New York Session")
- ny_trans = input.int(95, "Transparency (0-100)", minval=0, maxval=100, group="4. New York Session")
- erase_mode = input.string("Wick Touch", "Erase Session High/Low Lines On", options=["Wick Touch", "Candle Close Beyond"], group="Session Level Line Settings")
- box_border_width = input.int(4, "Session Box Line Thickness", minval=1, maxval=10, group="Box Outline Settings")
- dash_offset = input.int(5, "Downward Height Offset (%)", minval=0, maxval=100, group="Dashboard Height Calibration")
- show_box_labels = input.bool(true, "Show Labels on Boxes", group="Box Label Settings")
- box_lbl_bg = input.color(#000000, "Label Background Color", group="Box Label Settings")
- box_lbl_color = input.color(#ffffff, "Label Text Color", group="Box Label Settings")
- var array<line> active_high_lines = array.new<line>()
- var array<line> active_low_lines = array.new<line>()
- var array<line> ovn_high_lines = array.new<line>()
- var array<line> ovn_low_lines = array.new<line>()
- var array<label> ovn_high_labels = array.new<label>()
- var array<label> ovn_low_labels = array.new<label>()
- var float current_fut_h = na
- var float current_fut_l = na
- is_within_lookback = (timenow - time) <= lookback_days * 86400000
- nz_sess = crypto_mode ? nz_hours + ":1234567" : nz_hours + ":23456"
- tok_sess = crypto_mode ? tok_hours + ":1234567" : tok_hours + ":23456"
- euro_sess = crypto_mode ? euro_hours + ":1234567" : euro_hours + ":23456"
- ny_sess = crypto_mode ? ny_hours + ":1234567" : ny_hours + ":23456"
- in_session(string sess, string tz) => not na(time(timeframe.period, sess, tz))
- nz_active = is_within_lookback and nz_show and in_session(nz_sess, nz_tz)
- tok_active = is_within_lookback and tok_show and in_session(tok_sess, tok_tz)
- euro_active = is_within_lookback and euro_show and in_session(euro_sess, euro_tz)
- ny_active = is_within_lookback and ny_show and in_session(ny_sess, ny_tz)
- ny_dow = dayofweek(time, "America/New_York")
- ny_hr = hour(time, "America/New_York")
- weekend_gap = ny_dow == dayofweek.saturday or (ny_dow == dayofweek.friday and ny_hr >= 18) or (ny_dow == dayofweek.sunday and ny_hr < 18)
- fut_in_sess = in_session("1800-0930", "America/New_York") and (crypto_mode or not weekend_gap)
- fut_active = is_within_lookback and overnight_mode and fut_in_sess
- var bool in_nz_last = false
- var bool in_tok_last = false
- var bool in_euro_last = false
- var bool in_ny_last = false
- var bool in_fut_last = false
- nz_start = nz_active and not in_nz_last
- tok_start = tok_active and not in_tok_last
- euro_start = euro_active and not in_euro_last
- ny_start = ny_active and not in_ny_last
- fut_start = fut_active and not in_fut_last
- nz_end = not nz_active and in_nz_last
- tok_end = not tok_active and in_tok_last
- euro_end = not euro_active and in_euro_last
- ny_end = not ny_active and in_ny_last
- fut_end = not fut_active and in_fut_last
- in_nz_last := nz_active
- in_tok_last := tok_active
- in_euro_last := euro_active
- in_ny_last := ny_active
- in_fut_last := fut_active
- htf_close_prev = request.security(syminfo.tickerid, break_tf, close[1], gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)
- vol_ma = ta.sma(volume, 14)
- rvol = vol_ma > 0 ? volume / vol_ma : 1.0
- get_ms_to_end(string sess_str, string tz) =>
- int end_hours = int(str.tonumber(str.substring(sess_str, 5, 7)))
- int end_mins = int(str.tonumber(str.substring(sess_str, 7, 9)))
- int cur_total_secs = (hour(timenow, tz) * 3600) + (minute(timenow, tz) * 60) + second(timenow, tz)
- int end_total_secs = (end_hours * 3600) + (end_mins * 60)
- int diff_secs = end_total_secs - cur_total_secs
- int final_diff = diff_secs < 0 ? diff_secs + 86400 : diff_secs
- final_diff * 1000
- format_timer(int ms) =>
- int total_secs = int(math.floor(ms / 1000))
- int hrs = int(math.floor(total_secs / 3600))
- int mins = int(math.floor((total_secs % 3600) / 60))
- int secs = int(total_secs % 60)
- str.format("{0,number,00}:{1,number,00}:{2,number,00}", hrs, mins, secs)
- f_session(bool start, bool active, bool ended, string name, color col, int trans) =>
- var box bx = na
- var label lb = na
- var float h = na
- var float l = na
- if start
- h := high
- l := low
- bx := box.new(left=time, top=h, right=time_close, bottom=l, xloc=xloc.bar_time,
- bgcolor=color.new(col, trans), border_color=col, border_width=box_border_width)
- if show_box_labels
- lb := label.new(x=time_close, y=h, text=name, xloc=xloc.bar_time, color=box_lbl_bg,
- textcolor=box_lbl_color, style=label.style_label_down, size=size.normal)
- else if active and not na(bx)
- h := math.max(h, high)
- l := math.min(l, low)
- box.set_top(bx, h)
- box.set_bottom(bx, l)
- box.set_right(bx, time_close)
- if not na(lb)
- label.set_y(lb, h)
- if ended and not na(bx)
- array.push(active_high_lines, line.new(x1=box.get_left(bx), y1=h, x2=time_close, y2=h, xloc=xloc.bar_time, color=col, style=line.style_dashed, width=1))
- array.push(active_low_lines, line.new(x1=box.get_left(bx), y1=l, x2=time_close, y2=l, xloc=xloc.bar_time, color=col, style=line.style_dashed, width=1))
- true
- f_session(nz_start, nz_active, nz_end, "NZ/Sydney", nz_color, nz_trans)
- f_session(tok_start, tok_active, tok_end, "Tokyo", tok_color, tok_trans)
- f_session(euro_start, euro_active, euro_end, "Europe (Frankfurt Open)", euro_color, euro_trans)
- f_session(ny_start, ny_active, ny_end, "New York", ny_color, ny_trans)
- if fut_start and show_ovn_rays
- current_fut_h := high
- current_fut_l := low
- array.push(ovn_high_lines, line.new(x1=time, y1=current_fut_h, x2=time_close, y2=current_fut_h, xloc=xloc.bar_time, color=color.white, style=line.style_dashed, width=2, extend=extend.right))
- array.push(ovn_low_lines, line.new(x1=time, y1=current_fut_l, x2=time_close, y2=current_fut_l, xloc=xloc.bar_time, color=color.white, style=line.style_dashed, width=2, extend=extend.right))
- label h_lb = na
- label l_lb = na
- if show_box_labels
- h_lb := label.new(x=time_close, y=current_fut_h, text="Overnight High", xloc=xloc.bar_time, color=box_lbl_bg, textcolor=color.white, style=label.style_label_down, size=size.small)
- l_lb := label.new(x=time_close, y=current_fut_l, text="Overnight Low", xloc=xloc.bar_time, color=box_lbl_bg, textcolor=color.white, style=label.style_label_up, size=size.small)
- array.push(ovn_high_labels, h_lb)
- array.push(ovn_low_labels, l_lb)
- else if fut_active and show_ovn_rays and array.size(ovn_high_lines) > 0
- current_fut_h := math.max(current_fut_h, high)
- current_fut_l := math.min(current_fut_l, low)
- line h_item = array.get(ovn_high_lines, array.size(ovn_high_lines) - 1)
- line l_item = array.get(ovn_low_lines, array.size(ovn_low_lines) - 1)
- line.set_y1(h_item, current_fut_h)
- line.set_y2(h_item, current_fut_h)
- line.set_x2(h_item, time_close)
- line.set_y1(l_item, current_fut_l)
- line.set_y2(l_item, current_fut_l)
- line.set_x2(l_item, time_close)
- if array.size(ovn_high_labels) > 0
- label h_lb_item = array.get(ovn_high_labels, array.size(ovn_high_labels) - 1)
- label l_lb_item = array.get(ovn_low_labels, array.size(ovn_low_labels) - 1)
- if not na(h_lb_item)
- label.set_x(h_lb_item, time_close)
- label.set_y(h_lb_item, current_fut_h)
- if not na(l_lb_item)
- label.set_x(l_lb_item, time_close)
- label.set_y(l_lb_item, current_fut_l)
- alert_time_string = str.format_time(timenow, "yyyy-MM-dd HH:mm", "UTC") + " UTC"
- bool trigger_h_flash = false
- bool trigger_l_flash = false
- f_retire(line ln, int idx, bool isHigh) =>
- array<label> lbls = isHigh ? ovn_high_labels : ovn_low_labels
- array<line> lns = isHigh ? ovn_high_lines : ovn_low_lines
- line.delete(ln)
- if array.size(lbls) > idx
- label lb = array.get(lbls, idx)
- if not na(lb)
- label.delete(lb)
- array.remove(lbls, idx)
- array.remove(lns, idx)
- true
- if show_ovn_rays and not fut_in_sess and not na(htf_close_prev)
- if array.size(ovn_high_lines) > 0
- for i = array.size(ovn_high_lines) - 1 to 0
- line l_check = array.get(ovn_high_lines, i)
- float target_y = line.get_y1(l_check)
- if htf_close_prev > target_y
- alert("🚨 BREAKOUT: [Overnight High] broken at " + str.tostring(target_y) + " on " + alert_time_string + " | RVOL: " + str.tostring(rvol, "#.##"), alert.freq_once_per_bar)
- trigger_h_flash := true
- f_retire(l_check, i, true)
- if array.size(ovn_low_lines) > 0
- for i = array.size(ovn_low_lines) - 1 to 0
- line l_check = array.get(ovn_low_lines, i)
- float target_y = line.get_y1(l_check)
- if htf_close_prev < target_y
- alert("🚨 BREAKOUT: [Overnight Low] broken at " + str.tostring(target_y) + " on " + alert_time_string + " | RVOL: " + str.tostring(rvol, "#.##"), alert.freq_once_per_bar)
- trigger_l_flash := true
- f_retire(l_check, i, false)
- bgcolor(trigger_h_flash ? color.new(color.green, 85) : (trigger_l_flash ? color.new(color.red, 85) : na))
- if array.size(active_high_lines) > 0
- for i = array.size(active_high_lines) - 1 to 0
- line line_item = array.get(active_high_lines, i)
- bool hi_hit = erase_mode == "Wick Touch" ? high >= line.get_y1(line_item) : close > line.get_y1(line_item)
- if hi_hit
- line.delete(line_item)
- array.remove(active_high_lines, i)
- else
- line.set_x2(line_item, time_close)
- if array.size(active_low_lines) > 0
- for i = array.size(active_low_lines) - 1 to 0
- line line_item = array.get(active_low_lines, i)
- bool lo_hit = erase_mode == "Wick Touch" ? low <= line.get_y1(line_item) : close < line.get_y1(line_item)
- if lo_hit
- line.delete(line_item)
- array.remove(active_low_lines, i)
- else
- line.set_x2(line_item, time_close)
- var table status_table = table.new(position = position.top_right, columns = 1, rows = 8)
- if barstate.islast
- string current_sessions = ""
- int active_count = 0
- for r = 0 to 7
- table.cell(status_table, 0, r, "", bgcolor=color.new(#000000, 100))
- table.cell(status_table, 0, 0, "", bgcolor=color.new(#000000, 100), text_size=size.small, height=dash_offset)
- if nz_active
- current_sessions += "NZ/Sydney "
- active_count += 1
- if tok_active
- current_sessions += (active_count > 0 ? "+ Tokyo " : "Tokyo ")
- active_count += 1
- if euro_active
- current_sessions += (active_count > 0 ? "+ Europe " : "Europe ")
- active_count += 1
- if ny_active
- current_sessions += (active_count > 0 ? "+ New York " : "New York ")
- active_count += 1
- color dark_panel_bg = active_count > 1 ? #2b1d42 : #131722
- table.cell(status_table, 0, 1, active_count > 1 ? "⚠️ OVERLAP: " + current_sessions : (active_count == 1 ? "🟢 ACTIVE: " + current_sessions : "⚪ MARKET CLOSE"), text_color=color.white, bgcolor=dark_panel_bg, text_size=size.large)
- int current_row = 2
- if nz_active
- table.cell(status_table, 0, current_row, "🛑 NZ/Sydney ends in: " + format_timer(get_ms_to_end(nz_sess, nz_tz)), text_color=#b2b5be, bgcolor=dark_panel_bg, text_size=size.large)
- current_row += 1
- if tok_active
- table.cell(status_table, 0, current_row, "🛑 Tokyo ends in: " + format_timer(get_ms_to_end(tok_sess, tok_tz)), text_color=#b2b5be, bgcolor=dark_panel_bg, text_size=size.large)
- current_row += 1
- if euro_active
- table.cell(status_table, 0, current_row, "🛑 Europe ends in: " + format_timer(get_ms_to_end(euro_sess, euro_tz)), text_color=#b2b5be, bgcolor=dark_panel_bg, text_size=size.large)
- current_row += 1
- if ny_active
- table.cell(status_table, 0, current_row, "🛑 New York ends in: " + format_timer(get_ms_to_end(ny_sess, ny_tz)), text_color=#b2b5be, bgcolor=dark_panel_bg, text_size=size.large)
- current_row += 1
- table.cell(status_table, 0, current_row, "📊 Current Bar RVOL: " + str.tostring(rvol, "#.##") + "x", text_color=(rvol >= 1.5 ? #00ff6a : (rvol <= 0.5 ? #ff007c : color.white)), bgcolor=dark_panel_bg, text_size=size.large)
- current_row += 1
- if not timeframe.isintraday
- table.cell(status_table, 0, current_row, "⚠️ Use an intraday chart timeframe for session boxes", text_color=color.white, bgcolor=color.new(color.red, 20), text_size=size.normal)
- else if timeframe.in_seconds(break_tf) < timeframe.in_seconds()
- table.cell(status_table, 0, current_row, "⚠️ Breakin' Candle Timeframe is lower than the chart timeframe", text_color=color.white, bgcolor=color.new(color.red, 20), text_size=size.normal)
- line_duration_hrs = input.int(24, "Line Lifespan Hours (1-24h)", minval=1, maxval=24, group="Market Open Lines")
- london_show = input.bool(true, "Show London Open Vertical Line", group="London Open")
- london_sess = input.string("0800-0801", "Open Time (HHMM-HHMM)", group="London Open")
- london_tz = input.string("Europe/London", "Timezone", group="London Open")
- london_col = input.color(#ffffff, "Line Color", group="London Open")
- nyo_show = input.bool(true, "Show New York Open Vertical Line", group="New York Open")
- nyo_sess = input.string("0930-0931", "Open Time (HHMM-HHMM)", group="New York Open")
- nyo_tz = input.string("America/New_York", "Timezone", group="New York Open")
- nyo_col = input.color(#00ff6a, "Line Color", group="New York Open")
- china_show = input.bool(false, "Show China Open Vertical Line", group="China Open")
- china_sess = input.string("0930-0931", "Open Time (HHMM-HHMM)", group="China Open")
- china_tz = input.string("Asia/Shanghai", "Timezone", group="China Open")
- china_col = input.color(#ffffff, "Line Color", group="China Open")
- akl_show = input.bool(false, "Show Auckland Open Vertical Line", group="Auckland Open")
- akl_sess = input.string("1000-1001", "Open Time (HHMM-HHMM)", group="Auckland Open")
- akl_tz = input.string("Pacific/Auckland", "Timezone", group="Auckland Open")
- akl_col = input.color(#00f2ff, "Line Color", group="Auckland Open")
- syd_show = input.bool(false, "Show Sydney Open Vertical Line", group="Sydney Open")
- syd_sess = input.string("1000-1001", "Open Time (HHMM-HHMM)", group="Sydney Open")
- syd_tz = input.string("Australia/Sydney", "Timezone", group="Sydney Open")
- syd_col = input.color(#4fc3f7, "Line Color", group="Sydney Open")
- del_show = input.bool(false, "Show New Delhi Open Vertical Line", group="New Delhi Open")
- del_sess = input.string("0915-0916", "Open Time (HHMM-HHMM)", group="New Delhi Open")
- del_tz = input.string("Asia/Kolkata", "Timezone", group="New Delhi Open")
- del_col = input.color(#ff9800, "Line Color", group="New Delhi Open")
- fra_show = input.bool(false, "Show Frankfurt Open Vertical Line", group="Frankfurt Open")
- fra_sess = input.string("0900-0901", "Open Time (HHMM-HHMM)", group="Frankfurt Open")
- fra_tz = input.string("Europe/Berlin", "Timezone", group="Frankfurt Open")
- fra_col = input.color(#ff007c, "Line Color", group="Frankfurt Open")
- chi_show = input.bool(false, "Show Chicago (CME) Open Vertical Line", group="Chicago (CME) Open")
- chi_sess = input.string("0830-0831", "Open Time (HHMM-HHMM)", group="Chicago (CME) Open")
- chi_tz = input.string("America/Chicago", "Timezone", group="Chicago (CME) Open")
- chi_col = input.color(#ffeb3b, "Line Color", group="Chicago (CME) Open")
- var array<line> open_vertical_lines = array.new<line>()
- var array<int> open_vertical_times = array.new<int>()
- var array<label> open_line_labels = array.new<label>()
- f_open_line(bool show, string txt, string sess, string tz, color col) =>
- string full = crypto_mode ? sess + ":1234567" : sess + ":23456"
- int t_hit = time(timeframe.period, full, tz)
- if show and is_within_lookback and not na(t_hit)
- array.push(open_vertical_lines, line.new(x1=time, y1=close, x2=time, y2=close, xloc=xloc.bar_time, color=col, style=line.style_solid, width=2, extend=extend.both))
- array.push(open_line_labels, label.new(x=time, y=high, text=txt, xloc=xloc.bar_time, color=box_lbl_bg, textcolor=col, style=label.style_label_down, size=size.normal))
- array.push(open_vertical_times, time)
- true
- f_open_line(london_show, "London Open", london_sess, london_tz, london_col)
- f_open_line(nyo_show, "New York Open", nyo_sess, nyo_tz, nyo_col)
- f_open_line(china_show, "China Open", china_sess, china_tz, china_col)
- f_open_line(akl_show, "Auckland Open", akl_sess, akl_tz, akl_col)
- f_open_line(syd_show, "Sydney Open", syd_sess, syd_tz, syd_col)
- f_open_line(del_show, "New Delhi Open", del_sess, del_tz, del_col)
- f_open_line(fra_show, "Frankfurt Open", fra_sess, fra_tz, fra_col)
- f_open_line(chi_show, "Chicago (CME) Open", chi_sess, chi_tz, chi_col)
- if array.size(open_vertical_lines) > 0
- for i = 0 to array.size(open_vertical_lines) - 1
- label.set_y(array.get(open_line_labels, i), high)
- for i = array.size(open_vertical_lines) - 1 to 0
- if (timenow - array.get(open_vertical_times, i)) > (line_duration_hrs * 3600000)
- line.delete(array.get(open_vertical_lines, i))
- label.delete(array.get(open_line_labels, i))
- array.remove(open_vertical_lines, i)
- array.remove(open_vertical_times, i)
- array.remove(open_line_labels, i)
Advertisement