SMC Rules
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Swiss_Traders

//@version=5
indicator("Flutschi - SMC Rules", overlay=true, max_boxes_count=500, max_labels_count=500, max_lines_count=500, max_bars_back=1000)

//Visitiblity Section
visibility_group = "Visibility"
inside_bar_show = input.bool(true, "Show Inside Bar", group = visibility_group)
show_imbalance = input.bool(true, "Show Imbalances", group = visibility_group)
show_rules = input.bool(true, "Show Rules", group=visibility_group)
show_session = input.bool(false, "Show Trading Sessions Bars", group=visibility_group)
show_box = input.bool(false, "Show Boxes Sessions", group=visibility_group, inline="boxes")
show_box_history = input.bool(true, "Show Boxes History", group=visibility_group, inline="boxes")
show_lines = input.bool(false, "Show Lines", group=visibility_group)
show_pips = input.bool(false, "Show Pips (beta)", group=visibility_group, tooltip = "Use this on higher timeframe then 5m, somehow it breaks below that..", inline="pips")
show_pips_history = input.bool(true, "Show Pips History", group=visibility_group, inline="pips")

// Start Session

session_group 					= "Start Session Group"
show_session_color 				= input.bool(true, "Show Sessions", group = session_group)
show_fr_session_color 			= input.bool(true, "Frankfurt", group = session_group, inline="sess")
show_ln_session_color 			= input.bool(true, "London", group = session_group, inline="sess")
show_ny_session_color 			= input.bool(true, "New York", group = session_group, inline="sess")
show_as_session_color  			= input.bool(true, "Asia", group = session_group, inline="sess")
fr_session_color 				= input.color(color.red, "Frankfurt", group = session_group, inline="sess_color")
ln_session_color	 			= input.color(color.red, "London", group = session_group, inline="sess_color")
ny_session_color		 		= input.color(color.red, "New York", group = session_group, inline="sess_color")
as_session_color		 		= input.color(color.red, "Asia", group = session_group, inline="sess_color")


fr_session = false
ln_session = false
ny_session = false
as_session = false
if show_session_color
	if show_fr_session_color
		fr_session := not na(time(timeframe.period, "0200-0201"))
	if show_ln_session_color
		ln_session := not na(time(timeframe.period, "0300-0301"))
	if show_ny_session_color
		ny_session := not na(time(timeframe.period, "0800-0801"))
	if show_as_session_color
		as_session := not na(time(timeframe.period, "2100-2101"))

barcolor(fr_session ? fr_session_color : na)
barcolor(ln_session ? ln_session_color : na)
barcolor(ny_session ? ny_session_color : na)
barcolor(as_session ? as_session_color : na)



//Rules Section

table_color_groups 	= "Table Settings"
bg_table_color  	= input.color(#e0fff5, "Table Color", group = table_color_groups, inline = "02")
bg_border_color  	= input.color(color.new(color.green, 70), "Table Border", group = table_color_groups, inline = "02")
title_text_color 	= input.color(color.blue, "Table Title", group = table_color_groups, inline = "02")
farme_color 		= input.color(color.gray, "Frame Color", group = table_color_groups, inline = "02")	

table_width 		= input.int(3, 'Table Width', minval=1, group=table_color_groups, inline = "03")
frame_width 		= input.int(3, 'Frame Width', minval=1, group=table_color_groups, inline = "03")

table_text_size 	= input.string("Large", "Text Size", options = ["Small", "Normal", "Large"], group = "Table Text Size")
h1_size = size.huge //big title
h2_size = size.large //titles
h3_size = size.normal //text
h4_size = size.small //footer
switch table_text_size
    "Large" => 
        h1_size := size.huge
        h2_size := size.large
        h3_size := size.normal
		h4_size := size.small
    "Normal" => 
        h1_size := size.large
        h2_size := size.normal
        h3_size := size.small
		h4_size := size.tiny
    "Small" => 
        h1_size := size.normal
        h2_size := size.small
        h3_size := size.tiny
		h4_size := size.tiny

trend_settings_group = "Trend Settings"
general_group = "General"
market_structure_group = "Market Structure"
snd_group = "Supply & Demand"
liquidity_group = "Liquidity"
more_confluences_group = "More Confluences"
before_trade_group = "Before Trade"
table_footers = "Footers"

table_title = "Rules"

headerColor = color.new(color.blue, 80)
infoColor = color.new(color.red, 80)

Trend_Title 							= input.string("Trend Settings", "General Title", group = trend_settings_group)
swing_structure_4h 						= input.string("Bearish", "4h Swing Structure", options = ["Bearish", "Bullish"], group = trend_settings_group)
swing_structure_15m 					= input.string("Bearish", "15m Swing Structure", options = ["Bearish", "Bullish"], group = trend_settings_group)
swing_structure_color_bull 				= input.color(#abe69b, "Bull", group = "Colors", inline = "01")
swing_structure_color_bear 				= input.color(#ffdbd2, "Bear", group = "Colors", inline = "01")
swing_structure_4h_color 				= color.green
swing_structure_15m_color 				= color.green

if swing_structure_4h == "Bearish"
	swing_structure_4h_color := swing_structure_color_bear
else
	swing_structure_4h_color := swing_structure_color_bull
if swing_structure_15m == "Bearish"
	swing_structure_15m_color := swing_structure_color_bear
else
	swing_structure_15m_color := swing_structure_color_bull

General_Title = input.string("General Infos", "General Title", group = general_group)
General_Infos = input.text_area("!! Dont trade outside Peak Hours !!\nalways take the extreme, unless the flip sweeps!", "General Infos", group = general_group, tooltip = "use '\\n' for new line")

Market_Structure_Title = input.string("Market Structure", "Market Structure Title", group = market_structure_group)
Market_Structure_Info = input.text_area("4h comes first, then you do 15m.\n(4h = 80 Pips, 15m = 30 Pips)", "Market Structure Info", group = market_structure_group, tooltip = "use '\\n' for new line")


SnD_Title = input.string("Supply & Demand", "Supply & Demand Title", group = snd_group)
SnD_Info = input.text_area("We focus on 15m POI's, but we dont ignore 4h!\nmore confluences are:\nSweeps\nInteractions (Flip zones)\nInducement\nPvsD (Premium vs Discount)\nMitigation", "Supply & Demand Info", group = snd_group, tooltip = "use '\\n' for new line")


Liquidity_Title = input.string("Liquidity", "Liquidity Title", group = liquidity_group)
Liquidity_Info = input.text_area("Its either 'Inducements' or 'Sweep Zones'\nIt's mostly Equal Highs/Lows that get swept.", "Liquidity Info", group = liquidity_group, tooltip = "use '\\n' for new line")


more_confluences_title = input.string("More Confluences", "More Confluences Title", group = more_confluences_group)
more_confluences_info = input.text_area("PvsD (Premium vs Discount)\nSession Ranges (Asia mostly..)\nHTF Extremes", "More Confluences Info", group = more_confluences_group, tooltip = "use '\\n' for new line")


before_trade_title = input.string("Before you take a trade", "Before Trade Title", group = before_trade_group)
before_trade_info = input.text_area("Is the price near the HFT POI?\nDid the price take any LQ and left any LQ behind?\nDid you get Wyckoff at all?\nIf no, please, for the love of god, dont take the trade!", "Before Trade Info", group = before_trade_group, tooltip = "use '\\n' for new line")

table_footer = "Many thanks to the people in this Discord\nhttps://discord.gg/5resvCpZEr"

var maTable = table.new(
     position=position.top_right, columns=2, rows=21, bgcolor=bg_table_color, 
     frame_color=farme_color, frame_width=frame_width, border_color=bg_border_color, border_width=table_width)
     
if barstate.islast and show_rules
	Cell = 0

	// Header
	table.cell(maTable, 0, 0, text = table_title, text_size = h1_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)
	
	//Trend Settings
	Cell += 1
	table.cell(maTable, 0, Cell, text = Trend_Title, text_color = title_text_color, text_size = h2_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)
	Cell += 1
	table.cell(maTable, 0, Cell, text = "4h Swing Structure")
	table.cell(maTable, 1, Cell, text = swing_structure_4h, bgcolor = swing_structure_4h_color, text_size = h3_size)
	Cell += 1
	table.cell(maTable, 0, Cell, text = "15m Swing Structure")
	table.cell(maTable, 1, Cell, text = swing_structure_15m, bgcolor = swing_structure_15m_color, text_size = h3_size)
	//table.merge_cells(maTable, 0, Cell, 1, Cell)	
	
	//General Infos
	Cell += 1
	table.cell(maTable, 0, Cell, text = General_Title, text_color = title_text_color, text_size = h2_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)
	Cell += 1
	table.cell(maTable, 0, Cell, text = General_Infos, text_size = h3_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)	
	
	// Market Structure
	Cell += 1
	table.cell(maTable, 0, Cell, text = Market_Structure_Title, text_color = title_text_color, text_size = h2_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)
	Cell += 1
	table.cell(maTable, 0, Cell, text = Market_Structure_Info, text_size = h3_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)

	
    //Supply and Demand
	Cell += 1
	table.cell(maTable, 0, Cell, text = SnD_Title, text_color = title_text_color, text_size = h2_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)
	Cell += 1
	table.cell(maTable, 0, Cell, text = SnD_Info, text_size = h3_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)

    //Liquidity
	Cell += 1
	table.cell(maTable, 0, Cell, text = Liquidity_Title, text_color = title_text_color, text_size = h2_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)
	Cell += 1
	table.cell(maTable, 0, Cell, text = Liquidity_Info, text_size = h3_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)

    //More Confluences
	Cell += 1
	table.cell(maTable, 0, Cell, text = more_confluences_title, text_color = title_text_color, text_size = h2_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)
	Cell += 1
	table.cell(maTable, 0, Cell, text = more_confluences_info, text_size = h3_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)
	
	
	//Before you take a trade, please, for the love of god, read this!
	Cell += 1
	table.cell(maTable, 0, Cell, text = before_trade_title, text_color = title_text_color, text_size = h2_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)
	Cell += 1
	table.cell(maTable, 0, Cell, text = before_trade_info, text_size = h3_size)
	table.merge_cells(maTable, 0, Cell, 1, Cell)	
	
	
	

//Inside Bar Section
inside_bar_color  = input.color(color.white, "Inside Bar Color", group = "Inside Bar")

if inside_bar_show == false
    inside_bar_color := na

Inside(position) => high <= high[position] and low >= low[position]
secLast = 1
barcolor(Inside(secLast)? inside_bar_color: na)


// ********* //
// ********* // 
// Trading Session //
// ********* //
// ********* //


fr_group = "session_fr"
lnd_group = "session_lnd"
ny_group = "session_ny"
asia_group = "session_asia"

style_group = "Trading Session Box Style"

// Show & Styles
i_sess_border_style = input.string(line.style_dotted, 'Style', options=[line.style_solid, line.style_dotted, line.style_dashed], group=style_group)
i_sess_border_width = input.int(1, 'Thickness', minval=0, group=style_group)
i_sess_bgopacity = input.int(100, 'Transp', minval=0, maxval=100, step=1, group=style_group, tooltip='Setting the 100 is no background color')


i_tz = input.string('GMT+2', title='Timezone', options=['GMT-11', 'GMT-10', 'GMT-9', 'GMT-8', 'GMT-7', 'GMT-6', 'GMT-5', 'GMT-4', 'GMT-3', 'GMT-2', 'GMT-1', 'GMT', 'GMT+1', 'GMT+2', 'GMT+3', 'GMT+4', 'GMT+5', 'GMT+6', 'GMT+7', 'GMT+8', 'GMT+9', 'GMT+10', 'GMT+11', 'GMT+12'], tooltip='e.g. \'America/New_York\', \'Asia/Tokyo\', \'GMT-4\', \'GMT+9\'...', group="General")

trading_session_group = "Trading Session"
outside_session_color = input.color(color.red, 'Bar Color', group=trading_session_group)
text_color = input.color(color.white, 'Text Color', group=trading_session_group)
label_color = input.color(color.new(color.green, 100), 'Label Color', group=trading_session_group)
label_position = str.lower(input.string('Bottom', '', options=['Top', 'Bottom'], group=trading_session_group))

label_style = label.style_label_center

icon_separator = ' • '

fr_Session	= input.session(title="Frankfurt", defval="0700-1100", inline=fr_group)
show_fr		= input.bool(true, title="", inline=fr_group)
fr_color	= input.color(color.new(color.teal, 0), '', inline=fr_group)

lnd_Session	= input.session(title="London", defval="0800-1200", inline=lnd_group)
show_ln		= input.bool(true, title="", inline=lnd_group)
ln_color	= input.color(color.new(color.blue, 0), '', inline=lnd_group)

ny_Session	= input.session(title="New York", defval="1300-1700", inline=ny_group)
show_ny		= input.bool(true, title="", inline=ny_group)
ny_color	= input.color(color.new(color.orange, 0), '', inline=ny_group)

asia_Session= input.session(title="Asia", defval="0100-0700", inline=asia_group)
show_as		= input.bool(true, title="", inline=asia_group)
as_color	= input.color(color.new(color.purple, 0), '', inline=asia_group)



//Pip calculation

i_lookback = 12 * 60
f_get_started (_session) => na(_session[1]) and _session
f_get_ended (_session) => na(_session) and _session[1]


f_get_period (_session, _start, _lookback) =>
    result = math.max(_start, 1)
    for i = result to _lookback
        if na(_session[i+1]) and _session[i]
            result := i+1
            break
    result

get_min_max(_session) =>
	max = f_get_period(_session, 1, i_lookback)
	top = ta.highest(high, max)
	bottom = ta.lowest(low, max)
	[top, bottom]
    
get_pips(_top, _bottom) =>
	pips = (_top - _bottom) * 10000
	pips
	
	
//draw_line(lnd_Session, f_get_started(sess_ln), sess_ln)
draw_line(_is_session, _is_started, _session) =>

	open_session = ta.valuewhen(na(_session[1]) and _session, bar_index, 1)
	line my_line = na
	if _is_started
		my_line := line.new(bar_index-1, open_session, bar_index, open_session)
		
	if _is_session
		line.set_y1(my_line, open_session)
		line.set_y2(my_line, open_session)
	
draw_label(_is_started, _is_session, session_string, active_session, _top, _bottom, _textcolor) =>

	pips = get_pips(_top, _bottom)
	label my_label = na
	
	if _is_started
		my_label := label.new(time, _bottom, str.tostring(pips), textcolor=_textcolor, color=label_color, size=size.normal, style=label_style, xloc=xloc.bar_time)
		//label.delete(my_label[1])

		if show_pips_history == false
			label.delete(my_label[1])
			
	label_seperator = (high * syminfo.mintick * 100)
	
	if _is_session
	    if session_string == "Frankfurt "
		    label.set_y(my_label, _bottom - label_seperator)
		else
		    label.set_y(my_label, _bottom - label_seperator - label_seperator)
		label.set_text(my_label, session_string + icon_separator + str.tostring(pips))


draw_market (_show, _session, _is_started, _is_ended, _color, _top, _bottom) =>
    var box my_box = na

    x0_1 = ta.valuewhen(na(_session[1]) and _session, bar_index, 1)
    x0_2 = ta.valuewhen(na(_session) and _session[1], bar_index, 0)
    var x1 = 0
    var x2 = 0
    var v_session_open  = 0.0
    var v_session_high  = 0.0
    var v_session_low   = 0.0

    if _show
        if _is_started
            x1 := bar_index
            x2 := bar_index + math.abs(x0_2 - x0_1)
            my_box := box.new(x1, _top, x2, _bottom)
            box.set_border_style(my_box, i_sess_border_style)
            box.set_border_width(my_box, i_sess_border_width)
            box.set_border_color(my_box, _color)
            box.set_bgcolor(my_box, color.new(_color, i_sess_bgopacity))
            
            v_session_open := open
            v_session_high := _top
            v_session_low  := _bottom

            if show_box_history == false
                box.delete(my_box[1])
				
        // Proccesing
        else if _session
            box.set_top(my_box, _top)
            box.set_bottom(my_box, _bottom)

            v_session_high := _top
            v_session_low  := _bottom
        
        else if _is_ended
            v_session_open := na
            box.set_right(my_box, bar_index)

    [x1, x2, v_session_open, v_session_high, v_session_low]
	
///////////////////
// Calculating
///////////////////
string tz = (i_tz == "No" or i_tz == '') ? na : i_tz
int sess_fr = time(timeframe.period, fr_Session, tz)
int sess_as = time(timeframe.period, asia_Session, tz)
int sess_ln = time(timeframe.period, lnd_Session, tz)
int sess_ny = time(timeframe.period, ny_Session, tz)

[fr_top, fr_bottom] = get_min_max(sess_fr)
[ln_top, ln_bottom] = get_min_max(sess_ln)
[ny_top, ny_bottom] = get_min_max(sess_ny)
[as_top, as_bottom] = get_min_max(sess_as)

if show_fr
	if show_pips
		draw_label(f_get_started(sess_fr), sess_fr, "Frankfurt ", fr_Session, fr_top, fr_bottom, fr_color)
	draw_market(show_box, sess_fr, f_get_started(sess_fr), f_get_ended(sess_fr), fr_color, fr_top, fr_bottom)
	
if show_ln
	if show_pips
		draw_label(f_get_started(sess_ln), sess_ln, "London ", lnd_Session, ln_top, ln_bottom, ln_color)
	draw_market(show_box, sess_ln, f_get_started(sess_ln), f_get_ended(sess_ln), ln_color, ln_top, ln_bottom)
	if show_lines
		draw_line(sess_ln, f_get_started(sess_ln), sess_ln)
if show_ny
	if show_pips
		draw_label(f_get_started(sess_ny), sess_ny, "New York ", ny_Session, ny_top, ny_bottom, ny_color)
	draw_market(show_box, sess_ny, f_get_started(sess_ny), f_get_ended(sess_ny), ny_color, ny_top, ny_bottom)

if show_as
	if show_pips
		draw_label(f_get_started(sess_as), sess_as, "Asia ", asia_Session, as_top, as_bottom, as_color)
	draw_market(show_box, sess_as, f_get_started(sess_as), f_get_ended(sess_as), as_color, as_top, as_bottom)
	
if show_session == false
    outside_session_color := na

InSession(sess) => na(time(timeframe.period, sess, tz)) == false
barcolor(color=(InSession(fr_Session)[1] and show_fr) or (InSession(lnd_Session)[1] and show_ln) or (InSession(ny_Session)[1] and show_ny ) or (InSession(asia_Session)[1] and show_as) ? na : outside_session_color, title="Frankfurt")

////////////////////
// Alerts
////////////////////

// Alerts
i_alert1_show = input.bool(false, 'Alerts - Sessions stard/end', group='Alerts visualized')
i_alert2_show = input.bool(false, 'Alerts - Opening range breakouts', group='Alerts visualized')
i_alert3_show = input.bool(false, 'Alerts - Price crossed session\s High/Low after session closed', group='Alerts visualized')


//Session alerts
bool sess_frankfurt_started = sess_fr and not sess_fr[1]
bool sess_frankfurt_ended = not sess_fr and sess_fr[1]
bool sess_london_started = sess_ln and not sess_ln[1]
bool sess_london_ended = not sess_ln and sess_ln[1]
bool sess_new_york_started = sess_ny and not sess_ny[1]
bool sess_new_york_ended = not sess_ny and sess_ny[1]
bool sess_asia_started = sess_as and not sess_as[1]
bool sess_asia_ended = not sess_as and sess_as[1]


alertcondition(sess_frankfurt_started,   'Frankfurt session started')
alertcondition(sess_frankfurt_ended,     'Frankfurt session ended')
alertcondition(sess_london_started,   'London session started')
alertcondition(sess_london_ended,     'London session ended')
alertcondition(sess_new_york_started,   'New York session started')
alertcondition(sess_new_york_ended,     'New York session ended')
alertcondition(sess_asia_started,   'Asia session started')
alertcondition(sess_asia_ended,     'Asia session ended')

alertcondition((not sess_fr) and ta.crossover(close, fr_top), 'Frankfurt session High crossed (after session closed)')
alertcondition((not sess_fr) and ta.crossunder(close, fr_bottom), 'Frankfurt session Low crossed (after session closed)')
alertcondition((not sess_ln) and ta.crossover(close, ln_top), 'London session High crossed (after session closed)')
alertcondition((not sess_ln) and ta.crossunder(close, ln_bottom), 'London session Low crossed (after session closed)')
alertcondition((not sess_ny) and ta.crossover(close, ny_top), 'New York session High crossed (after session closed)')
alertcondition((not sess_ny) and ta.crossunder(close, ny_bottom), 'New York session Low crossed (after session closed)')
alertcondition((not sess_as) and ta.crossover(close, as_top), 'Asia session High crossed (after session closed)')
alertcondition((not sess_as) and ta.crossunder(close, as_bottom), 'Asia session Low crossed (after session closed)')



// ********* //
// ********* // 
// Imbalance //
// ********* //
// ********* //


color gray0 = color.new(color.gray, 0)
color yellow0 = color.new(#FFF700, 0)
bool showgreydiamond = input(defval=false, title='Show Diamond For Back Testing' ,group='=== Information ===')

Imbcol = input.color(yellow0, 'Imbalance Colour', inline="1" ,group='=== Information ===')
Dimcol = input.color(gray0, 'Imbalance Colour', inline="1" ,group='=== Information ===')
TopImbalance = low[2] <= open[1] and high[0] >= close[1]
TopImbalancesize = low[2] - high[0]
if TopImbalance and TopImbalancesize > 0 and show_imbalance
    BOX1 = box.new(left=bar_index[1], top=low[2], right=bar_index[0], bottom=high[0])
    box.set_bgcolor(BOX1, Imbcol )
    box.set_border_color(BOX1, Imbcol )

BottomImbalance = high[2] >= open[1] and low[0] <= close[1]
BottomImbalancesize = low[0] - high[2]
if BottomImbalance and BottomImbalancesize > 0 and show_imbalance
    BOX2 = box.new(left=bar_index[1], top=low[0], right=bar_index[0], bottom=high[2])
    box.set_bgcolor(BOX2, Imbcol )
    box.set_border_color(BOX2, Imbcol )

DownImbalance = TopImbalance and TopImbalancesize > 0
if show_imbalance == false
	DownImbalance := false
	showgreydiamond := false
plotshape(DownImbalance[0] and showgreydiamond, style=shape.diamond, location=location.abovebar, color=Dimcol, size=size.tiny)

UpImbalance = BottomImbalance and BottomImbalancesize > 0
if show_imbalance
	UpImbalance := false
	showgreydiamond := false
plotshape(UpImbalance[0] and showgreydiamond, style=shape.diamond, location=location.belowbar, color=Dimcol, size=size.tiny)

alertcondition(DownImbalance ,  title='Down Imbalance', message='Down Imbalance')
alertcondition(UpImbalance ,  title='Up Imbalance', message='Up Imbalance')
alertcondition(DownImbalance or UpImbalance ,  title='Imbalance Present ', message='Imbalance Present')