Indicator · Pine Script v6 · On the chart

Initial Balance & Extensions with Z-Scores

by TamaraKGreen· code credited to notprofessogreen

This indicator plots the initial balance high, low, midpoint and optional Fibonacci levels for a user-defined session on the price chart.

View on GitHub

GitHub stars46on the repository
Pine versionv6current
Lines of code738
Settings40inputs
LicenceNone statedfile: MPL-2.0
Last update7 weeks ago4 Sep 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

738 lines of Pine Script v6 from Initial Balance & levels with stats.txt, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

Initial Balance & levels with stats.txt
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © notprofessogreen

//@version=6
indicator("Initial Balance & Extensions with Z-Scores", shorttitle="IB Extensions Z", overlay=true, max_bars_back=5000)
// Input Groups
var g_SESS = "========= Trading Sessions =========="
var g_INFO = "========= Display Options =========="
var g_IB_LINES = "========= IB Lines (IBH/IBL) =========="
var g_MID_LINES = "========= 50% & Fibonacci Lines =========="
var g_EXT_LINES = "========= Extension Lines =========="
var g_PERC_LINES = "========= Percentile Lines =========="
var g_TABLES = "========= Tables =========="
var g_GENERAL = "========= General Settings =========="

// Trading Sessions
ib_session = input.session("0830-0930", title="Initial Balance Period", group=g_SESS)
break_tracking_session = input.session("0930-1600", title="Break Tracking Session", group=g_SESS)

// Display Options
show_intermediate_levels = input.bool(true, "Show 50% & Fibonacci Levels", group=g_INFO)
show_ib_calculation_area = input.bool(false, "Highlight IB Calculation Period", group=g_INFO)
show_labels = input.bool(true, "Show All Labels", group=g_INFO)
fill_ib_areas = input.bool(true, "Fill IB Area", group=g_INFO)
only_current_levels = input.bool(false, "Only Current Day Levels", group=g_INFO)
only_current_zone = input.bool(true, "Only Current IB Zone", group=g_INFO)

// IB Lines (IBH/IBL)
show_ibh = input.bool(true, "Show IBH", inline="ibh", group=g_IB_LINES)
ib_high_color = input.color(color.gray, "", inline="ibh", group=g_IB_LINES)
ib_high_style = input.string("Solid", "", options=["Solid", "Dashed", "Dotted"], inline="ibh", group=g_IB_LINES)
ib_high_width = input.int(2, "", minval=1, maxval=4, inline="ibh", group=g_IB_LINES)

show_ibl = input.bool(true, "Show IBL", inline="ibl", group=g_IB_LINES)
ib_low_color = input.color(color.gray, "", inline="ibl", group=g_IB_LINES)
ib_low_style = input.string("Solid", "", options=["Solid", "Dashed", "Dotted"], inline="ibl", group=g_IB_LINES)
ib_low_width = input.int(2, "", minval=1, maxval=4, inline="ibl", group=g_IB_LINES)

// 50% & Fibonacci Lines
show_mid = input.bool(true, "Show 50% Line", inline="mid", group=g_MID_LINES)
mid_color = input.color(color.rgb(33, 149, 243, 60), "", inline="mid", group=g_MID_LINES)
mid_style = input.string("Dotted", "", options=["Solid", "Dashed", "Dotted"], inline="mid", group=g_MID_LINES)
mid_width = input.int(1, "", minval=1, maxval=4, inline="mid", group=g_MID_LINES)

fib1 = input.float(0.214, 'Fib Level 1', inline="fib1", group=g_MID_LINES)
fib1_show = input.bool(true, '', inline="fib1", group=g_MID_LINES)
fib_color = input.color(color.rgb(33, 149, 243, 60), "", inline="fib1", group=g_MID_LINES)
fib_style = input.string("Dotted", "", options=["Solid", "Dashed", "Dotted"], inline="fib1", group=g_MID_LINES)
fib_width = input.int(1, "", minval=1, maxval=4, inline="fib1", group=g_MID_LINES)

fib2 = input.float(0.236, 'Fib Level 2', inline="fib2", group=g_MID_LINES)
fib2_show = input.bool(true, '', inline="fib2", group=g_MID_LINES)
fib3 = input.float(0.786, 'Fib Level 3', inline="fib3", group=g_MID_LINES)
fib3_show = input.bool(true, '', inline="fib3", group=g_MID_LINES)
fib4 = input.float(0.800, 'Fib Level 4', inline="fib4", group=g_MID_LINES)
fib4_show = input.bool(true, '', inline="fib4", group=g_MID_LINES)

// Extension Lines
show_extensions = input.bool(true, "Show Extensions", group=g_EXT_LINES)
show_mean_high = input.bool(true, "Show Mean High", inline="meanhigh", group=g_EXT_LINES)
show_median_high = input.bool(true, "Show Median High", inline="medianhigh", group=g_EXT_LINES)
show_mean_low = input.bool(true, "Show Mean Low", inline="meanlow", group=g_EXT_LINES)
show_median_low = input.bool(true, "Show Median Low", inline="medianlow", group=g_EXT_LINES)

ext_color = input.color(color.teal, "Extension Color", inline="extcolor", group=g_EXT_LINES)
ext_style = input.string("Dashed", "Style", options=["Solid", "Dashed", "Dotted"], inline="extcolor", group=g_EXT_LINES)
ext_width = input.int(1, "Width", minval=1, maxval=4, inline="extcolor", group=g_EXT_LINES)

show_sd1 = input.bool(true, "Show 1 SD", inline="sd1", group=g_EXT_LINES)
show_sd2 = input.bool(true, "Show 2 SD", inline="sd1", group=g_EXT_LINES)
show_sd3 = input.bool(false, "Show 3 SD", inline="sd2", group=g_EXT_LINES)
show_sd4 = input.bool(false, "Show 4 SD", inline="sd2", group=g_EXT_LINES)
z_score_threshold = input.float(2.0, "Z-Score Threshold", minval=0.5, step=0.1, group=g_EXT_LINES)

// Percentile Lines
show_percentiles = input.bool(true, "Show Percentiles", group=g_PERC_LINES)
show_p25_high = input.bool(true, "Show 25th %ile High", inline="p25h", group=g_PERC_LINES)
show_p75_high = input.bool(true, "Show 75th %ile High", inline="p25h", group=g_PERC_LINES)
show_p25_low = input.bool(true, "Show 25th %ile Low", inline="p25l", group=g_PERC_LINES)
show_p75_low = input.bool(true, "Show 75th %ile Low", inline="p25l", group=g_PERC_LINES)

percentile_color = input.color(color.purple, "Percentile Color", inline="perccolor", group=g_PERC_LINES)
percentile_style = input.string("Solid", "Style", options=["Solid", "Dashed", "Dotted"], inline="perccolor", group=g_PERC_LINES)
percentile_width = input.int(2, "Width", minval=1, maxval=4, inline="perccolor", group=g_PERC_LINES)

// Tables
show_delta_analytics = input.bool(true, "Show IB Stats Table", group=g_TABLES)
table_position = input.string('Top Right', "IB Stats Position", options=['Bottom Center', 'Bottom Left', 'Bottom Right', 'Middle Center', 'Middle Left', 'Middle Right', 'Top Center', 'Top Left', 'Top Right'], group=g_TABLES)
table_size = input.string('Tiny', "IB Stats Text Size", options=['Auto', 'Tiny', 'Small', 'Normal', 'Large', 'Huge'], group=g_TABLES)
table_text = input.color(color.black, "IB Stats Text Color", group=g_TABLES)
table_bg = input.color(color.white, "IB Stats Background", group=g_TABLES)
table_frame = input.color(color.black, "IB Stats Frame", group=g_TABLES)
table_border = input.color(color.black, "IB Stats Border", group=g_TABLES)
table_border_width = input.int(1, "IB Stats Border Width", group=g_TABLES)
table_frame_width = input.int(2, "IB Stats Frame Width", group=g_TABLES)

show_z_score_table = input.bool(true, "Show Z-Score Table", group=g_TABLES)
z_table_position = input.string("Bottom Left", "Z-Score Position", options=['Bottom Center', 'Bottom Left', 'Bottom Right', 'Middle Center', 'Middle Left', 'Middle Right', 'Top Center', 'Top Left', 'Top Right'], group=g_TABLES)
z_table_size = input.string('Tiny', "Z-Score Text Size", options=['Auto', 'Tiny', 'Small', 'Normal', 'Large', 'Huge'], group=g_TABLES)
z_table_text = input.color(color.black, "Z-Score Text Color", group=g_TABLES)
z_table_bg = input.color(color.white, "Z-Score Background", group=g_TABLES)
z_table_frame = input.color(color.black, "Z-Score Frame", group=g_TABLES)
z_table_border = input.color(color.black, "Z-Score Border", group=g_TABLES)
z_table_border_width = input.int(1, "Z-Score Border Width", group=g_TABLES)
z_table_frame_width = input.int(2, "Z-Score Frame Width", group=g_TABLES)

// General Settings
label_size = input.string("Small", "Label Size", options=["Auto", "Huge", "Large", "Normal", "Small", "Tiny"], group=g_GENERAL)
extend_level = input.string("Right", "Extend Lines", options=["Right", "Left", "Both", "None"], group=g_GENERAL)
fill_ib_color = input.color(color.rgb(33, 149, 243, 80), "IB Fill Color", group=g_GENERAL)
ext = extend_level == "Right" ? extend.right : extend_level == "Left" ? extend.left : extend_level == "Both" ? extend.both : extend.none

// Arrays for historical data
var delta_history = array.new_float(0)
var float[] high_extensions = array.new_float(0)
var float[] low_extensions = array.new_float(0)
var float[] high_break_extensions = array.new_float(0)
var float[] low_break_extensions = array.new_float(0)

inSession(sess) =>
    na(time(timeframe.period, sess)) == false

get_line_style(s) =>
    s == "Solid" ? line.style_solid : s == "Dotted" ? line.style_dotted : line.style_dashed

get_levels(n) =>
    h = high[1]
    l = low[1]
    for i = 1 to n
        if low[i] < l
            l := low[i]
        if high[i] > h
            h := high[i]
    [h, l, (h + l) / 2]

get_table_position(pos) =>
    result = 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

get_table_text_size(size) =>
    result = switch size
        'Auto' => size.auto
        'Tiny' => size.tiny
        'Small' => size.small
        'Normal' => size.normal
        'Large' => size.large
        'Huge' => size.huge

var line ibh = na
var line ibl = na
var line ibm = na
var line fib_ln_1 = na
var line fib_ln_2 = na
var line fib_ln_3 = na
var line fib_ln_4 = na
var label labelh = na
var label labell = na
var label labelm = na
var label labelfib1 = na
var label labelfib2 = na
var label labelfib3 = na
var label labelfib4 = na
var box ib_area = na

// Extension lines
var line mean_high_ext_line = na
var line median_high_ext_line = na
var line mean_low_ext_line = na
var line median_low_ext_line = na
var line sd1_high_line = na
var line sd2_high_line = na
var line sd3_high_line = na
var line sd4_high_line = na
var line sd1_low_line = na
var line sd2_low_line = na
var line sd3_low_line = na
var line sd4_low_line = na
var line sd_high_line = na
var line sd_low_line = na

// Percentile lines
var line p25_high_line = na
var line p75_high_line = na
var line p25_low_line = na
var line p75_low_line = na

// Z-Score Variables
var float z_score_ib_delta = na
var float z_score_high_ext = na
var float z_score_low_ext = na
var line z_score_ib_line = na
var label z_score_ib_label = na
var table z_score_table = na
var float breakout_prob = na

labelSize = (label_size == "Huge") ? size.huge :
     (label_size == "Large") ? size.large :
     (label_size == "Small") ? size.small :
     (label_size == "Tiny") ? size.tiny :
     (label_size == "Auto") ? size.auto : size.normal

var offset = 0
var float ib_delta = na
var float current_high_ext = na
var float current_low_ext = na
var float ib_high = na
var float ib_low = na
var bool ib_formed = false

ins = inSession(ib_session)

bgcolor(show_ib_calculation_area and ins ? #673ab730 : na, title="IB calculation zone")

if ins
    offset += 1

if ins[1] and not ins
    [h, l, m] = get_levels(offset)
    ib_delta := h - l
    array.push(delta_history, ib_delta)
    
    // Store IB levels and reset extension tracking
    ib_high := h
    ib_low := l
    ib_formed := true
    current_high_ext := h
    current_low_ext := l

    // 1. Analyze IB Range Z-Score
    if array.size(delta_history) >= 2
        mean_delta = array.avg(delta_history)
        sd_delta = array.stdev(delta_history)
        z_score_ib_delta := (ib_delta - mean_delta) / sd_delta
        line.delete(z_score_ib_line)
        label.delete(z_score_ib_label)
        if show_intermediate_levels
            z_score_ib_line := line.new(bar_index[offset], m, bar_index, m, color=color.purple, style=line.style_dashed, width=1)
            if show_labels
                z_score_ib_label := label.new(bar_index[offset], m, "Z-Score 50% IB: " + str.tostring(z_score_ib_delta, "#.##"), 
                                             style=label.style_none, textcolor=color.purple, size=labelSize)

    line.set_extend(ibh, extend.none)
    line.set_extend(ibl, extend.none)
    if show_intermediate_levels
        line.set_extend(ibm, extend.none)
        if fib1_show
            line.set_extend(fib_ln_1, extend.none)
        if fib2_show
            line.set_extend(fib_ln_2, extend.none)
        if fib3_show
            line.set_extend(fib_ln_3, extend.none)
        if fib4_show
            line.set_extend(fib_ln_4, extend.none)
    
    if show_labels
        if only_current_levels
            label.delete(labelh)
            label.delete(labell)
            if show_intermediate_levels
                label.delete(labelm)
        labelh := label.new(bar_index[offset], h, text="IBH: " + str.tostring(h), style=label.style_none, textcolor=ib_high_color, size=labelSize)
        labell := label.new(bar_index[offset], l, text="IBL: " + str.tostring(l), style=label.style_none, textcolor=ib_low_color, size=labelSize)
        
        // Fixed: Only show intermediate level labels when both show_labels AND show_intermediate_levels are true
        if show_intermediate_levels
            if only_current_levels
                label.delete(labelm)
                if fib1_show
                    label.delete(labelfib1)
                if fib2_show
                    label.delete(labelfib2)
                if fib3_show
                    label.delete(labelfib3)
                if fib4_show
                    label.delete(labelfib4)
            labelm := label.new(bar_index[offset], m, text="50%: " + str.tostring(m), style=label.style_none, textcolor=mid_color, size=labelSize)

    // Fixed: Only create Fibonacci labels when respective show flags are true AND show_labels AND show_intermediate_levels are true
    if show_labels and show_intermediate_levels
        if fib1_show
            labelfib1 := label.new(bar_index[offset], l + (h - l) * fib1, text=str.tostring(fib1), style=label.style_none, textcolor=fib_color, size=labelSize)
        if fib2_show
            labelfib2 := label.new(bar_index[offset], l + (h - l) * fib2, text=str.tostring(fib2), style=label.style_none, textcolor=fib_color, size=labelSize)
        if fib3_show
            labelfib3 := label.new(bar_index[offset], l + (h - l) * fib3, text=str.tostring(fib3), style=label.style_none, textcolor=fib_color, size=labelSize)
        if fib4_show
            labelfib4 := label.new(bar_index[offset], l + (h - l) * fib4, text=str.tostring(fib4), style=label.style_none, textcolor=fib_color, size=labelSize)
    
    if fill_ib_areas
        if only_current_zone
            box.delete(ib_area)
        ib_area := box.new(bar_index[offset], h, bar_index, l, bgcolor=fill_ib_color, border_color=#00000000)
    if only_current_levels
        line.delete(ibh)
        line.delete(ibl)
        if show_intermediate_levels
            line.delete(ibm)
            if fib1_show
                line.delete(fib_ln_1)
            if fib2_show
                line.delete(fib_ln_2)
            if fib3_show
                line.delete(fib_ln_3)
            if fib4_show
                line.delete(fib_ln_4)
     
    ibh := line.new(bar_index[offset], h, bar_index, h, color=ib_high_color, extend=ext, width=ib_high_width, style=get_line_style(ib_high_style))
    ibl := line.new(bar_index[offset], l, bar_index, l, color=ib_low_color, extend=ext, width=ib_low_width, style=get_line_style(ib_low_style))
    if show_intermediate_levels
        ibm := line.new(bar_index[offset], m, bar_index, m, color=mid_color, style=get_line_style(mid_style), extend=ext, width=mid_width)
        if fib1_show
            fib_ln_1 := line.new(bar_index[offset], l + (h - l) * fib1, bar_index, l + (h - l) * fib1, color=fib_color, style=get_line_style(fib_style), extend=ext, width=fib_width)
        if fib2_show
            fib_ln_2 := line.new(bar_index[offset], l + (h - l) * fib2, bar_index, l + (h - l) * fib2, color=fib_color, style=get_line_style(fib_style), extend=ext, width=fib_width)
        if fib3_show
            fib_ln_3 := line.new(bar_index[offset], l + (h - l) * fib3, bar_index, l + (h - l) * fib3, color=fib_color, style=get_line_style(fib_style), extend=ext, width=fib_width)
        if fib4_show    
            fib_ln_4 := line.new(bar_index[offset], l + (h - l) * fib4, bar_index, l + (h - l) * fib4, color=fib_color, style=get_line_style(fib_style), extend=ext, width=fib_width)    
    
    // Plot extensions
    if show_extensions
        mean_high_ext = array.avg(high_extensions)
        median_high_ext = array.median(high_extensions)
        mean_low_ext = array.avg(low_extensions)
        median_low_ext = array.median(low_extensions)
        high_sd = array.stdev(high_extensions)
        low_sd = array.stdev(low_extensions)
        
        line.delete(mean_high_ext_line)
        line.delete(median_high_ext_line)
        line.delete(mean_low_ext_line)
        line.delete(median_low_ext_line)
        line.delete(sd1_high_line)
        line.delete(sd2_high_line)
        line.delete(sd3_high_line)
        line.delete(sd4_high_line)
        line.delete(sd1_low_line)
        line.delete(sd2_low_line)
        line.delete(sd3_low_line)
        line.delete(sd4_low_line)
        line.delete(sd_high_line)
        line.delete(sd_low_line)
        line.delete(p25_high_line)
        line.delete(p75_high_line)
        line.delete(p25_low_line)
        line.delete(p75_low_line)
        
        if show_mean_high and not na(mean_high_ext)
            mean_high_ext_line := line.new(bar_index[offset], ib_high + mean_high_ext, bar_index, ib_high + mean_high_ext, 
                                          color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_high + mean_high_ext, "Mean High Ext: " + str.tostring(mean_high_ext, "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
        
        if show_median_high and not na(median_high_ext)
            median_high_ext_line := line.new(bar_index[offset], ib_high + median_high_ext, bar_index, ib_high + median_high_ext,
                                             color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_high + median_high_ext, "Median High Ext: " + str.tostring(median_high_ext, "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
                
        if show_mean_low and not na(mean_low_ext)
            mean_low_ext_line := line.new(bar_index[offset], ib_low - mean_low_ext, bar_index, ib_low - mean_low_ext, 
                                         color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_low - mean_low_ext, "Mean Low Ext: " + str.tostring(mean_low_ext, "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
        
        if show_median_low and not na(median_low_ext)
            median_low_ext_line := line.new(bar_index[offset], ib_low - median_low_ext, bar_index, ib_low - median_low_ext, 
                                           color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_low - median_low_ext, "Median Low Ext: " + str.tostring(median_low_ext, "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
        
        // Add percentile lines for break extensions
        if show_percentiles and show_p25_high and array.size(high_break_extensions) > 0
            high_break_25th = array.percentile_linear_interpolation(high_break_extensions, 25)
            
            if not na(high_break_25th)
                p25_high_line := line.new(bar_index[offset], ib_high + high_break_25th, bar_index, ib_high + high_break_25th, 
                                         color=percentile_color, extend=ext, style=get_line_style(percentile_style), width=percentile_width)
                if show_labels
                    label.new(bar_index[offset], ib_high + high_break_25th, "25th %ile", 
                             style=label.style_none, textcolor=percentile_color, size=labelSize)
        
        if show_percentiles and show_p75_high and array.size(high_break_extensions) > 0
            high_break_75th = array.percentile_linear_interpolation(high_break_extensions, 75)
            
            if not na(high_break_75th)
                p75_high_line := line.new(bar_index[offset], ib_high + high_break_75th, bar_index, ib_high + high_break_75th, 
                                         color=percentile_color, extend=ext, style=get_line_style(percentile_style), width=percentile_width)
                if show_labels
                    label.new(bar_index[offset], ib_high + high_break_75th, "75th %ile", 
                             style=label.style_none, textcolor=percentile_color, size=labelSize)
        
        if show_percentiles and show_p25_low and array.size(low_break_extensions) > 0
            low_break_25th = array.percentile_linear_interpolation(low_break_extensions, 25)
            
            if not na(low_break_25th)
                p25_low_line := line.new(bar_index[offset], ib_low - low_break_25th, bar_index, ib_low - low_break_25th,
                                         color=percentile_color, extend=ext, style=get_line_style(percentile_style), width=percentile_width)
                if show_labels
                    label.new(bar_index[offset], ib_low - low_break_25th, "25th %ile", 
                             style=label.style_none, textcolor=percentile_color, size=labelSize)
        
        if show_percentiles and show_p75_low and array.size(low_break_extensions) > 0
            low_break_75th = array.percentile_linear_interpolation(low_break_extensions, 75)
            
            if not na(low_break_75th)
                p75_low_line := line.new(bar_index[offset], ib_low - low_break_75th, bar_index, ib_low - low_break_75th,
                                         color=percentile_color, extend=ext, style=get_line_style(percentile_style), width=percentile_width)
                if show_labels
                    label.new(bar_index[offset], ib_low - low_break_75th, "75th %ile", 
                             style=label.style_none, textcolor=percentile_color, size=labelSize)
                        
        // SD Levels
        if show_sd1 and not na(high_sd)
            sd1_high_line := line.new(bar_index[offset], ib_high + mean_high_ext + high_sd, bar_index, ib_high + mean_high_ext + high_sd, 
                                     color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_high + mean_high_ext + high_sd, "1 SD High: " + str.tostring(mean_high_ext + high_sd, "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
            sd1_low_line := line.new(bar_index[offset], ib_low - mean_low_ext - low_sd, bar_index, ib_low - mean_low_ext - low_sd,
                                     color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_low - mean_low_ext - low_sd, "1 SD Low: " + str.tostring(mean_low_ext + low_sd, "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
        
        if show_sd2 and not na(high_sd)
            sd2_high_line := line.new(bar_index[offset], ib_high + mean_high_ext + (high_sd * 2), bar_index, ib_high + mean_high_ext + (high_sd * 2), 
                                     color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_high + mean_high_ext + (high_sd * 2), "2 SD High: " + str.tostring(mean_high_ext + (high_sd * 2), "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
            sd2_low_line := line.new(bar_index[offset], ib_low - mean_low_ext - (low_sd * 2), bar_index, ib_low - mean_low_ext - (low_sd * 2),
                                     color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_low - mean_low_ext - (low_sd * 2), "2 SD Low: " + str.tostring(mean_low_ext + (low_sd * 2), "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
        
        if show_sd3 and not na(high_sd)
            sd3_high_line := line.new(bar_index[offset], ib_high + mean_high_ext + (high_sd * 3), bar_index, ib_high + mean_high_ext + (high_sd * 3), 
                                     color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_high + mean_high_ext + (high_sd * 3), "3 SD High: " + str.tostring(mean_high_ext + (high_sd * 3), "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
            sd3_low_line := line.new(bar_index[offset], ib_low - mean_low_ext - (low_sd * 3), bar_index, ib_low - mean_low_ext - (low_sd * 3),
                                     color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_low - mean_low_ext - (low_sd * 3), "3 SD Low: " + str.tostring(mean_low_ext + (low_sd * 3), "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
        
        if show_sd4 and not na(high_sd)
            sd4_high_line := line.new(bar_index[offset], ib_high + mean_high_ext + (high_sd * 4), bar_index, ib_high + mean_high_ext + (high_sd * 4), 
                                     color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_high + mean_high_ext + (high_sd * 4), "4 SD High: " + str.tostring(mean_high_ext + (high_sd * 4), "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
            sd4_low_line := line.new(bar_index[offset], ib_low - mean_low_ext - (low_sd * 4), bar_index, ib_low - mean_low_ext - (low_sd * 4),
                                     color=ext_color, extend=ext, style=get_line_style(ext_style), width=ext_width)
            if show_labels
                label.new(bar_index[offset], ib_low - mean_low_ext - (low_sd * 4), "4 SD Low: " + str.tostring(mean_low_ext + (low_sd * 4), "#.##"), 
                         style=label.style_none, textcolor=ext_color, size=labelSize)
    
    offset := 0

// Track extensions after IB is formed
if ib_formed and not ins
    if high > current_high_ext
        current_high_ext := high
    if low < current_low_ext
        current_low_ext := low

// When new IB starts, store previous extensions and calculate z-scores
if not ins[1] and ins and ib_formed
    if not na(current_high_ext) and not na(ib_high)
        high_ext_value = current_high_ext - ib_high
        array.push(high_extensions, high_ext_value)
        if array.size(high_extensions) >= 2
            mean_high_ext = array.avg(high_extensions)
            high_sd = array.stdev(high_extensions)
            z_score_high_ext := (high_ext_value - mean_high_ext) / high_sd
            if show_extensions and not na(z_score_high_ext) and math.abs(z_score_high_ext) >= z_score_threshold
                line.delete(sd_high_line)
                sd_high_line := line.new(bar_index[offset], current_high_ext, bar_index, current_high_ext,
                                         color=color.orange, extend=ext, style=line.style_dashed)
                if show_labels
                    label.new(bar_index[offset], current_high_ext, "Dynamic High Z=" + str.tostring(z_score_high_ext, "#.##"), 
                             style=label.style_none, textcolor=color.orange, size=labelSize)

    if not na(current_low_ext) and not na(ib_low)
        low_ext_value = ib_low - current_low_ext
        array.push(low_extensions, low_ext_value)
        if array.size(low_extensions) >= 2
            mean_low_ext = array.avg(low_extensions)
            low_sd = array.stdev(low_extensions)
            z_score_low_ext := (low_ext_value - mean_low_ext) / low_sd
            if show_extensions and not na(z_score_low_ext) and math.abs(z_score_low_ext) >= z_score_threshold
                line.delete(sd_low_line)
                sd_low_line := line.new(bar_index[offset], current_low_ext, bar_index, current_low_ext, 
                                       color=color.orange, extend=ext, style=line.style_dashed)
                if show_labels
                    label.new(bar_index[offset], current_low_ext, "Dynamic Low Z=" + str.tostring(z_score_low_ext, "#.##"), 
                             style=label.style_none, textcolor=color.orange, size=labelSize)
    ib_formed := false

// Break tracking variables
var int[] historical_high_breaks = array.new_int(0)
var int[] historical_low_breaks = array.new_int(0)
var int[] historical_both_sides_break = array.new_int(0)
var int[] historical_no_breaks = array.new_int(0)

// Session tracking for current day
var bool high_broken_today = false
var bool low_broken_today = false
var bool session_recorded = false

// Track maximum extensions during break days
var float max_high_break_ext_today = 0.0
var float max_low_break_ext_today = 0.0

// Define break tracking session
break_ins = inSession(break_tracking_session)

// When IB session ends, reset break tracking for the day
if ins[1] and not ins
    high_broken_today := false
    low_broken_today := false
    session_recorded := false
    max_high_break_ext_today := 0.0
    max_low_break_ext_today := 0.0

// Real-time break detection during break tracking session after IB ends
if not ins and ib_formed and break_ins and not session_recorded
    // Check for breaks above IBH
    if high > ib_high and not high_broken_today
        high_broken_today := true
    
    // Check for breaks below IBL  
    if low < ib_low and not low_broken_today
        low_broken_today := true
    
    // Track maximum extensions on break days
    if high_broken_today
        current_high_ext = high - ib_high
        if current_high_ext > max_high_break_ext_today
            max_high_break_ext_today := current_high_ext
    
    if low_broken_today
        current_low_ext = ib_low - low
        if current_low_ext > max_low_break_ext_today
            max_low_break_ext_today := current_low_ext

// At the end of break tracking session, record the day's break pattern
if break_ins[1] and not break_ins and not session_recorded and ib_formed
    session_recorded := true
    
    if high_broken_today and low_broken_today
        array.push(historical_both_sides_break, bar_index)
        // Store extensions for both breaks
        array.push(high_break_extensions, max_high_break_ext_today)
        array.push(low_break_extensions, max_low_break_ext_today)
    else if high_broken_today
        array.push(historical_high_breaks, bar_index)
        // Store extension for high break
        array.push(high_break_extensions, max_high_break_ext_today)
    else if low_broken_today
        array.push(historical_low_breaks, bar_index)
        // Store extension for low break
        array.push(low_break_extensions, max_low_break_ext_today)
    else
        array.push(historical_no_breaks, bar_index)

if (not ins) and (not ins[1])
    line.set_x2(ibh, bar_index)
    line.set_x2(ibl, bar_index)
    if show_intermediate_levels and not na(ibm)
        line.set_x2(ibm, bar_index)
        if fib1_show and not na(fib_ln_1)
            line.set_x2(fib_ln_1, bar_index)
        if fib2_show and not na(fib_ln_2)
            line.set_x2(fib_ln_2, bar_index)
        if fib3_show and not na(fib_ln_3)
            line.set_x2(fib_ln_3, bar_index)
        if fib4_show and not na(fib_ln_4)
            line.set_x2(fib_ln_4, bar_index)
    if not na(z_score_ib_line)
        line.set_x2(z_score_ib_line, bar_index)
    if show_extensions
        if show_mean_high and not na(mean_high_ext_line)
            line.set_x2(mean_high_ext_line, bar_index)
        if show_median_high and not na(median_high_ext_line)
            line.set_x2(median_high_ext_line, bar_index)
        if show_mean_low and not na(mean_low_ext_line)
            line.set_x2(mean_low_ext_line, bar_index)
        if show_median_low and not na(median_low_ext_line)
            line.set_x2(median_low_ext_line, bar_index)
        if show_sd1 and not na(sd1_high_line)
            line.set_x2(sd1_high_line, bar_index)
        if show_sd2 and not na(sd2_high_line)
            line.set_x2(sd2_high_line, bar_index)
        if show_sd3 and not na(sd3_high_line)
            line.set_x2(sd3_high_line, bar_index)
        if show_sd4 and not na(sd4_high_line)
            line.set_x2(sd4_high_line, bar_index)
        if show_sd1 and not na(sd1_low_line)
            line.set_x2(sd1_low_line, bar_index)
        if show_sd2 and not na(sd2_low_line)
            line.set_x2(sd2_low_line, bar_index)
        if show_sd3 and not na(sd3_low_line)
            line.set_x2(sd3_low_line, bar_index)
        if show_sd4 and not na(sd4_low_line)
            line.set_x2(sd4_low_line, bar_index)
        if not na(sd_high_line)
            line.set_x2(sd_high_line, bar_index)
        if not na(sd_low_line)
            line.set_x2(sd_low_line, bar_index)
    if show_percentiles
        if show_p25_high and not na(p25_high_line)
            line.set_x2(p25_high_line, bar_index)
        if show_p75_high and not na(p75_high_line)
            line.set_x2(p75_high_line, bar_index)
        if show_p25_low and not na(p25_low_line)
            line.set_x2(p25_low_line, bar_index)
        if show_p75_low and not na(p75_low_line)
            line.set_x2(p75_low_line, bar_index)

var table ib_analytics = table.new(position.bottom_left, 20, 20)

ib_sentiment() =>
    h = array.max(delta_history)
    l = array.min(delta_history)
    a = array.avg(delta_history)
    h_comp = ib_delta > h ? ib_delta - h : (ib_delta - h) * -1
    l_comp = ib_delta > l ? ib_delta - l : (ib_delta - l) * -1
    a_comp = ib_delta > a ? ib_delta - a : (ib_delta - a) * -1
    (h_comp < l_comp and h_comp < a_comp) ? "Huge" : (l_comp < h_comp and l_comp < a_comp) ? "Small" : "Medium"

sd = array.stdev(delta_history)
med = array.median(delta_history)

total_high_breaks = array.size(historical_high_breaks)
total_low_breaks = array.size(historical_low_breaks)
total_both_sides_breaks = array.size(historical_both_sides_break)
total_no_breaks = array.size(historical_no_breaks)
sess_cnt = total_high_breaks + total_low_breaks + total_both_sides_breaks + total_no_breaks

// Z-Score Table
if show_z_score_table and barstate.islast
    z_score_table := table.new(
         position = get_table_position(z_table_position),
         columns = 2,
         rows = 5,
         bgcolor = z_table_bg,
         frame_color = z_table_frame,
         frame_width = z_table_frame_width,
         border_color = z_table_border,
         border_width = z_table_border_width
     )
    ts = get_table_text_size(z_table_size)

    table.cell(z_score_table, 0, 0, "Z-Score Stats", bgcolor=color.white, text_color=z_table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(z_score_table, 1, 0, "Value", bgcolor=color.white, text_color=z_table_text, text_size=ts, text_font_family=font.family_monospace)
    
    table.cell(z_score_table, 0, 1, "IB Range Z-Score", bgcolor=color.white, text_color=z_table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(z_score_table, 1, 1, str.tostring(z_score_ib_delta, "#.##"), bgcolor=color.white, text_color=math.abs(z_score_ib_delta) > 2 ? color.red : z_table_text, text_size=ts, text_font_family=font.family_monospace)
    
    table.cell(z_score_table, 0, 2, "High Ext Z-Score", bgcolor=color.white, text_color=z_table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(z_score_table, 1, 2, str.tostring(z_score_high_ext, "#.##"), bgcolor=color.white, text_color=math.abs(z_score_high_ext) > 2 ? color.red : z_table_text, text_size=ts, text_font_family=font.family_monospace)
    
    table.cell(z_score_table, 0, 3, "Low Ext Z-Score", bgcolor=color.white, text_color=z_table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(z_score_table, 1, 3, str.tostring(z_score_low_ext, "#.##"), bgcolor=color.white, text_color=math.abs(z_score_low_ext) > 2 ? color.red : z_table_text, text_size=ts, text_font_family=font.family_monospace)
    
    if array.size(historical_both_sides_break) + array.size(historical_high_breaks) + array.size(historical_low_breaks) > 0
        total_breaks = array.size(historical_high_breaks) + array.size(historical_low_breaks) + array.size(historical_both_sides_break)
        total_sessions = array.size(delta_history)
        breakout_prob := (total_breaks / total_sessions) * 100
        if not na(z_score_ib_delta) and z_score_ib_delta < 0
            breakout_prob := breakout_prob * (1 + math.abs(z_score_ib_delta) * 0.1)
    table.cell(z_score_table, 0, 4, "Breakout Probability", bgcolor=color.white, text_color=z_table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(z_score_table, 1, 4, str.tostring(breakout_prob, "#.##") + "%", bgcolor=color.white, text_color=z_table_text, text_size=ts, text_font_family=font.family_monospace)

// IB Stats Table
if show_delta_analytics and barstate.islast
    ib_analytics := table.new(
         position = get_table_position(table_position),
         columns = 2,
         rows = 20,
         bgcolor = table_bg,
         frame_color = table_frame,
         frame_width = table_frame_width,
         border_color = table_border,
         border_width = table_border_width
     )

    ts = get_table_text_size(table_size)

    table.cell(ib_analytics, 0, 0, "IB Stats", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 0, "Value", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 1, "IB max range", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 1, str.tostring(array.max(delta_history), "#.####"), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 2, "IB average range", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 2, str.tostring(array.avg(delta_history), "#.####"), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 3, "IB min range", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 3, str.tostring(array.min(delta_history), "#.####"), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 4, "Today's range", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 4, str.tostring(ib_delta), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 5, "IB range standard deviation", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 5, str.tostring(math.round(sd, 2)), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 6, "IB range median", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 6, str.tostring(math.round(med, 2)), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 7, "Total IB high breaks", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 7, str.tostring(total_high_breaks), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 8, "Total IB low breaks", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 8, str.tostring(total_low_breaks), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 9, "No break", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 9, str.tostring(total_no_breaks), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 10, "Both side break", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 10, str.tostring(total_both_sides_breaks), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 11, "Total IB sessions", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 11, str.tostring(sess_cnt), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 12, "Mean High Extension", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 12, str.tostring(array.avg(high_extensions), "#.####"), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 13, "Median High Extension", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 13, str.tostring(array.median(high_extensions), "#.####"), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 14, "Mean Low Extension", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 14, str.tostring(array.avg(low_extensions), "#.####"), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 0, 15, "Median Low Extension", bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)
    table.cell(ib_analytics, 1, 15, str.tostring(array.median(low_extensions), "#.####"), bgcolor=color.white, text_color=table_text, text_size=ts, text_font_family=font.family_monospace)

Overview

Initial Balance & Extensions with Z-Scores tracks a separate break session and includes settings groups for extension lines, percentile lines and tables. Users can show or hide the IB high and low, the midpoint, labels and area fills, and limit drawings to the current day or current zone. Line colors, styles and widths are adjustable. No entry or exit rules are defined.

Details

Published by

TamaraKGreen on GitHub

Code credit

notprofessogreen, as written in the script's header

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

Sessions & time, Support & resistance, Screeners & dashboards

Markets

Any symbol

Timeframes

M15-H1

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Initial Balance Periodsession0830-0930ib_session
Break Tracking Sessionsession0930-1600break_tracking_session
Show 50% & Fibonacci Levelsbooltrueshow_intermediate_levels
Highlight IB Calculation Periodboolfalseshow_ib_calculation_area
Show All Labelsbooltrueshow_labels
Fill IB Areabooltruefill_ib_areas
Only Current Day Levelsboolfalseonly_current_levels
Only Current IB Zonebooltrueonly_current_zone
Show IBHbooltrueshow_ibh
ib_high_colorcolorcolor.grayib_high_color
ib_high_stylestringSolidib_high_style
ib_high_widthint2ib_high_width
Show all 40 settings
SettingTypeDefaultVariable
Show IBLbooltrueshow_ibl
ib_low_colorcolorcolor.grayib_low_color
ib_low_stylestringSolidib_low_style
ib_low_widthint2ib_low_width
Show 50% Linebooltrueshow_mid
mid_colorcolorcolor.rgb(33, 149, 243, 60)mid_color
mid_stylestringDottedmid_style
mid_widthint1mid_width
Fib Level 1float0.214fib1
fib1_showbooltruefib1_show
fib_colorcolorcolor.rgb(33, 149, 243, 60)fib_color
fib_stylestringDottedfib_style
fib_widthint1fib_width
Fib Level 2float0.236fib2
fib2_showbooltruefib2_show
Fib Level 3float0.786fib3
fib3_showbooltruefib3_show
Fib Level 4float0.800fib4
fib4_showbooltruefib4_show
Show Extensionsbooltrueshow_extensions
Show Mean Highbooltrueshow_mean_high
Show Median Highbooltrueshow_median_high
Show Mean Lowbooltrueshow_mean_low
Show Median Lowbooltrueshow_median_low
Extension Colorcolorcolor.tealext_color
StylestringDashedext_style
Widthint1ext_width
Show 1 SDbooltrueshow_sd1
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

575 stars

This indicator builds Market Profile Time Price Opportunity (TPO) structures across defined session timeframes directly on the main price chart. It visualizes the Point of Control (POC) and Value Area boundaries using dynamic box drawings. An integrated multi-

Indicator v5 Support & resistanceScreeners & dashboards
Updated 1 year ago · MPL-2.0 GitHub repository of Market Profile with Screener
257 stars

This indicator overlays an intraday SPX and ES chart with a midnight session range, regular-trading-hours opening levels, and a VWAP projection box. It draws the midnight high, mid, and low, flags edge rejections within an absolute tolerance, and plots optiona

Indicator v6 TrendSupport & resistance
Updated 6 weeks ago · None stated GitHub repository of SPX Midnight Box + Snag Logic

Golden Bullet Strategy

by TradersPost
218 stars

The Golden Bullet Strategy is an overlay signal indicator based on Smart Money Concepts and time-based liquidity models. It identifies liquidity sweeps of a designated reference session range during a specified hunt window. It then confirms Market Structure Sh

Indicator v6 SMC / ICT / price actionSessions & time
Updated 3 months ago · None stated GitHub repository of Golden Bullet Strategy

Session Edge Probabilities

by TraderOracle
61 stars

Session Edge Probabilities tracks eight session-based trading rules using statistical probabilities evaluated on historical chart data. It utilizes a fixed calculation timeframe to evaluate opening ranges, midnight levels, afternoon reversal windows, and price

Indicator v6 Sessions & timeScreeners & dashboards
Updated 9 days ago · None stated GitHub repository of Session Edge Probabilities
56 stars

This indicator marks forex trading sessions and opening ranges on the price chart. It can draw Sydney, Tokyo, Frankfurt, London, and New York session boxes or five- and fifteen-minute opening ranges, plus an optional opening channel and a day-open range. Day r

Indicator v5 Sessions & timeSupport & resistance Repaints
Updated 2 months ago · None stated GitHub repository of Day Trading Booster by DGT

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers