Created
November 16, 2022 20:27
-
-
Save niquedegraaff/8c2f45dc73519458afeae14b0096d719 to your computer and use it in GitHub Desktop.
Smart Money Concepts [LuxAlgo] [Enhanced]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/ | |
// © LuxAlgo | |
//@version=5 | |
indicator("Smart Money Concepts [LUX]", "Smart Money Concepts [LuxAlgo]" | |
, overlay = true | |
, max_labels_count = 500 | |
, max_lines_count = 500 | |
, max_boxes_count = 500 | |
, max_bars_back = 500) | |
//-----------------------------------------------------------------------------{ | |
//Constants | |
//-----------------------------------------------------------------------------{ | |
color TRANSP_CSS = #ffffff00 | |
//Tooltips | |
string MODE_TOOLTIP = 'Allows to display historical Structure or only the recent ones' | |
string STYLE_TOOLTIP = 'Indicator color theme' | |
string COLOR_CANDLES_TOOLTIP = 'Display additional candles with a color reflecting the current trend detected by structure' | |
string SHOW_INTERNAL = 'Display internal market structure' | |
string CONFLUENCE_FILTER = 'Filter non significant internal structure breakouts' | |
string SHOW_SWING = 'Display swing market Structure' | |
string SHOW_SWING_POINTS = 'Display swing point as labels on the chart' | |
string SHOW_SWHL_POINTS = 'Highlight most recent strong and weak high/low points on the chart' | |
string HIGHLIGHT_MIT_OB = 'Highlight mitigated orderblocks with other color' | |
string INTERNAL_OB = 'Display internal order blocks on the chart\n\nNumber of internal order blocks to display on the chart' | |
string SWING_OB = 'Display swing order blocks on the chart\n\nNumber of internal swing blocks to display on the chart' | |
string FILTER_OB = 'Method used to filter out volatile order blocks \n\nIt is recommended to use the cumulative mean range method when a low amount of data is available' | |
string SHOW_EQHL = 'Display equal highs and equal lows on the chart' | |
string EQHL_BARS = 'Number of bars used to confirm equal highs and equal lows' | |
string EQHL_THRESHOLD = 'Sensitivity threshold in a range (0, 1) used for the detection of equal highs & lows\n\nLower values will return fewer but more pertinent results' | |
string SHOW_FVG = 'Display fair values gaps on the chart' | |
string AUTO_FVG = 'Filter out non significant fair value gaps' | |
string FVG_TF = 'Fair value gaps timeframe' | |
string EXTEND_FVG = 'Determine how many bars to extend the Fair Value Gap boxes on chart' | |
string PED_ZONES = 'Display premium, discount, and equilibrium zones on chart' | |
//-----------------------------------------------------------------------------{ | |
//Settings | |
//-----------------------------------------------------------------------------{ | |
//General | |
//----------------------------------------{ | |
mode = input.string('Historical' | |
, options = ['Historical', 'Present'] | |
, group = 'Smart Money Concepts' | |
, tooltip = MODE_TOOLTIP) | |
style = input.string('Colored' | |
, options = ['Colored', 'Monochrome'] | |
, group = 'Smart Money Concepts' | |
, tooltip = STYLE_TOOLTIP) | |
show_trend = input(false, 'Color Candles' | |
, group = 'Smart Money Concepts' | |
, tooltip = COLOR_CANDLES_TOOLTIP) | |
//----------------------------------------} | |
//Internal Structure | |
//----------------------------------------{ | |
show_internals = input(true, 'Show Internal Structure' | |
, group = 'Real Time Internal Structure' | |
, tooltip = SHOW_INTERNAL) | |
show_ibull = input.string('All', 'Bullish Structure' | |
, options = ['All', 'BOS', 'CHoCH'] | |
, inline = 'ibull' | |
, group = 'Real Time Internal Structure') | |
swing_ibull_css = input(#089981, '' | |
, inline = 'ibull' | |
, group = 'Real Time Internal Structure') | |
//Bear Structure | |
show_ibear = input.string('All', 'Bearish Structure' | |
, options = ['All', 'BOS', 'CHoCH'] | |
, inline = 'ibear' | |
, group = 'Real Time Internal Structure') | |
swing_ibear_css = input(#f23645, '' | |
, inline = 'ibear' | |
, group = 'Real Time Internal Structure') | |
ifilter_confluence = input(false, 'Confluence Filter' | |
, group = 'Real Time Internal Structure' | |
, tooltip = CONFLUENCE_FILTER) | |
//----------------------------------------} | |
//Swing Structure | |
//----------------------------------------{ | |
show_Structure = input(true, 'Show Swing Structure' | |
, group = 'Real Time Swing Structure' | |
, tooltip = SHOW_SWING) | |
//Bull Structure | |
show_bull = input.string('All', 'Bullish Structure' | |
, options = ['All', 'BOS', 'CHoCH'] | |
, inline = 'bull' | |
, group = 'Real Time Swing Structure') | |
swing_bull_css = input(#089981, '' | |
, inline = 'bull' | |
, group = 'Real Time Swing Structure') | |
//Bear Structure | |
show_bear = input.string('All', 'Bearish Structure' | |
, options = ['All', 'BOS', 'CHoCH'] | |
, inline = 'bear' | |
, group = 'Real Time Swing Structure') | |
swing_bear_css = input(#f23645, '' | |
, inline = 'bear' | |
, group = 'Real Time Swing Structure') | |
//Swings | |
show_swings = input(false, 'Show Swings Points' | |
, inline = 'swings' | |
, group = 'Real Time Swing Structure' | |
, tooltip = SHOW_SWING_POINTS) | |
length = input.int(50, '' | |
, minval = 10 | |
, inline = 'swings' | |
, group = 'Real Time Swing Structure') | |
show_hl_swings = input(true, 'Show Strong/Weak High/Low' | |
, group = 'Real Time Swing Structure' | |
, tooltip = SHOW_SWHL_POINTS) | |
//----------------------------------------} | |
//Order Blocks | |
//----------------------------------------{ | |
show_iob = input(true, 'Internal Order Blocks' | |
, inline = 'iob' | |
, group = 'Order Blocks' | |
, tooltip = INTERNAL_OB) | |
iob_showlast = input.int(5, '' | |
, minval = 1 | |
, inline = 'iob' | |
, group = 'Order Blocks') | |
show_ob = input(false, 'Swing Order Blocks' | |
, inline = 'ob' | |
, group = 'Order Blocks' | |
, tooltip = SWING_OB) | |
ob_showlast = input.int(5, '' | |
, minval = 1 | |
, inline = 'ob' | |
, group = 'Order Blocks') | |
ob_filter = input.string('Atr', 'Order Block Filter' | |
, options = ['Atr', 'Cumulative Mean Range'] | |
, group = 'Order Blocks' | |
, tooltip = FILTER_OB) | |
ob_highlight_mit = input(true, 'Highlight Mitigated Order blocks' | |
, inline = 'ob' | |
, group = 'Order Blocks' | |
, tooltip = HIGHLIGHT_MIT_OB) | |
ibull_ob_css = input.color(color.new(#3179f5, 80), 'Internal Bullish OB' | |
, inline = 'inull_ob_css' | |
, group = 'Order Blocks') | |
ibullm_ob_css = input.color(color.new(#636363, 80), '' | |
, inline = 'inull_ob_css' | |
, group = 'Order Blocks' | |
, tooltip = 'Unmitigated and Mitigated colors') | |
ibear_ob_css = input.color(color.new(#f77c80, 80), 'Internal Bearish OB' | |
, inline = 'ibear_ob_css' | |
, group = 'Order Blocks') | |
ibearm_ob_css = input.color(color.new(#636363, 80), '' | |
, inline = 'ibear_ob_css' | |
, group = 'Order Blocks' | |
, tooltip = 'Unmitigated and Mitigated colors') | |
bull_ob_css = input.color(color.new(#1848cc, 80), 'Bullish OB' | |
, inline = 'bull_ob_css' | |
, group = 'Order Blocks') | |
bullm_ob_css = input.color(color.new(#636363, 80), '' | |
, group = 'Order Blocks' | |
, inline = 'bull_ob_css' | |
, tooltip = 'Unmitigated and Mitigated colors') | |
bear_ob_css = input.color(color.new(#b22833, 80), 'Bearish OB' | |
, group = 'Order Blocks' | |
, inline = 'bear_ob_css') | |
bearm_ob_css = input.color(color.new(#636363, 80), '' | |
, group = 'Order Blocks' | |
, inline = 'bear_ob_css' | |
, tooltip = 'Unmitigated and Mitigated colors') | |
//----------------------------------------} | |
//EQH/EQL | |
//----------------------------------------{ | |
show_eq = input(true, 'Equal High/Low' | |
, group = 'EQH/EQL' | |
, tooltip = SHOW_EQHL) | |
eq_len = input.int(3, 'Bars Confirmation' | |
, minval = 1 | |
, group = 'EQH/EQL' | |
, tooltip = EQHL_BARS) | |
eq_threshold = input.float(0.1, 'Threshold' | |
, minval = 0 | |
, maxval = 0.5 | |
, step = 0.1 | |
, group = 'EQH/EQL' | |
, tooltip = EQHL_THRESHOLD) | |
//----------------------------------------} | |
//Fair Value Gaps | |
//----------------------------------------{ | |
show_fvg = input(false, 'Fair Value Gaps' | |
, group = 'Fair Value Gaps' | |
, tooltip = SHOW_FVG) | |
fvg_auto = input(true, "Auto Threshold" | |
, group = 'Fair Value Gaps' | |
, tooltip = AUTO_FVG) | |
fvg_tf = input.timeframe('', "Timeframe" | |
, group = 'Fair Value Gaps' | |
, tooltip = FVG_TF) | |
bull_fvg_css = input.color(color.new(#00ff68, 70), 'Bullish FVG' | |
, group = 'Fair Value Gaps') | |
bear_fvg_css = input.color(color.new(#ff0008, 70), 'Bearish FVG' | |
, group = 'Fair Value Gaps') | |
fvg_extend = input.int(1, "Extend FVG" | |
, minval = 0 | |
, group = 'Fair Value Gaps' | |
, tooltip = EXTEND_FVG) | |
//----------------------------------------} | |
//Previous day/week high/low | |
//----------------------------------------{ | |
//Daily | |
show_pdhl = input(false, 'Daily' | |
, inline = 'daily' | |
, group = 'Highs & Lows MTF') | |
pdhl_style = input.string('⎯⎯⎯', '' | |
, options = ['⎯⎯⎯', '----', '····'] | |
, inline = 'daily' | |
, group = 'Highs & Lows MTF') | |
pdhl_css = input(#2157f3, '' | |
, inline = 'daily' | |
, group = 'Highs & Lows MTF') | |
//Weekly | |
show_pwhl = input(false, 'Weekly' | |
, inline = 'weekly' | |
, group = 'Highs & Lows MTF') | |
pwhl_style = input.string('⎯⎯⎯', '' | |
, options = ['⎯⎯⎯', '----', '····'] | |
, inline = 'weekly' | |
, group = 'Highs & Lows MTF') | |
pwhl_css = input(#2157f3, '' | |
, inline = 'weekly' | |
, group = 'Highs & Lows MTF') | |
//Monthly | |
show_pmhl = input(false, 'Monthly' | |
, inline = 'monthly' | |
, group = 'Highs & Lows MTF') | |
pmhl_style = input.string('⎯⎯⎯', '' | |
, options = ['⎯⎯⎯', '----', '····'] | |
, inline = 'monthly' | |
, group = 'Highs & Lows MTF') | |
pmhl_css = input(#2157f3, '' | |
, inline = 'monthly' | |
, group = 'Highs & Lows MTF') | |
//----------------------------------------} | |
//Premium/Discount zones | |
//----------------------------------------{ | |
show_sd = input(false, 'Premium/Discount Zones' | |
, group = 'Premium & Discount Zones' | |
, tooltip = PED_ZONES) | |
premium_css = input.color(#f23645, 'Premium Zone' | |
, group = 'Premium & Discount Zones') | |
eq_css = input.color(#b2b5be, 'Equilibrium Zone' | |
, group = 'Premium & Discount Zones') | |
discount_css = input.color(#089981, 'Discount Zone' | |
, group = 'Premium & Discount Zones') | |
//-----------------------------------------------------------------------------} | |
//Functions | |
//-----------------------------------------------------------------------------{ | |
n = bar_index | |
atr = ta.atr(200) | |
cmean_range = ta.cum(high - low) / n | |
//HL Output function | |
hl() => [high, low] | |
//Get ohlc values function | |
get_ohlc()=> [close[1], open[1], high, low, high[2], low[2]] | |
//Display Structure function | |
display_Structure(x, y, txt, css, dashed, down, lbl_size)=> | |
structure_line = line.new(x, y, n, y | |
, color = css | |
, style = dashed ? line.style_dashed : line.style_solid) | |
structure_lbl = label.new(int(math.avg(x, n)), y, txt | |
, color = TRANSP_CSS | |
, textcolor = css | |
, style = down ? label.style_label_down : label.style_label_up | |
, size = lbl_size) | |
if mode == 'Present' | |
line.delete(structure_line[1]) | |
label.delete(structure_lbl[1]) | |
//Swings detection/measurements | |
swings(len)=> | |
var os = 0 | |
upper = ta.highest(len) | |
lower = ta.lowest(len) | |
os := high[len] > upper ? 0 : low[len] < lower ? 1 : os[1] | |
top = os == 0 and os[1] != 0 ? high[len] : 0 | |
btm = os == 1 and os[1] != 1 ? low[len] : 0 | |
[top, btm] | |
//Order block coordinates function | |
ob_coord(use_max, loc, target_top, target_btm, target_left, target_right, target_type, target_mit)=> | |
min = 99999999. | |
max = 0. | |
idx = 1 | |
ob_threshold = ob_filter == 'Atr' ? atr : cmean_range | |
//Search for highest/lowest high within the structure interval and get range | |
if use_max | |
for i = 1 to (n - loc)-1 | |
if (high[i] - low[i]) < ob_threshold[i] * 2 | |
max := math.max(high[i], max) | |
min := max == high[i] ? low[i] : min | |
idx := max == high[i] ? i : idx | |
else | |
for i = 1 to (n - loc)-1 | |
if (high[i] - low[i]) < ob_threshold[i] * 2 | |
min := math.min(low[i], min) | |
max := min == low[i] ? high[i] : max | |
idx := min == low[i] ? i : idx | |
array.unshift(target_top, max) | |
array.unshift(target_btm, min) | |
array.unshift(target_left, time[idx]) | |
array.unshift(target_right, time[idx]) | |
array.unshift(target_type, use_max ? -1 : 1) | |
array.unshift(target_mit, 0) | |
//Set order blocks | |
display_ob(boxes, target_top, target_btm, target_left, target_right, target_type, target_mit, show_last, swing, size)=> | |
for i = 0 to math.min(show_last-1, size-1) | |
get_box = array.get(boxes, i) | |
box.set_lefttop(get_box, array.get(target_left, i), array.get(target_top, i)) | |
box.set_rightbottom(get_box, array.get(target_right, i), array.get(target_btm, i)) | |
box.set_extend(get_box, array.get(target_mit, i) > 0 ? extend.none : extend.right) | |
color css = na | |
if swing | |
if style == 'Monochrome' | |
css := array.get(target_type, i) == 1 ? color.new(#b2b5be, 80) : color.new(#5d606b, 80) | |
border_css = array.get(target_type, i) == 1 ? #b2b5be : #5d606b | |
box.set_border_color(get_box, border_css) | |
else | |
if array.get(target_mit, i) > 0 | |
css := array.get(target_type, i) == 1 ? bullm_ob_css : bearm_ob_css | |
else | |
css := array.get(target_type, i) == 1 ? bull_ob_css : bear_ob_css | |
box.set_border_color(get_box, css) | |
box.set_bgcolor(get_box, css) | |
else | |
if style == 'Monochrome' | |
css := array.get(target_type, i) == 1 ? color.new(#b2b5be, 80) : color.new(#5d606b, 80) | |
else | |
if array.get(target_mit, i) > 0 | |
css := array.get(target_type, i) == 1 ? ibullm_ob_css : ibearm_ob_css | |
else | |
css := array.get(target_type, i) == 1 ? ibull_ob_css : ibear_ob_css | |
box.set_border_color(get_box, css) | |
box.set_bgcolor(get_box, css) | |
//Line Style function | |
get_line_style(style) => | |
out = switch style | |
'⎯⎯⎯' => line.style_solid | |
'----' => line.style_dashed | |
'····' => line.style_dotted | |
//Set line/labels function for previous high/lows | |
phl(h, l, tf, css)=> | |
var line high_line = line.new(na,na,na,na | |
, xloc = xloc.bar_time | |
, color = css | |
, style = get_line_style(pdhl_style)) | |
var label high_lbl = label.new(na,na | |
, xloc = xloc.bar_time | |
, text = str.format('P{0}H', tf) | |
, color = TRANSP_CSS | |
, textcolor = css | |
, size = size.small | |
, style = label.style_label_left) | |
var line low_line = line.new(na,na,na,na | |
, xloc = xloc.bar_time | |
, color = css | |
, style = get_line_style(pdhl_style)) | |
var label low_lbl = label.new(na,na | |
, xloc = xloc.bar_time | |
, text = str.format('P{0}L', tf) | |
, color = TRANSP_CSS | |
, textcolor = css | |
, size = size.small | |
, style = label.style_label_left) | |
hy = ta.valuewhen(h != h[1], h, 1) | |
hx = ta.valuewhen(h == high, time, 1) | |
ly = ta.valuewhen(l != l[1], l, 1) | |
lx = ta.valuewhen(l == low, time, 1) | |
if barstate.islast | |
ext = time + (time - time[1])*20 | |
//High | |
line.set_xy1(high_line, hx, hy) | |
line.set_xy2(high_line, ext, hy) | |
label.set_xy(high_lbl, ext, hy) | |
//Low | |
line.set_xy1(low_line, lx, ly) | |
line.set_xy2(low_line, ext, ly) | |
label.set_xy(low_lbl, ext, ly) | |
//-----------------------------------------------------------------------------} | |
//Global variables | |
//-----------------------------------------------------------------------------{ | |
var trend = 0, var itrend = 0 | |
var top_y = 0., var top_x = 0 | |
var btm_y = 0., var btm_x = 0 | |
var itop_y = 0., var itop_x = 0 | |
var ibtm_y = 0., var ibtm_x = 0 | |
var trail_up = high, var trail_dn = low | |
var trail_up_x = 0, var trail_dn_x = 0 | |
var top_cross = true, var btm_cross = true | |
var itop_cross = true, var ibtm_cross = true | |
var txt_top = '', var txt_btm = '' | |
//Alerts | |
bull_choch_alert = false | |
bull_bos_alert = false | |
bear_choch_alert = false | |
bear_bos_alert = false | |
bull_ichoch_alert = false | |
bull_ibos_alert = false | |
bear_ichoch_alert = false | |
bear_ibos_alert = false | |
bull_iob_mit = false | |
bear_iob_mit = false | |
bull_ob_mit = false | |
bear_ob_mit = false | |
bull_iob_break = false | |
bear_iob_break = false | |
bull_ob_break = false | |
bear_ob_break = false | |
eqh_alert = false | |
eql_alert = false | |
//Structure colors | |
var bull_css = style == 'Monochrome' ? #b2b5be | |
: swing_bull_css | |
var bear_css = style == 'Monochrome' ? #b2b5be | |
: swing_bear_css | |
var ibull_css = style == 'Monochrome' ? #b2b5be | |
: swing_ibull_css | |
var ibear_css = style == 'Monochrome' ? #b2b5be | |
: swing_ibear_css | |
//Swings | |
[top, btm] = swings(length) | |
[itop, ibtm] = swings(5) | |
//-----------------------------------------------------------------------------} | |
//Pivot High | |
//-----------------------------------------------------------------------------{ | |
var line extend_top = na | |
var label extend_top_lbl = label.new(na, na | |
, color = TRANSP_CSS | |
, textcolor = bear_css | |
, style = label.style_label_down | |
, size = size.tiny) | |
if top | |
top_cross := true | |
txt_top := top > top_y ? 'HH' : 'LH' | |
if show_swings | |
top_lbl = label.new(n-length, top, txt_top | |
, color = TRANSP_CSS | |
, textcolor = bear_css | |
, style = label.style_label_down | |
, size = size.small) | |
if mode == 'Present' | |
label.delete(top_lbl[1]) | |
//Extend recent top to last bar | |
line.delete(extend_top[1]) | |
extend_top := line.new(n-length, top, n, top | |
, color = bear_css) | |
top_y := top | |
top_x := n - length | |
trail_up := top | |
trail_up_x := n - length | |
if itop | |
itop_cross := true | |
itop_y := itop | |
itop_x := n - 5 | |
//Trailing maximum | |
trail_up := math.max(high, trail_up) | |
trail_up_x := trail_up == high ? n : trail_up_x | |
//Set top extension label/line | |
if barstate.islast and show_hl_swings | |
line.set_xy1(extend_top, trail_up_x, trail_up) | |
line.set_xy2(extend_top, n + 20, trail_up) | |
label.set_x(extend_top_lbl, n + 20) | |
label.set_y(extend_top_lbl, trail_up) | |
label.set_text(extend_top_lbl, trend < 0 ? 'Strong High' : 'Weak High') | |
//-----------------------------------------------------------------------------} | |
//Pivot Low | |
//-----------------------------------------------------------------------------{ | |
var line extend_btm = na | |
var label extend_btm_lbl = label.new(na, na | |
, color = TRANSP_CSS | |
, textcolor = bull_css | |
, style = label.style_label_up | |
, size = size.tiny) | |
if btm | |
btm_cross := true | |
txt_btm := btm < btm_y ? 'LL' : 'HL' | |
if show_swings | |
btm_lbl = label.new(n - length, btm, txt_btm | |
, color = TRANSP_CSS | |
, textcolor = bull_css | |
, style = label.style_label_up | |
, size = size.small) | |
if mode == 'Present' | |
label.delete(btm_lbl[1]) | |
//Extend recent btm to last bar | |
line.delete(extend_btm[1]) | |
extend_btm := line.new(n - length, btm, n, btm | |
, color = bull_css) | |
btm_y := btm | |
btm_x := n-length | |
trail_dn := btm | |
trail_dn_x := n-length | |
if ibtm | |
ibtm_cross := true | |
ibtm_y := ibtm | |
ibtm_x := n - 5 | |
//Trailing minimum | |
trail_dn := math.min(low, trail_dn) | |
trail_dn_x := trail_dn == low ? n : trail_dn_x | |
//Set btm extension label/line | |
if barstate.islast and show_hl_swings | |
line.set_xy1(extend_btm, trail_dn_x, trail_dn) | |
line.set_xy2(extend_btm, n + 20, trail_dn) | |
label.set_x(extend_btm_lbl, n + 20) | |
label.set_y(extend_btm_lbl, trail_dn) | |
label.set_text(extend_btm_lbl, trend > 0 ? 'Strong Low' : 'Weak Low') | |
//-----------------------------------------------------------------------------} | |
//Order Blocks Arrays | |
//-----------------------------------------------------------------------------{ | |
var iob_top = array.new_float(0) | |
var iob_btm = array.new_float(0) | |
var iob_left = array.new_int(0) | |
var iob_right = array.new_int(0) | |
var iob_type = array.new_int(0) | |
var iob_mit = array.new_int(0) | |
var ob_top = array.new_float(0) | |
var ob_btm = array.new_float(0) | |
var ob_left = array.new_int(0) | |
var ob_right = array.new_int(0) | |
var ob_type = array.new_int(0) | |
var ob_mit = array.new_int(0) | |
//-----------------------------------------------------------------------------} | |
//Pivot High BOS/CHoCH | |
//-----------------------------------------------------------------------------{ | |
//Filtering | |
var bull_concordant = true | |
if ifilter_confluence | |
bull_concordant := high - math.max(close, open) > math.min(close, open - low) | |
//Detect internal bullish Structure | |
if ta.crossover(close, itop_y) and itop_cross and top_y != itop_y and bull_concordant | |
bool choch = na | |
if itrend < 0 | |
choch := true | |
bull_ichoch_alert := true | |
else | |
bull_ibos_alert := true | |
txt = choch ? 'CHoCH' : 'BOS' | |
if show_internals | |
if show_ibull == 'All' or (show_ibull == 'BOS' and not choch) or (show_ibull == 'CHoCH' and choch) | |
display_Structure(itop_x, itop_y, txt, ibull_css, true, true, size.tiny) | |
itop_cross := false | |
itrend := 1 | |
//Internal Order Block | |
if show_iob | |
ob_coord(false, itop_x, iob_top, iob_btm, iob_left, iob_right, iob_type, iob_mit) | |
//Detect bullish Structure | |
if ta.crossover(close, top_y) and top_cross | |
bool choch = na | |
if trend < 0 | |
choch := true | |
bull_choch_alert := true | |
else | |
bull_bos_alert := true | |
txt = choch ? 'CHoCH' : 'BOS' | |
if show_Structure | |
if show_bull == 'All' or (show_bull == 'BOS' and not choch) or (show_bull == 'CHoCH' and choch) | |
display_Structure(top_x, top_y, txt, bull_css, false, true, size.small) | |
//Order Block | |
if show_ob | |
ob_coord(false, top_x, ob_top, ob_btm, ob_left, ob_right, ob_type, ob_mit) | |
top_cross := false | |
trend := 1 | |
//-----------------------------------------------------------------------------} | |
//Pivot Low BOS/CHoCH | |
//-----------------------------------------------------------------------------{ | |
var bear_concordant = true | |
if ifilter_confluence | |
bear_concordant := high - math.max(close, open) < math.min(close, open - low) | |
//Detect internal bearish Structure | |
if ta.crossunder(close, ibtm_y) and ibtm_cross and btm_y != ibtm_y and bear_concordant | |
bool choch = false | |
if itrend > 0 | |
choch := true | |
bear_ichoch_alert := true | |
else | |
bear_ibos_alert := true | |
txt = choch ? 'CHoCH' : 'BOS' | |
if show_internals | |
if show_ibear == 'All' or (show_ibear == 'BOS' and not choch) or (show_ibear == 'CHoCH' and choch) | |
display_Structure(ibtm_x, ibtm_y, txt, ibear_css, true, false, size.tiny) | |
ibtm_cross := false | |
itrend := -1 | |
//Internal Order Block | |
if show_iob | |
ob_coord(true, ibtm_x, iob_top, iob_btm, iob_left, iob_right, iob_type, iob_mit) | |
//Detect bearish Structure | |
if ta.crossunder(close, btm_y) and btm_cross | |
bool choch = na | |
if trend > 0 | |
choch := true | |
bear_choch_alert := true | |
else | |
bear_bos_alert := true | |
txt = choch ? 'CHoCH' : 'BOS' | |
if show_Structure | |
if show_bear == 'All' or (show_bear == 'BOS' and not choch) or (show_bear == 'CHoCH' and choch) | |
display_Structure(btm_x, btm_y, txt, bear_css, false, false, size.small) | |
//Order Block | |
if show_ob | |
ob_coord(true, btm_x, ob_top, ob_btm, ob_left, ob_right, ob_type, ob_mit) | |
btm_cross := false | |
trend := -1 | |
//-----------------------------------------------------------------------------} | |
//Order Blocks | |
//-----------------------------------------------------------------------------{ | |
//Set order blocks | |
var iob_boxes = array.new_box(0) | |
var ob_boxes = array.new_box(0) | |
//Delete internal order blocks box coordinates if top/bottom is broken | |
for element in iob_type | |
index = array.indexof(iob_type, element) | |
// Mark internal orderbox as mitigated if price tapped inside the orderblock | |
if ob_highlight_mit | |
if element == 1 and low[1] > array.get(iob_top, index) and low <= array.get(iob_top, index) | |
array.set(iob_mit, index, array.get(iob_mit, index) + 1) | |
array.set(iob_right, index, time) | |
bull_iob_mit := true | |
else if element == -1 and high[1] < array.get(iob_btm, index) and high >= array.get(iob_btm, index) | |
array.set(iob_mit, index, array.get(iob_mit, index) + 1) | |
array.set(iob_right, index, time) | |
bear_iob_mit := true | |
// box.new() | |
if close < array.get(iob_btm, index) and element == 1 | |
array.remove(iob_top, index) | |
array.remove(iob_btm, index) | |
array.remove(iob_left, index) | |
array.remove(iob_right, index) | |
array.remove(iob_type, index) | |
array.remove(iob_mit, index) | |
bull_iob_break := true | |
else if close > array.get(iob_top, index) and element == -1 | |
array.remove(iob_top, index) | |
array.remove(iob_btm, index) | |
array.remove(iob_left, index) | |
array.remove(iob_right, index) | |
array.remove(iob_type, index) | |
array.remove(iob_mit, index) | |
bear_iob_break := true | |
//Delete internal order blocks box coordinates if top/bottom is broken | |
for element in ob_type | |
index = array.indexof(ob_type, element) | |
if ob_highlight_mit | |
if element == 1 and low[1] > array.get(ob_top, index) and low <= array.get(ob_top, index) | |
array.set(ob_mit, index, array.get(ob_mit, index) + 1) | |
array.set(ob_right, index, time) | |
bull_ob_mit := true | |
else if element == -1 and high[1] < array.get(ob_btm, index) and high >= array.get(ob_btm, index) | |
array.set(ob_mit, index, array.get(ob_mit, index) + 1) | |
array.set(ob_right, index, time) | |
bear_ob_mit := true | |
if close < array.get(ob_btm, index) and element == 1 | |
array.remove(ob_top, index) | |
array.remove(ob_btm, index) | |
array.remove(ob_left, index) | |
array.remove(ob_right, index) | |
array.remove(ob_type, index) | |
array.remove(ob_mit, index) | |
bull_ob_break := true | |
else if close > array.get(ob_top, index) and element == -1 | |
array.remove(ob_top, index) | |
array.remove(ob_btm, index) | |
array.remove(ob_left, index) | |
array.remove(ob_right, index) | |
array.remove(ob_type, index) | |
array.remove(ob_mit, index) | |
bear_ob_break := true | |
iob_size = array.size(iob_type) | |
ob_size = array.size(ob_type) | |
if barstate.isfirst | |
if show_iob | |
for i = 0 to iob_showlast-1 | |
array.push(iob_boxes, box.new(na,na,na,na, xloc = xloc.bar_time)) | |
if show_ob | |
for i = 0 to ob_showlast-1 | |
array.push(ob_boxes, box.new(na,na,na,na, xloc = xloc.bar_time)) | |
if iob_size > 0 | |
if barstate.islast | |
display_ob(iob_boxes, iob_top, iob_btm, iob_left, iob_right, iob_type, iob_mit, iob_showlast, false, iob_size) | |
if ob_size > 0 | |
if barstate.islast | |
display_ob(ob_boxes, ob_top, ob_btm, ob_left, ob_right, ob_type, ob_mit, ob_showlast, true, ob_size) | |
//-----------------------------------------------------------------------------} | |
//EQH/EQL | |
//-----------------------------------------------------------------------------{ | |
var eq_prev_top = 0. | |
var eq_top_x = 0 | |
var eq_prev_btm = 0. | |
var eq_btm_x = 0 | |
if show_eq | |
eq_top = ta.pivothigh(eq_len, eq_len) | |
eq_btm = ta.pivotlow(eq_len, eq_len) | |
if eq_top | |
max = math.max(eq_top, eq_prev_top) | |
min = math.min(eq_top, eq_prev_top) | |
if max < min + atr * eq_threshold | |
eqh_line = line.new(eq_top_x, eq_prev_top, n-eq_len, eq_top | |
, color = bear_css | |
, style = line.style_dotted) | |
eqh_lbl = label.new(int(math.avg(n-eq_len, eq_top_x)), eq_top, 'EQH' | |
, color = #00000000 | |
, textcolor = bear_css | |
, style = label.style_label_down | |
, size = size.tiny) | |
if mode == 'Present' | |
line.delete(eqh_line[1]) | |
label.delete(eqh_lbl[1]) | |
eqh_alert := true | |
eq_prev_top := eq_top | |
eq_top_x := n-eq_len | |
if eq_btm | |
max = math.max(eq_btm, eq_prev_btm) | |
min = math.min(eq_btm, eq_prev_btm) | |
if min > max - atr * eq_threshold | |
eql_line = line.new(eq_btm_x, eq_prev_btm, n-eq_len, eq_btm | |
, color = bull_css | |
, style = line.style_dotted) | |
eql_lbl = label.new(int(math.avg(n-eq_len, eq_btm_x)), eq_btm, 'EQL' | |
, color = #00000000 | |
, textcolor = bull_css | |
, style = label.style_label_up | |
, size = size.tiny) | |
eql_alert := true | |
if mode == 'Present' | |
line.delete(eql_line[1]) | |
label.delete(eql_lbl[1]) | |
eq_prev_btm := eq_btm | |
eq_btm_x := n-eq_len | |
//-----------------------------------------------------------------------------} | |
//Fair Value Gaps | |
//-----------------------------------------------------------------------------{ | |
var bullish_fvg_max = array.new_box(0) | |
var bullish_fvg_min = array.new_box(0) | |
var bearish_fvg_max = array.new_box(0) | |
var bearish_fvg_min = array.new_box(0) | |
float bullish_fvg_avg = na | |
float bearish_fvg_avg = na | |
bullish_fvg_cnd = false | |
bearish_fvg_cnd = false | |
[src_c1, src_o1, src_h, src_l, src_h2, src_l2] = | |
request.security(syminfo.tickerid, fvg_tf, get_ohlc()) | |
if show_fvg | |
delta_per = (src_c1 - src_o1) / src_o1 * 100 | |
change_tf = timeframe.change(fvg_tf) | |
threshold = fvg_auto ? ta.cum(math.abs(change_tf ? delta_per : 0)) / n * 2 | |
: 0 | |
//FVG conditions | |
bullish_fvg_cnd := src_l > src_h2 | |
and src_c1 > src_h2 | |
and delta_per > threshold | |
and change_tf | |
bearish_fvg_cnd := src_h < src_l2 | |
and src_c1 < src_l2 | |
and -delta_per > threshold | |
and change_tf | |
//FVG Areas | |
if bullish_fvg_cnd | |
array.unshift(bullish_fvg_max, box.new(n-1, src_l, n + fvg_extend, math.avg(src_l, src_h2) | |
, border_color = bull_fvg_css | |
, bgcolor = bull_fvg_css)) | |
array.unshift(bullish_fvg_min, box.new(n-1, math.avg(src_l, src_h2), n + fvg_extend, src_h2 | |
, border_color = bull_fvg_css | |
, bgcolor = bull_fvg_css)) | |
if bearish_fvg_cnd | |
array.unshift(bearish_fvg_max, box.new(n-1, src_h, n + fvg_extend, math.avg(src_h, src_l2) | |
, border_color = bear_fvg_css | |
, bgcolor = bear_fvg_css)) | |
array.unshift(bearish_fvg_min, box.new(n-1, math.avg(src_h, src_l2), n + fvg_extend, src_l2 | |
, border_color = bear_fvg_css | |
, bgcolor = bear_fvg_css)) | |
for bx in bullish_fvg_min | |
if low < box.get_bottom(bx) | |
box.delete(bx) | |
box.delete(array.get(bullish_fvg_max, array.indexof(bullish_fvg_min, bx))) | |
for bx in bearish_fvg_max | |
if high > box.get_top(bx) | |
box.delete(bx) | |
box.delete(array.get(bearish_fvg_min, array.indexof(bearish_fvg_max, bx))) | |
//-----------------------------------------------------------------------------} | |
//Previous day/week high/lows | |
//-----------------------------------------------------------------------------{ | |
//Daily high/low | |
[pdh, pdl] = request.security(syminfo.tickerid, 'D', hl() | |
, lookahead = barmerge.lookahead_on) | |
//Weekly high/low | |
[pwh, pwl] = request.security(syminfo.tickerid, 'W', hl() | |
, lookahead = barmerge.lookahead_on) | |
//Monthly high/low | |
[pmh, pml] = request.security(syminfo.tickerid, 'M', hl() | |
, lookahead = barmerge.lookahead_on) | |
//Display Daily | |
if show_pdhl | |
phl(pdh, pdl, 'D', pdhl_css) | |
//Display Weekly | |
if show_pwhl | |
phl(pwh, pwl, 'W', pwhl_css) | |
//Display Monthly | |
if show_pmhl | |
phl(pmh, pml, 'M', pmhl_css) | |
//-----------------------------------------------------------------------------} | |
//Premium/Discount/Equilibrium zones | |
//-----------------------------------------------------------------------------{ | |
var premium = box.new(na, na, na, na | |
, bgcolor = color.new(premium_css, 80) | |
, border_color = na) | |
var premium_lbl = label.new(na, na | |
, text = 'Premium' | |
, color = TRANSP_CSS | |
, textcolor = premium_css | |
, style = label.style_label_down | |
, size = size.small) | |
var eq = box.new(na, na, na, na | |
, bgcolor = color.rgb(120, 123, 134, 80) | |
, border_color = na) | |
var eq_lbl = label.new(na, na | |
, text = 'Equilibrium' | |
, color = TRANSP_CSS | |
, textcolor = eq_css | |
, style = label.style_label_left | |
, size = size.small) | |
var discount = box.new(na, na, na, na | |
, bgcolor = color.new(discount_css, 80) | |
, border_color = na) | |
var discount_lbl = label.new(na, na | |
, text = 'Discount' | |
, color = TRANSP_CSS | |
, textcolor = discount_css | |
, style = label.style_label_up | |
, size = size.small) | |
//Show Premium/Discount Areas | |
if barstate.islast and show_sd | |
avg = math.avg(trail_up, trail_dn) | |
box.set_lefttop(premium, math.max(top_x, btm_x), trail_up) | |
box.set_rightbottom(premium, n, .95 * trail_up + .05 * trail_dn) | |
label.set_xy(premium_lbl, int(math.avg(math.max(top_x, btm_x), n)), trail_up) | |
box.set_lefttop(eq, math.max(top_x, btm_x), .525 * trail_up + .475*trail_dn) | |
box.set_rightbottom(eq, n, .525 * trail_dn + .475 * trail_up) | |
label.set_xy(eq_lbl, n, avg) | |
box.set_lefttop(discount, math.max(top_x, btm_x), .95 * trail_dn + .05 * trail_up) | |
box.set_rightbottom(discount, n, trail_dn) | |
label.set_xy(discount_lbl, int(math.avg(math.max(top_x, btm_x), n)), trail_dn) | |
//-----------------------------------------------------------------------------} | |
//Trend | |
//-----------------------------------------------------------------------------{ | |
var color trend_css = na | |
if show_trend | |
if style == 'Colored' | |
trend_css := itrend == 1 ? bull_css : bear_css | |
else if style == 'Monochrome' | |
trend_css := itrend == 1 ? #b2b5be : #5d606b | |
plotcandle(open, high, low, close | |
, color = trend_css | |
, wickcolor = trend_css | |
, bordercolor = trend_css | |
, editable = false) | |
//-----------------------------------------------------------------------------} | |
//Alerts | |
//-----------------------------------------------------------------------------{ | |
//Internal Structure | |
alertcondition(bull_ibos_alert, 'Internal Bullish BOS', 'Internal Bullish BOS formed') | |
alertcondition(bull_ichoch_alert, 'Internal Bullish CHoCH', 'Internal Bullish CHoCH formed') | |
alertcondition(bear_ibos_alert, 'Internal Bearish BOS', 'Internal Bearish BOS formed') | |
alertcondition(bear_ichoch_alert, 'Internal Bearish CHoCH', 'Internal Bearish CHoCH formed') | |
//Swing Structure | |
alertcondition(bull_bos_alert, 'Bullish BOS', 'Internal Bullish BOS formed') | |
alertcondition(bull_choch_alert, 'Bullish CHoCH', 'Internal Bullish CHoCH formed') | |
alertcondition(bear_bos_alert, 'Bearish BOS', 'Bearish BOS formed') | |
alertcondition(bear_choch_alert, 'Bearish CHoCH', 'Bearish CHoCH formed') | |
//order Blocks | |
alertcondition(bull_iob_break, 'Bullish Internal OB Breakout', 'Price broke bullish iternal OB') | |
alertcondition(bear_iob_break, 'Bearish Internal OB Breakout', 'Price broke bearish iternal OB') | |
alertcondition(bull_ob_break, 'Bullish OB Breakout', 'Price broke bullish OB') | |
alertcondition(bear_ob_break, 'bearish OB Breakout', 'Price broke bearish OB') | |
alertcondition(bull_iob_mit, 'Bullish Internal OB Mitigated', 'Bullish internal OB mitigated') | |
alertcondition(bear_iob_mit, 'Bearish Internal OB Mitigated', 'Bearish internal OB mitigated') | |
alertcondition(bull_ob_mit, 'Bullish OB Mitigated', 'Bullish OB mitigated') | |
alertcondition(bear_ob_mit, 'Bearish OB Mitigated', 'Bearish OB mitigated') | |
//EQH/EQL | |
alertcondition(eqh_alert, 'Equal Highs', 'Equal highs detected') | |
alertcondition(eql_alert, 'Equal Lows', 'Equal lows detected') | |
//FVG | |
alertcondition(bullish_fvg_cnd, 'Bullish FVG', 'Bullish FVG formed') | |
alertcondition(bearish_fvg_cnd, 'Bearish FVG', 'Bearish FVG formed') | |
//-----------------------------------------------------------------------------} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
IS THERE A VERSION OF THIS CODING WRITTEN IN PYTHON?