-
-
Save niquedegraaff/8c2f45dc73519458afeae14b0096d719 to your computer and use it in GitHub Desktop.
| // 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') | |
| //-----------------------------------------------------------------------------} | |
IS THERE A VERSION OF THIS CODING WRITTEN IN PYTHON?
IS THERE A VERSION OF THIS CODING WRITTEN IN PYTHON?
This is pinescript, written for tradingview, there is not python version as this interacts with the TradingView api inside the tradingview client.
can this Pine script be converted to MQL5? in a bid to use it to develop an expert advisor?
Probably, but you'll have to do it yourself :)
I need just part of this code's Adaptation of luxalgo smart money concepts indicator for just order blocks with just Two timeframe options (daily and hourly) swing and internal order block with marking from candle open to candle close wick for use in tradingview.
can this Pine script be converted to MQL5? in a bid to use it to develop an expert advisor?
were you able to get the mql5
`//+------------------------------------------------------------------+
//| Smart_Money_Concepts_Lux.mq5 |
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0
//--- Define maximum number of objects to draw
#define MAX_LABELS 500
#define MAX_LINES 500
#define MAX_BOXES 500
//--- Input parameters
input group "Smart Money Concepts"
input string Mode = "Historical"; // Historical or Present
input string Style = "Colored"; // Colored or Monochrome
input bool ShowTrend = false; // Color Candles
input group "Real Time Internal Structure"
input bool ShowInternals = true; // Show Internal Structure
input string ShowIBull = "All"; // Bullish Structure: All, BOS, CHoCH
input color SwingIBullCss = clrDarkGreen;
input string ShowIBear = "All"; // Bearish Structure: All, BOS, CHoCH
input color SwingIBearCss = clrRed;
input bool FilterConfluence = false; // Confluence Filter
input group "Real Time Swing Structure"
input bool ShowStructure = true; // Show Swing Structure
input string ShowBull = "All"; // Bullish Structure: All, BOS, CHoCH
input color SwingBullCss = clrDarkGreen;
input string ShowBear = "All"; // Bearish Structure: All, BOS, CHoCH
input color SwingBearCss = clrRed;
input bool ShowSwings = false; // Show Swings Points
input int Length = 50; // Length for swing detection
input bool ShowHLSwings = true; // Show Strong/Weak High/Low
input group "Order Blocks"
input bool ShowIOB = true; // Internal Order Blocks
input int IOBShowLast = 5; // Number of internal order blocks to display
input bool ShowOB = false; // Swing Order Blocks
input int OBShowLast = 5; // Number of swing order blocks to display
input string OBFilter = "Atr"; // Order Block Filter: Atr, Cumulative Mean Range
input bool OBHighlightMit = true; // Highlight Mitigated Order blocks
input color IBullObCss = C'52,121,245,204'; // Internal Bullish OB with transparency
input color IBullmObCss = C'99,99,99,204'; // Internal Bullish Mitigated OB
input color IBearObCss = C'247,124,128,204'; // Internal Bearish OB with transparency
input color IBearmObCss = C'99,99,99,204'; // Internal Bearish Mitigated OB
input color BullObCss = C'24,72,204,204'; // Bullish OB with transparency
input color BullmObCss = C'99,99,99,204'; // Bullish Mitigated OB
input color BearObCss = C'178,40,51,204'; // Bearish OB with transparency
input color BearmObCss = C'99,99,99,204'; // Bearish Mitigated OB
input group "EQH/EQL"
input bool ShowEQ = true; // Equal High/Low
input int EQLen = 3; // Bars Confirmation
input float EQThreshold = 0.1; // Threshold
input group "Fair Value Gaps"
input bool ShowFVG = false; // Fair Value Gaps
input bool FVGAuto = true; // Auto Threshold
input string FVGTF = ""; // Timeframe
input color BullFvgCss = C'0,255,104,178'; // Bullish FVG with transparency
input color BearFvgCss = C'255,0,8,178'; // Bearish FVG with transparency
input int FVGExtend = 1; // Extend FVG
input group "Highs & Lows MTF"
input bool ShowPDHL = false; // Daily
input string PDHLStyle = "⎯⎯⎯"; // Style: ⎯⎯⎯, ----, ····
input color PDHLCss = clrDodgerBlue;
input bool ShowPWHL = false; // Weekly
input string PWHLStyle = "⎯⎯⎯"; // Style: ⎯⎯⎯, ----, ····
input color PWHLCss = clrDodgerBlue;
input bool ShowPMHL = false; // Monthly
input string PMHLStyle = "⎯⎯⎯"; // Style: ⎯⎯⎯, ----, ····
input color PMHLCss = clrDodgerBlue;
input group "Premium & Discount Zones"
input bool ShowSD = false; // Premium/Discount Zones
input color PremiumCss = clrRed;
input color EqCss = C'178,181,190'; // Equilibrium Zone
input color DiscountCss = clrDarkGreen;
//--- Global variables
int trend;
int itrend;
double top_y;
int top_x;
double btm_y;
int btm_x;
double itop_y;
int itop_x;
double ibtm_y;
int ibtm_x;
double trail_up;
double trail_dn;
int trail_up_x;
int trail_dn_x;
bool top_cross;
bool btm_cross;
bool itop_cross;
bool ibtm_cross;
string txt_top;
string txt_btm;
//--- Arrays for order blocks
double iob_top[];
double iob_btm[];
datetime iob_left[];
datetime iob_right[];
int iob_type[];
int iob_mit[];
double ob_top[];
double ob_btm[];
datetime ob_left[];
datetime ob_right[];
int ob_type[];
int ob_mit[];
//--- ATR handle and buffer
int atr_handle;
double atr_buffer[];
//--- Alert variables
bool bull_choch_alert;
bool bull_bos_alert;
bool bear_choch_alert;
bool bear_bos_alert;
bool bull_ichoch_alert;
bool bull_ibos_alert;
bool bear_ichoch_alert;
bool bear_ibos_alert;
bool bull_iob_mit;
bool bear_iob_mit;
bool bull_ob_mit;
bool bear_ob_mit;
bool bull_iob_break;
bool bear_iob_break;
bool bull_ob_break;
bool bear_ob_break;
bool eqh_alert;
bool eql_alert;
bool bullish_fvg_cnd;
bool bearish_fvg_cnd;
//--- FVG variables
double bullish_fvg_max[];
double bullish_fvg_min[];
datetime bullish_fvg_time[];
double bearish_fvg_max[];
double bearish_fvg_min[];
datetime bearish_fvg_time[];
//--- EQH/EQL variables
double eq_prev_top;
int eq_top_x;
double eq_prev_btm;
int eq_btm_x;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Set indicator to calculate on all ticks
IndicatorSetInteger(INDICATOR_CALCULATIONS, -1);
//--- Initialize arrays
ArrayResize(iob_top, MAX_BOXES);
ArrayResize(iob_btm, MAX_BOXES);
ArrayResize(iob_left, MAX_BOXES);
ArrayResize(iob_right, MAX_BOXES);
ArrayResize(iob_type, MAX_BOXES);
ArrayResize(iob_mit, MAX_BOXES);
ArrayResize(ob_top, MAX_BOXES);
ArrayResize(ob_btm, MAX_BOXES);
ArrayResize(ob_left, MAX_BOXES);
ArrayResize(ob_right, MAX_BOXES);
ArrayResize(ob_type, MAX_BOXES);
ArrayResize(ob_mit, MAX_BOXES);
//--- Initialize FVG arrays
ArrayResize(bullish_fvg_max, MAX_BOXES);
ArrayResize(bullish_fvg_min, MAX_BOXES);
ArrayResize(bullish_fvg_time, MAX_BOXES);
ArrayResize(bearish_fvg_max, MAX_BOXES);
ArrayResize(bearish_fvg_min, MAX_BOXES);
ArrayResize(bearish_fvg_time, MAX_BOXES);
//--- Initialize ATR
atr_handle = iATR(_Symbol, _Period, 200);
if(atr_handle == INVALID_HANDLE)
{
Print("Error creating ATR indicator handle: ", GetLastError());
return(INIT_FAILED);
}
//--- Set ATR buffer
ArraySetAsSeries(atr_buffer, true);
//--- Initialize variables
trend = 0;
itrend = 0;
top_cross = true;
btm_cross = true;
itop_cross = true;
ibtm_cross = true;
eq_prev_top = 0;
eq_top_x = 0;
eq_prev_btm = 0;
eq_btm_x = 0;
//--- Initialize alert variables
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;
bullish_fvg_cnd = false;
bearish_fvg_cnd = false;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Delete all objects created by the indicator
ObjectsDeleteAll(0, "StructureLine_");
ObjectsDeleteAll(0, "StructureLabel_");
ObjectsDeleteAll(0, "IOB_");
ObjectsDeleteAll(0, "OB_");
ObjectsDeleteAll(0, "EQH_");
ObjectsDeleteAll(0, "EQL_");
ObjectsDeleteAll(0, "FVG_");
ObjectsDeleteAll(0, "PDHL_");
ObjectsDeleteAll(0, "PWHL_");
ObjectsDeleteAll(0, "PMHL_");
ObjectsDeleteAll(0, "Premium_");
ObjectsDeleteAll(0, "Equilibrium_");
ObjectsDeleteAll(0, "Discount_");
//--- Release indicator handle
if(atr_handle != INVALID_HANDLE)
IndicatorRelease(atr_handle);
}
//+------------------------------------------------------------------+
//| Helper function to detect swings (pivot highs and lows) |
//+------------------------------------------------------------------+
void DetectSwings(int length, double &top, double &btm)
{
double high[], low[];
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
CopyHigh(_Symbol, _Period, 0, length2, high);
CopyLow(_Symbol, _Period, 0, length2, low);
double upper = high[ArrayMaximum(high, 0, length)];
double lower = low[ArrayMinimum(low, 0, length)];
static int os = 0;
if(high[length] > upper)
os = 0;
else if(low[length] < lower)
os = 1;
if(os == 0 && os != 1)
top = high[length];
else
top = 0;
if(os == 1 && os != 0)
btm = low[length];
else
btm = 0;
}
//+------------------------------------------------------------------+
//| Helper function to draw structure lines and labels |
//+------------------------------------------------------------------+
void DrawStructure(datetime x, double y, string txt, color clr, bool dashed, bool down, string size)
{
//--- Create line
string line_name = "StructureLine_" + IntegerToString(ChartID()) + "_" + TimeToString(TimeCurrent());
ObjectCreate(0, line_name, OBJ_TREND, 0, x, y, TimeCurrent(), y);
ObjectSetInteger(0, line_name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, line_name, OBJPROP_STYLE, dashed ? STYLE_DASH : STYLE_SOLID);
ObjectSetInteger(0, line_name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, line_name, OBJPROP_RAY_RIGHT, false);
//--- Create label
string label_name = "StructureLabel_" + IntegerToString(ChartID()) + "_" + TimeToString(TimeCurrent());
ObjectCreate(0, label_name, OBJ_TEXT, 0, x, y);
ObjectSetString(0, label_name, OBJPROP_TEXT, txt);
ObjectSetInteger(0, label_name, OBJPROP_COLOR, clr);
//--- Set label size
int label_size;
if(size == "Tiny")
label_size = 7;
else if(size == "Small")
label_size = 9;
else // Normal
label_size = 11;
ObjectSetInteger(0, label_name, OBJPROP_FONTSIZE, label_size);
//--- Set label anchor
if(down)
ObjectSetInteger(0, label_name, OBJPROP_ANCHOR, ANCHOR_UPPER);
else
ObjectSetInteger(0, label_name, OBJPROP_ANCHOR, ANCHOR_LOWER);
//--- Delete objects in "Present" mode
if(Mode == "Present")
{
ObjectDelete(0, line_name);
ObjectDelete(0, label_name);
}
}
//+------------------------------------------------------------------+
//| Helper function to get order block coordinates |
//+------------------------------------------------------------------+
void OBCoord(bool useMax, int loc, double &targetTop[], double &targetBtm[],
datetime &targetLeft[], datetime &targetRight[], int &targetType[], int &targetMit[])
{
double high[], low[], atr[];
datetime time[];
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(atr, true);
ArraySetAsSeries(time, true);
int bars = Bars(_Symbol, _Period);
CopyHigh(_Symbol, _Period, 0, bars, high);
CopyLow(_Symbol, _Period, 0, bars, low);
CopyBuffer(atr_handle, 0, 0, bars, atr);
CopyTime(_Symbol, _Period, 0, bars, time);
double min = 99999999.0;
double max = 0.0;
int idx = 1;
double obThreshold;
if(OBFilter == "Atr")
obThreshold = atr[0];
else
{
// Calculate cumulative mean range
double cumRange = 0;
for(int i = 0; i < bars; i++)
cumRange += high[i] - low[i];
obThreshold = cumRange / bars;
}
// Search for highest/lowest high within the structure interval and get range
if(useMax)
{
for(int i = 1; i < (bars - loc) - 1; i++)
{
if((high[i] - low[i]) < obThreshold * 2)
{
if(high[i] > max)
{
max = high[i];
min = low[i];
idx = i;
}
}
}
}
else
{
for(int i = 1; i < (bars - loc) - 1; i++)
{
if((high[i] - low[i]) < obThreshold * 2)
{
if(low[i] < min)
{
min = low[i];
max = high[i];
idx = i;
}
}
}
}
// Add to arrays
int size = ArraySize(targetTop);
ArrayResize(targetTop, size + 1);
ArrayResize(targetBtm, size + 1);
ArrayResize(targetLeft, size + 1);
ArrayResize(targetRight, size + 1);
ArrayResize(targetType, size + 1);
ArrayResize(targetMit, size + 1);
// Shift array elements
for(int i = size; i > 0; i--)
{
targetTop[i] = targetTop[i-1];
targetBtm[i] = targetBtm[i-1];
targetLeft[i] = targetLeft[i-1];
targetRight[i] = targetRight[i-1];
targetType[i] = targetType[i-1];
targetMit[i] = targetMit[i-1];
}
// Add new element at the beginning
targetTop[0] = max;
targetBtm[0] = min;
targetLeft[0] = time[idx];
targetRight[0] = time[idx];
targetType[0] = useMax ? -1 : 1;
targetMit[0] = 0;
}
//+------------------------------------------------------------------+
//| Helper function to draw order blocks |
//+------------------------------------------------------------------+
void DrawOrderBlocks(string prefix, double &targetTop[], double &targetBtm[],
datetime &targetLeft[], datetime &targetRight[], int &targetType[], int &targetMit[],
int showLast, bool isSwing, int size, color bullCss, color bullmCss, color bearCss, color bearmCss)
{
for(int i = 0; i < MathMin(showLast, size); i++)
{
if(targetLeft[i] == 0) continue;
string box_name = prefix + "_" + IntegerToString(i) + "_" + IntegerToString(ChartID());
//--- Create or update rectangle
if(ObjectFind(0, box_name) < 0)
{
ObjectCreate(0, box_name, OBJ_RECTANGLE, 0, targetLeft[i], targetTop[i], targetRight[i], targetBtm[i]);
ObjectSetInteger(0, box_name, OBJPROP_BACK, true);
}
else
{
ObjectSetInteger(0, box_name, OBJPROP_TIME1, targetLeft[i]);
ObjectSetInteger(0, box_name, OBJPROP_PRICE1, targetTop[i]);
ObjectSetInteger(0, box_name, OBJPROP_TIME2, targetRight[i]);
ObjectSetInteger(0, box_name, OBJPROP_PRICE2, targetBtm[i]);
}
//--- Set color
color clr;
if(Style == "Monochrome")
clr = (targetType[i] == 1) ? C'178,181,190,204' : C'93,96,107,204';
else
{
if(targetMit[i] > 0)
clr = (targetType[i] == 1) ? bullmCss : bearmCss;
else
clr = (targetType[i] == 1) ? bullCss : bearCss;
}
ObjectSetInteger(0, box_name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, box_name, OBJPROP_FILL, true);
ObjectSetInteger(0, box_name, OBJPROP_BACK, true);
//--- Set extension
if(targetMit[i] > 0)
ObjectSetInteger(0, box_name, OBJPROP_RAY_RIGHT, false);
else
ObjectSetInteger(0, box_name, OBJPROP_RAY_RIGHT, true);
}
}
//+------------------------------------------------------------------+
//| Helper function to draw previous high/low lines |
//+------------------------------------------------------------------+
void DrawPHL(double high, double low, string tf, color clr, string style)
{
datetime time[];
double high_arr[], low_arr[];
ArraySetAsSeries(time, true);
ArraySetAsSeries(high_arr, true);
ArraySetAsSeries(low_arr, true);
int copied = CopyTime(_Symbol, _Period, 0, Bars(_Symbol, _Period), time);
CopyHigh(_Symbol, _Period, 0, Bars(_Symbol, _Period), high_arr);
CopyLow(_Symbol, _Period, 0, Bars(_Symbol, _Period), low_arr);
// Find last high and low
datetime high_time = 0;
datetime low_time = 0;
double last_high = 0;
double last_low = 0;
for(int i = 0; i < copied; i++)
{
if(high_arr[i] == high)
{
last_high = high;
high_time = time[i];
}
if(low_arr[i] == low)
{
last_low = low;
low_time = time[i];
}
}
if(high_time > 0)
{
string high_line_name = "PDHL_" + tf + "High" + IntegerToString(ChartID());
string high_lbl_name = "PDHL_" + tf + "HighLbl" + IntegerToString(ChartID());
// Create or update high line
if(ObjectFind(0, high_line_name) < 0)
{
ObjectCreate(0, high_line_name, OBJ_TREND, 0, high_time, last_high, TimeCurrent(), last_high);
ObjectSetInteger(0, high_line_name, OBJPROP_COLOR, clr);
int line_style = STYLE_SOLID;
if(style == "----")
line_style = STYLE_DASH;
else if(style == "····")
line_style = STYLE_DOT;
ObjectSetInteger(0, high_line_name, OBJPROP_STYLE, line_style);
ObjectSetInteger(0, high_line_name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, high_line_name, OBJPROP_RAY_RIGHT, true);
}
else
{
ObjectSetInteger(0, high_line_name, OBJPROP_TIME1, high_time);
ObjectSetInteger(0, high_line_name, OBJPROP_PRICE1, last_high);
ObjectSetInteger(0, high_line_name, OBJPROP_TIME2, TimeCurrent());
ObjectSetInteger(0, high_line_name, OBJPROP_PRICE2, last_high);
}
// Create or update high label
if(ObjectFind(0, high_lbl_name) < 0)
{
ObjectCreate(0, high_lbl_name, OBJ_TEXT, 0, TimeCurrent(), last_high);
ObjectSetString(0, high_lbl_name, OBJPROP_TEXT, "P" + tf + "H");
ObjectSetInteger(0, high_lbl_name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, high_lbl_name, OBJPROP_ANCHOR, ANCHOR_LEFT);
ObjectSetInteger(0, high_lbl_name, OBJPROP_FONTSIZE, 8);
}
else
{
ObjectSetInteger(0, high_lbl_name, OBJPROP_TIME, TimeCurrent());
ObjectSetInteger(0, high_lbl_name, OBJPROP_PRICE, last_high);
}
}
if(low_time > 0)
{
string low_line_name = "PDHL_" + tf + "Low" + IntegerToString(ChartID());
string low_lbl_name = "PDHL_" + tf + "LowLbl" + IntegerToString(ChartID());
// Create or update low line
if(ObjectFind(0, low_line_name) < 0)
{
ObjectCreate(0, low_line_name, OBJ_TREND, 0, low_time, last_low, TimeCurrent(), last_low);
ObjectSetInteger(0, low_line_name, OBJPROP_COLOR, clr);
int line_style = STYLE_SOLID;
if(style == "----")
line_style = STYLE_DASH;
else if(style == "····")
line_style = STYLE_DOT;
ObjectSetInteger(0, low_line_name, OBJPROP_STYLE, line_style);
ObjectSetInteger(0, low_line_name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, low_line_name, OBJPROP_RAY_RIGHT, true);
}
else
{
ObjectSetInteger(0, low_line_name, OBJPROP_TIME1, low_time);
ObjectSetInteger(0, low_line_name, OBJPROP_PRICE1, last_low);
ObjectSetInteger(0, low_line_name, OBJPROP_TIME2, TimeCurrent());
ObjectSetInteger(0, low_line_name, OBJPROP_PRICE2, last_low);
}
// Create or update low label
if(ObjectFind(0, low_lbl_name) < 0)
{
ObjectCreate(0, low_lbl_name, OBJ_TEXT, 0, TimeCurrent(), last_low);
ObjectSetString(0, low_lbl_name, OBJPROP_TEXT, "P" + tf + "L");
ObjectSetInteger(0, low_lbl_name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, low_lbl_name, OBJPROP_ANCHOR, ANCHOR_LEFT);
ObjectSetInteger(0, low_lbl_name, OBJPROP_FONTSIZE, 8);
}
else
{
ObjectSetInteger(0, low_lbl_name, OBJPROP_TIME, TimeCurrent());
ObjectSetInteger(0, low_lbl_name, OBJPROP_PRICE, last_low);
}
}
}
//+------------------------------------------------------------------+
//| Helper function to draw premium/discount zones |
//+------------------------------------------------------------------+
void DrawPremiumDiscountZones()
{
string premium_box = "Premium_" + IntegerToString(ChartID());
string premium_lbl = "PremiumLbl_" + IntegerToString(ChartID());
string eq_box = "Equilibrium_" + IntegerToString(ChartID());
string eq_lbl = "EquilibriumLbl_" + IntegerToString(ChartID());
string discount_box = "Discount_" + IntegerToString(ChartID());
string discount_lbl = "DiscountLbl_" + IntegerToString(ChartID());
datetime time[];
double high[], low[];
ArraySetAsSeries(time, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
int copied = CopyTime(_Symbol, _Period, 0, Bars(_Symbol, _Period), time);
CopyHigh(_Symbol, _Period, 0, Bars(_Symbol, _Period), high);
CopyLow(_Symbol, _Period, 0, Bars(_Symbol, _Period), low);
// Find start time
datetime start_time = time[MathMax(top_x, btm_x)];
// Calculate average
double avg = (trail_up + trail_dn) / 2;
// Create or update premium zone
if(ObjectFind(0, premium_box) < 0)
{
ObjectCreate(0, premium_box, OBJ_RECTANGLE, 0, start_time, trail_up, TimeCurrent(), 0.95 * trail_up + 0.05 * trail_dn);
ObjectSetInteger(0, premium_box, OBJPROP_COLOR, PremiumCss);
ObjectSetInteger(0, premium_box, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, premium_box, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, premium_box, OBJPROP_BACK, true);
ObjectSetInteger(0, premium_box, OBJPROP_FILL, true);
}
else
{
ObjectSetInteger(0, premium_box, OBJPROP_TIME1, start_time);
ObjectSetInteger(0, premium_box, OBJPROP_PRICE1, trail_up);
ObjectSetInteger(0, premium_box, OBJPROP_TIME2, TimeCurrent());
ObjectSetInteger(0, premium_box, OBJPROP_PRICE2, 0.95 * trail_up + 0.05 * trail_dn);
}
// Create or update premium label
if(ObjectFind(0, premium_lbl) < 0)
{
ObjectCreate(0, premium_lbl, OBJ_TEXT, 0, TimeCurrent(), trail_up);
ObjectSetString(0, premium_lbl, OBJPROP_TEXT, "Premium");
ObjectSetInteger(0, premium_lbl, OBJPROP_COLOR, PremiumCss);
ObjectSetInteger(0, premium_lbl, OBJPROP_ANCHOR, ANCHOR_LOWER);
ObjectSetInteger(0, premium_lbl, OBJPROP_FONTSIZE, 8);
}
else
{
ObjectSetInteger(0, premium_lbl, OBJPROP_TIME, TimeCurrent());
ObjectSetInteger(0, premium_lbl, OBJPROP_PRICE, trail_up);
}
// Create or update equilibrium zone
if(ObjectFind(0, eq_box) < 0)
{
ObjectCreate(0, eq_box, OBJ_RECTANGLE, 0, start_time, 0.525 * trail_up + 0.475 * trail_dn, TimeCurrent(), 0.525 * trail_dn + 0.475 * trail_up);
ObjectSetInteger(0, eq_box, OBJPROP_COLOR, EqCss);
ObjectSetInteger(0, eq_box, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, eq_box, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, eq_box, OBJPROP_BACK, true);
ObjectSetInteger(0, eq_box, OBJPROP_FILL, true);
}
else
{
ObjectSetInteger(0, eq_box, OBJPROP_TIME1, start_time);
ObjectSetInteger(0, eq_box, OBJPROP_PRICE1, 0.525 * trail_up + 0.475 * trail_dn);
ObjectSetInteger(0, eq_box, OBJPROP_TIME2, TimeCurrent());
ObjectSetInteger(0, eq_box, OBJPROP_PRICE2, 0.525 * trail_dn + 0.475 * trail_up);
}
// Create or update equilibrium label
if(ObjectFind(0, eq_lbl) < 0)
{
ObjectCreate(0, eq_lbl, OBJ_TEXT, 0, TimeCurrent(), avg);
ObjectSetString(0, eq_lbl, OBJPROP_TEXT, "Equilibrium");
ObjectSetInteger(0, eq_lbl, OBJPROP_COLOR, EqCss);
ObjectSetInteger(0, eq_lbl, OBJPROP_ANCHOR, ANCHOR_LEFT);
ObjectSetInteger(0, eq_lbl, OBJPROP_FONTSIZE, 8);
}
else
{
ObjectSetInteger(0, eq_lbl, OBJPROP_TIME, TimeCurrent());
ObjectSetInteger(0, eq_lbl, OBJPROP_PRICE, avg);
}
// Create or update discount zone
if(ObjectFind(0, discount_box) < 0)
{
ObjectCreate(0, discount_box, OBJ_RECTANGLE, 0, start_time, 0.95 * trail_dn + 0.05 * trail_up, TimeCurrent(), trail_dn);
ObjectSetInteger(0, discount_box, OBJPROP_COLOR, DiscountCss);
ObjectSetInteger(0, discount_box, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, discount_box, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, discount_box, OBJPROP_BACK, true);
ObjectSetInteger(0, discount_box, OBJPROP_FILL, true);
}
else
{
ObjectSetInteger(0, discount_box, OBJPROP_TIME1, start_time);
ObjectSetInteger(0, discount_box, OBJPROP_PRICE1, 0.95 * trail_dn + 0.05 * trail_up);
ObjectSetInteger(0, discount_box, OBJPROP_TIME2, TimeCurrent());
ObjectSetInteger(0, discount_box, OBJPROP_PRICE2, trail_dn);
}
// Create or update discount label
if(ObjectFind(0, discount_lbl) < 0)
{
ObjectCreate(0, discount_lbl, OBJ_TEXT, 0, TimeCurrent(), trail_dn);
ObjectSetString(0, discount_lbl, OBJPROP_TEXT, "Discount");
ObjectSetInteger(0, discount_lbl, OBJPROP_COLOR, DiscountCss);
ObjectSetInteger(0, discount_lbl, OBJPROP_ANCHOR, ANCHOR_UPPER);
ObjectSetInteger(0, discount_lbl, OBJPROP_FONTSIZE, 8);
}
else
{
ObjectSetInteger(0, discount_lbl, OBJPROP_TIME, TimeCurrent());
ObjectSetInteger(0, discount_lbl, OBJPROP_PRICE, trail_dn);
}
}
//+------------------------------------------------------------------+
//| Helper function to draw FVG boxes |
//+------------------------------------------------------------------+
void DrawFVGBoxes()
{
for(int i = 0; i < ArraySize(bullish_fvg_max); i++)
{
if(bullish_fvg_time[i] == 0) continue;
string box_name1 = "FVG_BullMax_" + IntegerToString(i) + "_" + IntegerToString(ChartID());
string box_name2 = "FVG_BullMin_" + IntegerToString(i) + "_" + IntegerToString(ChartID());
// Create or update max box
if(ObjectFind(0, box_name1) < 0)
{
ObjectCreate(0, box_name1, OBJ_RECTANGLE, 0, bullish_fvg_time[i], bullish_fvg_max[i], TimeCurrent(), (bullish_fvg_max[i] + bullish_fvg_min[i])/2);
ObjectSetInteger(0, box_name1, OBJPROP_COLOR, BullFvgCss);
ObjectSetInteger(0, box_name1, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, box_name1, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, box_name1, OBJPROP_BACK, true);
ObjectSetInteger(0, box_name1, OBJPROP_FILL, true);
}
else
{
ObjectSetInteger(0, box_name1, OBJPROP_TIME1, bullish_fvg_time[i]);
ObjectSetInteger(0, box_name1, OBJPROP_PRICE1, bullish_fvg_max[i]);
ObjectSetInteger(0, box_name1, OBJPROP_TIME2, TimeCurrent());
ObjectSetInteger(0, box_name1, OBJPROP_PRICE2, (bullish_fvg_max[i] + bullish_fvg_min[i])/2);
}
// Create or update min box
if(ObjectFind(0, box_name2) < 0)
{
ObjectCreate(0, box_name2, OBJ_RECTANGLE, 0, bullish_fvg_time[i], (bullish_fvg_max[i] + bullish_fvg_min[i])/2, TimeCurrent(), bullish_fvg_min[i]);
ObjectSetInteger(0, box_name2, OBJPROP_COLOR, BullFvgCss);
ObjectSetInteger(0, box_name2, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, box_name2, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, box_name2, OBJPROP_BACK, true);
ObjectSetInteger(0, box_name2, OBJPROP_FILL, true);
}
else
{
ObjectSetInteger(0, box_name2, OBJPROP_TIME1, bullish_fvg_time[i]);
ObjectSetInteger(0, box_name2, OBJPROP_PRICE1, (bullish_fvg_max[i] + bullish_fvg_min[i])/2);
ObjectSetInteger(0, box_name2, OBJPROP_TIME2, TimeCurrent());
ObjectSetInteger(0, box_name2, OBJPROP_PRICE2, bullish_fvg_min[i]);
}
}
for(int i = 0; i < ArraySize(bearish_fvg_max); i++)
{
if(bearish_fvg_time[i] == 0) continue;
string box_name1 = "FVG_BearMax_" + IntegerToString(i) + "_" + IntegerToString(ChartID());
string box_name2 = "FVG_BearMin_" + IntegerToString(i) + "_" + IntegerToString(ChartID());
// Create or update max box
if(ObjectFind(0, box_name1) < 0)
{
ObjectCreate(0, box_name1, OBJ_RECTANGLE, 0, bearish_fvg_time[i], bearish_fvg_max[i], TimeCurrent(), (bearish_fvg_max[i] + bearish_fvg_min[i])/2);
ObjectSetInteger(0, box_name1, OBJPROP_COLOR, BearFvgCss);
ObjectSetInteger(0, box_name1, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, box_name1, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, box_name1, OBJPROP_BACK, true);
ObjectSetInteger(0, box_name1, OBJPROP_FILL, true);
}
else
{
ObjectSetInteger(0, box_name1, OBJPROP_TIME1, bearish_fvg_time[i]);
ObjectSetInteger(0, box_name1, OBJPROP_PRICE1, bearish_fvg_max[i]);
ObjectSetInteger(0, box_name1, OBJPROP_TIME2, TimeCurrent());
ObjectSetInteger(0, box_name1, OBJPROP_PRICE2, (bearish_fvg_max[i] + bearish_fvg_min[i])/2);
}
// Create or update min box
if(ObjectFind(0, box_name2) < 0)
{
ObjectCreate(0, box_name2, OBJ_RECTANGLE, 0, bearish_fvg_time[i], (bearish_fvg_max[i] + bearish_fvg_min[i])/2, TimeCurrent(), bearish_fvg_min[i]);
ObjectSetInteger(0, box_name2, OBJPROP_COLOR, BearFvgCss);
ObjectSetInteger(0, box_name2, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, box_name2, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, box_name2, OBJPROP_BACK, true);
ObjectSetInteger(0, box_name2, OBJPROP_FILL, true);
}
else
{
ObjectSetInteger(0, box_name2, OBJPROP_TIME1, bearish_fvg_time[i]);
ObjectSetInteger(0, box_name2, OBJPROP_PRICE1, (bearish_fvg_max[i] + bearish_fvg_min[i])/2);
ObjectSetInteger(0, box_name2, OBJPROP_TIME2, TimeCurrent());
ObjectSetInteger(0, box_name2, OBJPROP_PRICE2, bearish_fvg_min[i]);
}
}
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &real_volume[],
const int &spread[])
{
//--- Check if we have enough data
if(rates_total < Length + 10)
return(0);
//--- Copy ATR values
if(CopyBuffer(atr_handle, 0, 0, rates_total, atr_buffer) <= 0)
{
Print("Error copying ATR buffer: ", GetLastError());
return(0);
}
//--- Set arrays as series
ArraySetAsSeries(time, true);
ArraySetAsSeries(open, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
//--- Detect swings
double top, btm;
DetectSwings(Length, top, btm);
double itop, ibtm;
DetectSwings(5, itop, ibtm);
//--- Process pivot highs
if(top > 0)
{
top_cross = true;
txt_top = (top > top_y) ? "HH" : "LH";
if(ShowSwings)
{
DrawStructure(time[Length], top, txt_top,
(Style == "Monochrome") ? C'178,181,190' : SwingBearCss,
false, true, "Small");
}
//--- Update variables
top_y = top;
top_x = Length;
trail_up = top;
trail_up_x = Length;
}
//--- Process pivot lows
if(btm > 0)
{
btm_cross = true;
txt_btm = (btm < btm_y) ? "LL" : "HL";
if(ShowSwings)
{
DrawStructure(time[Length], btm, txt_btm,
(Style == "Monochrome") ? C'178,181,190' : SwingBullCss,
false, false, "Small");
}
//--- Update variables
btm_y = btm;
btm_x = Length;
trail_dn = btm;
trail_dn_x = Length;
}
//--- Detect internal structure breakouts
if(itop > 0)
{
itop_cross = true;
itop_y = itop;
itop_x = 5;
}
if(ibtm > 0)
{
ibtm_cross = true;
ibtm_y = ibtm;
ibtm_x = 5;
}
//--- Update trailing values
if(high[0] > trail_up)
{
trail_up = high[0];
trail_up_x = 0;
}
if(low[0] < trail_dn)
{
trail_dn = low[0];
trail_dn_x = 0;
}
//--- Detect bullish internal structure
if(close[0] > itop_y && itop_cross && top_y != itop_y)
{
bool choch = (itrend < 0);
string txt = choch ? "CHoCH" : "BOS";
if(ShowInternals)
{
if(ShowIBull == "All" ||
(ShowIBull == "BOS" && !choch) ||
(ShowIBull == "CHoCH" && choch))
{
DrawStructure(time[itop_x], itop_y, txt,
(Style == "Monochrome") ? C'178,181,190' : SwingIBullCss,
true, true, "Tiny");
}
}
itop_cross = false;
itrend = 1;
//--- Internal Order Block
if(ShowIOB)
{
OBCoord(false, itop_x, iob_top, iob_btm, iob_left, iob_right, iob_type, iob_mit);
}
//--- Set alerts
if(choch)
bull_ichoch_alert = true;
else
bull_ibos_alert = true;
}
//--- Detect bullish structure
if(close[0] > top_y && top_cross)
{
bool choch = (trend < 0);
string txt = choch ? "CHoCH" : "BOS";
if(ShowStructure)
{
if(ShowBull == "All" ||
(ShowBull == "BOS" && !choch) ||
(ShowBull == "CHoCH" && choch))
{
DrawStructure(time[top_x], top_y, txt,
(Style == "Monochrome") ? C'178,181,190' : SwingBullCss,
false, true, "Small");
}
}
top_cross = false;
trend = 1;
//--- Order Block
if(ShowOB)
{
OBCoord(false, top_x, ob_top, ob_btm, ob_left, ob_right, ob_type, ob_mit);
}
//--- Set alerts
if(choch)
bull_choch_alert = true;
else
bull_bos_alert = true;
}
//--- Detect bearish internal structure
if(close[0] < ibtm_y && ibtm_cross && btm_y != ibtm_y)
{
bool choch = (itrend > 0);
string txt = choch ? "CHoCH" : "BOS";
if(ShowInternals)
{
if(ShowIBear == "All" ||
(ShowIBear == "BOS" && !choch) ||
(ShowIBear == "CHoCH" && choch))
{
DrawStructure(time[ibtm_x], ibtm_y, txt,
(Style == "Monochrome") ? C'178,181,190' : SwingIBearCss,
true, false, "Tiny");
}
}
ibtm_cross = false;
itrend = -1;
//--- Internal Order Block
if(ShowIOB)
{
OBCoord(true, ibtm_x, iob_top, iob_btm, iob_left, iob_right, iob_type, iob_mit);
}
//--- Set alerts
if(choch)
bear_ichoch_alert = true;
else
bear_ibos_alert = true;
}
//--- Detect bearish structure
if(close[0] < btm_y && btm_cross)
{
bool choch = (trend > 0);
string txt = choch ? "CHoCH" : "BOS";
if(ShowStructure)
{
if(ShowBear == "All" ||
(ShowBear == "BOS" && !choch) ||
(ShowBear == "CHoCH" && choch))
{
DrawStructure(time[btm_x], btm_y, txt,
(Style == "Monochrome") ? C'178,181,190' : SwingBearCss,
false, false, "Small");
}
}
btm_cross = false;
trend = -1;
//--- Order Block
if(ShowOB)
{
OBCoord(true, btm_x, ob_top, ob_btm, ob_left, ob_right, ob_type, ob_mit);
}
//--- Set alerts
if(choch)
bear_choch_alert = true;
else
bear_bos_alert = true;
}
//--- Check order block mitigation and break
for(int i = 0; i < ArraySize(iob_type); i++)
{
if(iob_left[i] == 0) continue;
// Mark internal orderbox as mitigated if price tapped inside the orderblock
if(OBHighlightMit)
{
if(iob_type[i] == 1 && low[1] > iob_top[i] && low[0] <= iob_top[i])
{
iob_mit[i]++;
iob_right[i] = time[0];
bull_iob_mit = true;
}
else if(iob_type[i] == -1 && high[1] < iob_btm[i] && high[0] >= iob_btm[i])
{
iob_mit[i]++;
iob_right[i] = time[0];
bear_iob_mit = true;
}
}
// Check if order block is broken
if(close[0] < iob_btm[i] && iob_type[i] == 1)
{
// Remove order block
for(int j = i; j < ArraySize(iob_type) - 1; j++)
{
iob_top[j] = iob_top[j+1];
iob_btm[j] = iob_btm[j+1];
iob_left[j] = iob_left[j+1];
iob_right[j] = iob_right[j+1];
iob_type[j] = iob_type[j+1];
iob_mit[j] = iob_mit[j+1];
}
ArrayResize(iob_top, ArraySize(iob_top) - 1);
ArrayResize(iob_btm, ArraySize(iob_btm) - 1);
ArrayResize(iob_left, ArraySize(iob_left) - 1);
ArrayResize(iob_right, ArraySize(iob_right) - 1);
ArrayResize(iob_type, ArraySize(iob_type) - 1);
ArrayResize(iob_mit, ArraySize(iob_mit) - 1);
bull_iob_break = true;
i--; // Adjust index after removal
}
else if(close[0] > iob_top[i] && iob_type[i] == -1)
{
// Remove order block
for(int j = i; j < ArraySize(iob_type) - 1; j++)
{
iob_top[j] = iob_top[j+1];
iob_btm[j] = iob_btm[j+1];
iob_left[j] = iob_left[j+1];
iob_right[j] = iob_right[j+1];
iob_type[j] = iob_type[j+1];
iob_mit[j] = iob_mit[j+1];
}
ArrayResize(iob_top, ArraySize(iob_top) - 1);
ArrayResize(iob_btm, ArraySize(iob_btm) - 1);
ArrayResize(iob_left, ArraySize(iob_left) - 1);
ArrayResize(iob_right, ArraySize(iob_right) - 1);
ArrayResize(iob_type, ArraySize(iob_type) - 1);
ArrayResize(iob_mit, ArraySize(iob_mit) - 1);
bear_iob_break = true;
i--; // Adjust index after removal
}
}
//--- Check swing order block mitigation and break
for(int i = 0; i < ArraySize(ob_type); i++)
{
if(ob_left[i] == 0) continue;
// Mark orderbox as mitigated if price tapped inside the orderblock
if(OBHighlightMit)
{
if(ob_type[i] == 1 && low[1] > ob_top[i] && low[0] <= ob_top[i])
{
ob_mit[i]++;
ob_right[i] = time[0];
bull_ob_mit = true;
}
else if(ob_type[i] == -1 && high[1] < ob_btm[i] && high[0] >= ob_btm[i])
{
ob_mit[i]++;
ob_right[i] = time[0];
bear_ob_mit = true;
}
}
// Check if order block is broken
if(close[0] < ob_btm[i] && ob_type[i] == 1)
{
// Remove order block
for(int j = i; j < ArraySize(ob_type) - 1; j++)
{
ob_top[j] = ob_top[j+1];
ob_btm[j] = ob_btm[j+1];
ob_left[j] = ob_left[j+1];
ob_right[j] = ob_right[j+1];
ob_type[j] = ob_type[j+1];
ob_mit[j] = ob_mit[j+1];
}
ArrayResize(ob_top, ArraySize(ob_top) - 1);
ArrayResize(ob_btm, ArraySize(ob_btm) - 1);
ArrayResize(ob_left, ArraySize(ob_left) - 1);
ArrayResize(ob_right, ArraySize(ob_right) - 1);
ArrayResize(ob_type, ArraySize(ob_type) - 1);
ArrayResize(ob_mit, ArraySize(ob_mit) - 1);
bull_ob_break = true;
i--; // Adjust index after removal
}
else if(close[0] > ob_top[i] && ob_type[i] == -1)
{
// Remove order block
for(int j = i; j < ArraySize(ob_type) - 1; j++)
{
ob_top[j] = ob_top[j+1];
ob_btm[j] = ob_btm[j+1];
ob_left[j] = ob_left[j+1];
ob_right[j] = ob_right[j+1];
ob_type[j] = ob_type[j+1];
ob_mit[j] = ob_mit[j+1];
}
ArrayResize(ob_top, ArraySize(ob_top) - 1);
ArrayResize(ob_btm, ArraySize(ob_btm) - 1);
ArrayResize(ob_left, ArraySize(ob_left) - 1);
ArrayResize(ob_right, ArraySize(ob_right) - 1);
ArrayResize(ob_type, ArraySize(ob_type) - 1);
ArrayResize(ob_mit, ArraySize(ob_mit) - 1);
bear_ob_break = true;
i--; // Adjust index after removal
}
}
//--- Draw order blocks
if(ShowIOB)
{
DrawOrderBlocks("IOB", iob_top, iob_btm, iob_left, iob_right, iob_type, iob_mit,
IOBShowLast, false, ArraySize(iob_type),
IBullObCss, IBullmObCss, IBearObCss, IBearmObCss);
}
if(ShowOB)
{
DrawOrderBlocks("OB", ob_top, ob_btm, ob_left, ob_right, ob_type, ob_mit,
OBShowLast, true, ArraySize(ob_type),
BullObCss, BullmObCss, BearObCss, BearmObCss);
}
//--- Detect and draw EQH/EQL
if(ShowEQ)
{
// Find pivot high and low
double eq_top = 0, eq_btm = 0;
int eq_top_idx = 0, eq_btm_idx = 0;
for(int i = EQLen; i < rates_total - EQLen; i++)
{
bool is_pivot_high = true;
bool is_pivot_low = true;
for(int j = 1; j <= EQLen; j++)
{
if(high[i] <= high[i+j] || high[i] <= high[i-j])
is_pivot_high = false;
if(low[i] >= low[i+j] || low[i] >= low[i-j])
is_pivot_low = false;
}
if(is_pivot_high)
{
eq_top = high[i];
eq_top_idx = i;
}
if(is_pivot_low)
{
eq_btm = low[i];
eq_btm_idx = i;
}
}
// Check for EQH
if(eq_top > 0 && eq_prev_top > 0)
{
double max = MathMax(eq_top, eq_prev_top);
double min = MathMin(eq_top, eq_prev_top);
if(max < min + atr_buffer[0] * EQThreshold)
{
string line_name = "EQH_" + IntegerToString(ChartID());
string label_name = "EQHLbl_" + IntegerToString(ChartID());
// Create or update line
if(ObjectFind(0, line_name) < 0)
{
ObjectCreate(0, line_name, OBJ_TREND, 0, time[eq_top_x], eq_prev_top, time[eq_top_idx], eq_top);
ObjectSetInteger(0, line_name, OBJPROP_COLOR, (Style == "Monochrome") ? C'178,181,190' : SwingBearCss);
ObjectSetInteger(0, line_name, OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, line_name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, line_name, OBJPROP_RAY_RIGHT, false);
}
else
{
ObjectSetInteger(0, line_name, OBJPROP_TIME1, time[eq_top_x]);
ObjectSetInteger(0, line_name, OBJPROP_PRICE1, eq_prev_top);
ObjectSetInteger(0, line_name, OBJPROP_TIME2, time[eq_top_idx]);
ObjectSetInteger(0, line_name, OBJPROP_PRICE2, eq_top);
}
// Create or update label
if(ObjectFind(0, label_name) < 0)
{
ObjectCreate(0, label_name, OBJ_TEXT, 0, time[(eq_top_x + eq_top_idx)/2], eq_top);
ObjectSetString(0, label_name, OBJPROP_TEXT, "EQH");
ObjectSetInteger(0, label_name, OBJPROP_COLOR, (Style == "Monochrome") ? C'178,181,190' : SwingBearCss);
ObjectSetInteger(0, label_name, OBJPROP_ANCHOR, ANCHOR_UPPER);
ObjectSetInteger(0, label_name, OBJPROP_FONTSIZE, 7);
}
else
{
ObjectSetInteger(0, label_name, OBJPROP_TIME, time[(eq_top_x + eq_top_idx)/2]);
ObjectSetInteger(0, label_name, OBJPROP_PRICE, eq_top);
}
eqh_alert = true;
}
}
// Check for EQL
if(eq_btm > 0 && eq_prev_btm > 0)
{
double max = MathMax(eq_btm, eq_prev_btm);
double min = MathMin(eq_btm, eq_prev_btm);
if(min > max - atr_buffer[0] * EQThreshold)
{
string line_name = "EQL_" + IntegerToString(ChartID());
string label_name = "EQLLbl_" + IntegerToString(ChartID());
// Create or update line
if(ObjectFind(0, line_name) < 0)
{
ObjectCreate(0, line_name, OBJ_TREND, 0, time[eq_btm_x], eq_prev_btm, time[eq_btm_idx], eq_btm);
ObjectSetInteger(0, line_name, OBJPROP_COLOR, (Style == "Monochrome") ? C'178,181,190' : SwingBullCss);
ObjectSetInteger(0, line_name, OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, line_name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, line_name, OBJPROP_RAY_RIGHT, false);
}
else
{
ObjectSetInteger(0, line_name, OBJPROP_TIME1, time[eq_btm_x]);
ObjectSetInteger(0, line_name, OBJPROP_PRICE1, eq_prev_btm);
ObjectSetInteger(0, line_name, OBJPROP_TIME2, time[eq_btm_idx]);
ObjectSetInteger(0, line_name, OBJPROP_PRICE2, eq_btm);
}
// Create or update label
if(ObjectFind(0, label_name) < 0)
{
ObjectCreate(0, label_name, OBJ_TEXT, 0, time[(eq_btm_x + eq_btm_idx)/2], eq_btm);
ObjectSetString(0, label_name, OBJPROP_TEXT, "EQL");
ObjectSetInteger(0, label_name, OBJPROP_COLOR, (Style == "Monochrome") ? C'178,181,190' : SwingBullCss);
ObjectSetInteger(0, label_name, OBJPROP_ANCHOR, ANCHOR_LOWER);
ObjectSetInteger(0, label_name, OBJPROP_FONTSIZE, 7);
}
else
{
ObjectSetInteger(0, label_name, OBJPROP_TIME, time[(eq_btm_x + eq_btm_idx)/2]);
ObjectSetInteger(0, label_name, OBJPROP_PRICE, eq_btm);
}
eql_alert = true;
}
}
// Update previous values
if(eq_top > 0)
{
eq_prev_top = eq_top;
eq_top_x = eq_top_idx;
}
if(eq_btm > 0)
{
eq_prev_btm = eq_btm;
eq_btm_x = eq_btm_idx;
}
}
//--- Detect and draw FVG
if(ShowFVG)
{
// Get data from specified timeframe
ENUM_TIMEFRAMES fvg_tf = PERIOD_CURRENT;
if(FVGTF == "M1") fvg_tf = PERIOD_M1;
else if(FVGTF == "M5") fvg_tf = PERIOD_M5;
else if(FVGTF == "M15") fvg_tf = PERIOD_M15;
else if(FVGTF == "M30") fvg_tf = PERIOD_M30;
else if(FVGTF == "H1") fvg_tf = PERIOD_H1;
else if(FVGTF == "H4") fvg_tf = PERIOD_H4;
else if(FVGTF == "D1") fvg_tf = PERIOD_D1;
else if(FVGTF == "W1") fvg_tf = PERIOD_W1;
else if(FVGTF == "MN1") fvg_tf = PERIOD_MN1;
// Check if timeframe changed
static datetime last_fvg_time = 0;
datetime fvg_time[];
double fvg_open[], fvg_close[], fvg_high[], fvg_low[];
ArraySetAsSeries(fvg_time, true);
ArraySetAsSeries(fvg_open, true);
ArraySetAsSeries(fvg_close, true);
ArraySetAsSeries(fvg_high, true);
ArraySetAsSeries(fvg_low, true);
CopyTime(_Symbol, fvg_tf, 0, 10, fvg_time);
CopyOpen(_Symbol, fvg_tf, 0, 10, fvg_open);
CopyClose(_Symbol, fvg_tf, 0, 10, fvg_close);
CopyHigh(_Symbol, fvg_tf, 0, 10, fvg_high);
CopyLow(_Symbol, fvg_tf, 0, 10, fvg_low);
// Check if we have a new bar on FVG timeframe
if(fvg_time[0] != last_fvg_time)
{
last_fvg_time = fvg_time[0];
// Calculate percentage change
double delta_per = (fvg_close[1] - fvg_open[1]) / fvg_open[1] * 100;
// Calculate threshold
double threshold;
if(FVGAuto)
{
static double cum_delta = 0;
static int bar_count = 0;
cum_delta += MathAbs(delta_per);
bar_count++;
threshold = cum_delta / bar_count * 2;
}
else
{
threshold = 0;
}
// Check for bullish FVG
if(fvg_low[1] > fvg_high[2] &&
fvg_close[1] > fvg_high[2] &&
delta_per > threshold)
{
// Add to arrays
int size = ArraySize(bullish_fvg_max);
ArrayResize(bullish_fvg_max, size + 1);
ArrayResize(bullish_fvg_min, size + 1);
ArrayResize(bullish_fvg_time, size + 1);
// Shift array elements
for(int i = size; i > 0; i--)
{
bullish_fvg_max[i] = bullish_fvg_max[i-1];
bullish_fvg_min[i] = bullish_fvg_min[i-1];
bullish_fvg_time[i] = bullish_fvg_time[i-1];
}
// Add new element at the beginning
bullish_fvg_max[0] = fvg_low[1];
bullish_fvg_min[0] = fvg_high[2];
bullish_fvg_time[0] = fvg_time[1];
bullish_fvg_cnd = true;
}
// Check for bearish FVG
if(fvg_high[1] < fvg_low[2] &&
fvg_close[1] < fvg_low[2] &&
-delta_per > threshold)
{
// Add to arrays
int size = ArraySize(bearish_fvg_max);
ArrayResize(bearish_fvg_max, size + 1);
ArrayResize(bearish_fvg_min, size + 1);
ArrayResize(bearish_fvg_time, size + 1);
// Shift array elements
for(int i = size; i > 0; i--)
{
bearish_fvg_max[i] = bearish_fvg_max[i-1];
bearish_fvg_min[i] = bearish_fvg_min[i-1];
bearish_fvg_time[i] = bearish_fvg_time[i-1];
}
// Add new element at the beginning
bearish_fvg_max[0] = fvg_high[1];
bearish_fvg_min[0] = fvg_low[2];
bearish_fvg_time[0] = fvg_time[1];
bearish_fvg_cnd = true;
}
}
// Check if FVG is mitigated
for(int i = 0; i < ArraySize(bullish_fvg_max); i++)
{
if(bullish_fvg_time[i] == 0) continue;
if(low[0] < bullish_fvg_min[i])
{
// Remove FVG
for(int j = i; j < ArraySize(bullish_fvg_max) - 1; j++)
{
bullish_fvg_max[j] = bullish_fvg_max[j+1];
bullish_fvg_min[j] = bullish_fvg_min[j+1];
bullish_fvg_time[j] = bullish_fvg_time[j+1];
}
ArrayResize(bullish_fvg_max, ArraySize(bullish_fvg_max) - 1);
ArrayResize(bullish_fvg_min, ArraySize(bullish_fvg_min) - 1);
ArrayResize(bullish_fvg_time, ArraySize(bullish_fvg_time) - 1);
i--; // Adjust index after removal
}
}
for(int i = 0; i < ArraySize(bearish_fvg_max); i++)
{
if(bearish_fvg_time[i] == 0) continue;
if(high[0] > bearish_fvg_max[i])
{
// Remove FVG
for(int j = i; j < ArraySize(bearish_fvg_max) - 1; j++)
{
bearish_fvg_max[j] = bearish_fvg_max[j+1];
bearish_fvg_min[j] = bearish_fvg_min[j+1];
bearish_fvg_time[j] = bearish_fvg_time[j+1];
}
ArrayResize(bearish_fvg_max, ArraySize(bearish_fvg_max) - 1);
ArrayResize(bearish_fvg_min, ArraySize(bearish_fvg_min) - 1);
ArrayResize(bearish_fvg_time, ArraySize(bearish_fvg_time) - 1);
i--; // Adjust index after removal
}
}
// Draw FVG boxes
DrawFVGBoxes();
}
//--- Draw previous high/low lines
if(ShowPDHL)
{
double pdh, pdl;
datetime pdh_time, pdl_time;
// Get daily high/low
double daily_high[], daily_low[];
datetime daily_time[];
ArraySetAsSeries(daily_high, true);
ArraySetAsSeries(daily_low, true);
ArraySetAsSeries(daily_time, true);
CopyHigh(_Symbol, PERIOD_D1, 0, 2, daily_high);
CopyLow(_Symbol, PERIOD_D1, 0, 2, daily_low);
CopyTime(_Symbol, PERIOD_D1, 0, 2, daily_time);
pdh = daily_high[1];
pdl = daily_low[1];
DrawPHL(pdh, pdl, "D", PDHLCss, PDHLStyle);
}
if(ShowPWHL)
{
double pwh, pwl;
datetime pwh_time, pwl_time;
// Get weekly high/low
double weekly_high[], weekly_low[];
datetime weekly_time[];
ArraySetAsSeries(weekly_high, true);
ArraySetAsSeries(weekly_low, true);
ArraySetAsSeries(weekly_time, true);
CopyHigh(_Symbol, PERIOD_W1, 0, 2, weekly_high);
CopyLow(_Symbol, PERIOD_W1, 0, 2, weekly_low);
CopyTime(_Symbol, PERIOD_W1, 0, 2, weekly_time);
pwh = weekly_high[1];
pwl = weekly_low[1];
DrawPHL(pwh, pwl, "W", PWHLCss, PWHLStyle);
}
if(ShowPMHL)
{
double pmh, pml;
datetime pmh_time, pml_time;
// Get monthly high/low
double monthly_high[], monthly_low[];
datetime monthly_time[];
ArraySetAsSeries(monthly_high, true);
ArraySetAsSeries(monthly_low, true);
ArraySetAsSeries(monthly_time, true);
CopyHigh(_Symbol, PERIOD_MN1, 0, 2, monthly_high);
CopyLow(_Symbol, PERIOD_MN1, 0, 2, monthly_low);
CopyTime(_Symbol, PERIOD_MN1, 0, 2, monthly_time);
pmh = monthly_high[1];
pml = monthly_low[1];
DrawPHL(pmh, pml, "M", PMHLCss, PMHLStyle);
}
//--- Draw premium/discount zones
if(ShowSD)
{
DrawPremiumDiscountZones();
}
//--- Color candles based on trend
if(ShowTrend)
{
color trend_color;
if(Style == "Colored")
trend_color = (itrend == 1) ? SwingBullCss : SwingBearCss;
else // Monochrome
trend_color = (itrend == 1) ? C'178,181,190' : C'93,96,107';
// This would require using chart objects to color candles
// In MQL5, we can't directly color candles without using a custom candlestick plot
// This is a limitation compared to Pine Script
}
//--- Return value
return(rates_total);
}
//+------------------------------------------------------------------+`
can you please drop it in a coded document
Good`