本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。
// ▓▓▓▓ ▓▓▓▓ ▓▓██ ▓▓██
// ▓▓▒▒▓▓▒▒▒▒▓▓▒▒▒▒▓▓▒▒▓▓
// ▓▓▒▒▒▒▒▒░░░░░░▒▒▒▒▒▒▓▓
// ▓▓▒▒▒▒░░░░░░▒▒▒▒▓▓
// ▓▓▒▒░░░░░░▒▒▓▓
// ▓▓▒▒▒▒▒▒██
// ▓▓▓▓▓▓▓▓▓▓
// ▓▓▓▓▒▒▒▒▒▒▒▒▒▒▓▓▓▓ ████████
// ▓▓▒▒░░░░▒▒▒▒▒▒▒▒▒▒▒▒▓▓ ██████████
// ▓▓▒▒░░▒▒▒▒▒▒░░▒▒▒▒▒▒▒▒▒▒▓▓ ██ ██
// ▓▓▒▒░░▒▒▒▒░░░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ██▄▄▄▄▄▄▄▄▄█
// ▓▓▒▒░░▒▒▒▒░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ██▀███ ███▀█
// ▓▓▒▒░░▒▒▒▒░░░░░░░░██░░░░░░░░▒▒▒▒▒▒▒▒▓▓ █ ▀█ █▀
// ▓▓░░▒▒▒▒▒▒░░░░░░██████░░░░░░▒▒▒▒▒▒▒▒▓▓ ██ █
// ▓▓▒▒░░▒▒▒▒░░░░░░██░░░░░░██░░░░░░▒▒▒▒▒▒▒▒▓▓ █ ██ ██
// ▓▓░░▒▒▒▒▒▒░░░░░░██░░░░░░██░░░░░░▒▒▒▒▒▒▒▒▓▓ /█▄ ████─██──████
// ▓▓▒▒░░▒▒▒▒░░░░░░░░░░██░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ▄███████████████──██──██████
// ▓▓░░▒▒▒▒▒▒░░░░░░░░░░░░██░░░░░░░░░░░░▒▒▒▒▒▒▒▒▓▓ █████████████──██──█████████
// ▓▓░░▒▒▒▒▒▒░░░░░░░░░░░░░░██░░░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ████──██─█████ ███
// ▓▓▒▒▒▒▒▒▒▒░░░░░░░░██░░░░░░██░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ███──██─█████ ███
// ▓▓▒▒▒▒▒▒▒▒░░░░░░░░██░░░░░░██░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ███─────█████████
// ▓▓▒▒▒▒▒▒▒▒░░░░░░░░██████░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ██─────████████▀
// ▓▓▒▒▒▒▒▒▒▒░░░░░░░░░░██░░░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ██████████
// ▓▓▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ██████████
// ▓▓▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▓▓ ████████
// ▓▓▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▓▓ ██████████▄▄
// ▓▓▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▓▓ █████████▀
// ▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓ ███ ███
// ▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓ ███ ███
// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ██████ ▀
// ▓▓░░░░░░▓▓░░░░░░░░▓▓░░ ▀▄▄▄▄▀
//
// ██╗ ██╗███████╗██╗ ██████╗ ████████╗██████╗ █████╗ ██████╗ ███████╗███████╗
// ██║ ██║██╔════╝██║ ██╔═══██╗╚══██╔══╝██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝
// ██║ █╗ ██║█████╗ ██║ ██║ ██║ ██║ ██████╔╝███████║██║ ██║█████╗ ███████╗
// ██║███╗██║██╔══╝ ██║ ██║ ██║ ██║ ██╔══██╗██╔══██║██║ ██║██╔══╝ ╚════██║
// ╚███╔███╔╝███████╗███████╗╚██████╔╝ ██║ ██║ ██║██║ ██║██████╔╝███████╗███████║
// ╚══╝╚══╝ ╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚══════╝
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © WeloTrades
//@version=5
indicator(title = 'Smart Money Concepts by WeloTrades', shorttitle = 'SMC {WeloTrades}', overlay = true, max_boxes_count = 500, max_labels_count = 500, max_lines_count = 500, max_bars_back = 500, max_polylines_count = 100)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// INPUTS ///////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////
//OB INPUT SETTINGS//
////////////////////
// INPUT OB & BB SETTINGS
timeframe1Enabled = input.bool(true, "TF #1🕑:", inline = '1', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
timeframe1 = input.timeframe("", "", inline = '1', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
timeframe2Enabled = input.bool(false, "TF #2🕑:", inline = '2_', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
timeframe2 = input.timeframe("D", "", inline = '2_', group = "++++++++++++++ OB SETTINGS ++++++++++++++", tooltip="⏩Toggle to enable or disable the Timeframes and select which Timeframes. ❓:(DEFAULT) ➖ (HIGHER TF CHART & LOWER TF SETTING) ➖ (LOWER TF CHART & HIGHER TF SETTING)")
showOBs = input.bool(true, "OB (Length)📏:", inline = '2', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
swingLengthOption = input.string("LONG", "", options = ["SHORT", "MID", "LONG", "CUSTOM"], inline = '2', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
swingLength = input.int(5, '🔧custom:', minval = 3, inline = '2', group = "++++++++++++++ OB SETTINGS ++++++++++++++", display = display.none, tooltip="⏩:Toggle to enable or disable the display of Order Blocks. ⏩:dropdown to select the swing length option (SHORT, MID, LONG, CUSTOM). ⏩:An integer input for specifying a custom swing length, which is hidden by default and likely shown only when swingLengthOption is set to (CUSTOM) ❓:Lengths are set as default (SHORT=10) ➖ (MID=28) ➖ (LONG=50) ")
showBBs = input.bool(true, "BB (Method)📛:", inline = '4', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
obEndMethod = input.string("Close", "", options = ["Wick", "Close"], inline = '4', group = "++++++++++++++ OB SETTINGS ++++++++++++++", display = display.none, tooltip="⏩:Toggle to enable or disable the display of Breaker Blocks. ⏩:Dropdown to select the method for determining the end of a Breaker Block (Wick or Close) ❓:(Wicks: OB is mitigated when the price wicks through the OB Level.) ➖ (Close: OB is mitigated when the closing price is within the OB Level.)")
zoneCountBullish = input.string("2", '🔍Max Bullish:', options = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], inline = '5', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
zoneCountBearish = input.string("2", '🔍Max Bearish:', options = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], inline = '6', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
bullOrderBlockColor = input.color(color.rgb(0, 126, 0, 50), '', inline = '5', group = '++++++++++++++ OB SETTINGS ++++++++++++++', display = display.none)
bearOrderBlockColor = input.color(color.rgb(128, 0, 11, 50), '', inline = '6', group = '++++++++++++++ OB SETTINGS ++++++++++++++', display = display.none)
bullOrderBlockinColor = input.color(color.rgb(0, 126, 0, 50), '', inline = '5', group = '++++++++++++++ OB SETTINGS ++++++++++++++', display = display.none, tooltip="⏩:Set the maximum number of Bullish OB to display & select color and internal color. ❓:Don't see a OB or BB where supposed to?(Try increasing the max count)➖(It counts OB & BB togheter even OB or BB display is disabled)")
bearOrderBlockinColor = input.color(color.rgb(128, 0, 11, 50), '', inline = '6', group = '++++++++++++++ OB SETTINGS ++++++++++++++', display = display.none, tooltip="⏩:Set the maximum number of Bearish OB to display & select color and internal color. ❓:Don't see a OB or BB where supposed to?(Try increasing the max count)➖(It counts OB & BB togheter even OB or BB display is disabled)")
obBoxLengthOption = input.string("CUSTOM", "↔ OB & BB Range:", options = ["RANGE", "CUSTOM"], inline = '7', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
adjustableLength = input.int(22000, "🔧Custom:", minval = 1000, maxval = 500000, step = 100, inline = '7', group = "++++++++++++++ OB SETTINGS ++++++++++++++", tooltip="⏩:Select how far the OB or BB should go. ❓:(Range=Current price) ➖ (CUSTOM=Adjustable Range)")
textSizeOption = input.string("M", "💬Text Options:", options = ["XS", "S", "M", "L", "XL"], inline = '8', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
textColor = input.color(color.rgb(255, 255, 255), "", inline = '8', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
showTimeframeOB = input.bool(true, "Text", inline = '8', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
showVolume = input.bool(true, "Volume", inline = '8', group = "++++++++++++++ OB SETTINGS ++++++++++++++")
showPercentage = input.bool(true, "%", inline = '8', group = "++++++++++++++ OB SETTINGS ++++++++++++++", tooltip= "⏩:Set Text Size & Color for OB & BB ⏩:Toggle to enable or disable the display of (TEXT) ➖ (VOLUME) ➖ (%)")
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////
// LIQUIDITY LEVELS INPUT SETTINGS //
////////////////////////////////////
// INPUT LIQUIDITY SETTINGS
currentTF = input.bool(true, title = "TF #1🕑:", inline = "1", group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
htfTF = input.timeframe("", title = "", inline = "1", group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
liquidityLengthOption = input.string("LONG", title = "📏Liquidity Length:", inline = "_1_", options = ["SHORT", "MID", "LONG" , "CUSTOM"], group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
liquidityswingLength = input.int(5, '🔧custom:', minval = 3, inline = '_1_', group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++', display = display.none, tooltip="⏩:Select the length for liquidity levels. ❓:(SHORT: Short-term:10) ➖ (MID: Medium-term:28) ➖ (LONG: Long-term:50) ➖ (CUSTOM: Custom length) ⏩:(For CUSTOM) select the custom length for Pivot calculation. ❓:(select length you prefer)")
_candleType = input.string("Close", title = "📛Mitigation (Method):", options = ["Close", "Wick"], inline = '4', group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
mitiOptions = input.string("Remove", title = "-", inline = "4", options = ["Remove", "Show"], group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++', tooltip="⏩:Select to display or hide mitigated levels. ❓:(Remove: Hide mitigated levels) ➖ (Show: Display mitigated levels). ⏩:Select option mitigation method. ❓:Wicks: Level is mitigated when the price wicks through the level.) ➖ (Close: Level is mitigated when the closing price is within the level.)")
displayLimitBuy = input.int(3, title = "🔍Max Buy Side Liquidity:", minval = 0, maxval = 50 , inline = "2", group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
highLineColorHTF = input.color(color.rgb(0, 19, 129, 50), "", inline = "2", group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++', tooltip="⏩:Set the maximum number of Buy Side Liquidity Levels to display. ❓:(Default: 5) ➖ (Min: 1) ➖ (Max: 50). ⏩:Select color for Buy Side Liquidity Levels. ❗:Don't see a Liquidity level where supposed to?(Try increasing the max count)➖(It counts Liquidity levels & recent Mitigated Liquidity Levels)")
highBoxBorderColorHTF = color.new(highLineColorHTF, 90)
displayLimitSell = input.int(3, title = "🔍Max Sell Side Liquidity:", minval = 0, maxval = 50 , inline = "3", group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
lowLineColorHTF = input.color(color.rgb(255, 0, 0, 50), "", inline = "3", group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++', tooltip="⏩:Set the maximum number of Sell Side Liquidity Levels to display. ❓:(Default: 5) ➖ (Min: 1) ➖ (Max: 50). ⏩:Select color for Sell Side Liquidity Levels. ❗:Don't see a Liquidity level where supposed to?(Try increasing the max count)➖(It counts Liquidity levels & recent Mitigated Liquidity Levels)")
lowBoxBorderColorHTF = color.new(lowLineColorHTF, 90)
box_width = input.float(-5, title = "✂ Box Style (↕):", minval = -50, maxval = 50, step = 0.5, inline = "5", group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
length_extend_liq = input.int(defval = 20, title = "(↔):", minval = 0, maxval = 500, inline = "5", group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
extentionMax = input.bool(false, title = "Extend ⏭", inline = "5", group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++', tooltip="⏩:Set the box width for liquidity levels. ❓:(Default: -5) ➖ (Range: -50 to 50). ⏩:Set the box length of Liquidity Levels. ❓:(Default: 20) ➖ (Min: 0) ➖ (Max: 500). ⏩:Toggle to extend Liquidity Levels. ❓:(Extend liquidity levels beyond the current range)")
_highLineStyleHTF = "Solid"
highLineStyleHTF = _highLineStyleHTF == "Solid" ? line.style_solid : _highLineStyleHTF == "Dashed" ? line.style_dashed : line.style_dotted
lineWidthHTF = 2
textSize = input.string("S", "💬 Text Options:", options=["XS", "S", "M", "L", "XL"], inline = '6', group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
liquidity_text_color = input.color(#ffffff, '', inline = '6', group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
show_text = input.bool(true, "Text", inline = '6', group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
show_volume = input.bool(true, "Volume", inline = '6', group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++')
show_percent = input.bool(true, "%", inline = '6', group = '++++++++++++++ LIQUIDITY LEVELS ++++++++++++++', tooltip="⏩:Select text size for liquidity levels. ❓:(XS: Extra Small) ➖ (S: Small) ➖ (M: Medium) ➖ (L: Large) ➖ (XL: Extra Large) ⏩:Select text color for liquidity levels. ⏩:Toggle to display text, volume, percentage for liquidity levels.")
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////
// FAIR VALUE GAPS INPUT SETTINGS //
///////////////////////////////////
// INPUT SETTINGS FAIR VALUE GAPS
show_fvg = input(true, 'TF #1🕑:' , inline = 'tf' , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
i_tf = input.timeframe("", "" , inline = 'tf' , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++', tooltip="⏩Toggle to enable or disable the Timeframes and select which Timeframes. ❓:(DEFAULT) ➖ (HIGHER TF CHART & LOWER TF SETTING) ➖ (LOWER TF CHART & HIGHER TF SETTING)")
mittigation_filt_fvg = input.string('Wicks', '📛FVG Break (Method):',options = ['Touch','Wicks','Close','Average'] , inline = "m1" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
show_mitigated_fvg = input.bool(false, 'show', inline = 'm1' , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
fvg_color_fill = input.bool(true,"Fill" , inline = "m1" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
fvg_shade_fill = input.bool(false,"Shade" , inline = "m1" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++', tooltip="⏩:Select the method Break FVG & Toggle visibility of FVG Breaks (fill FVG &/or shade FVG). ❓:(Touch: FVG is mitigated when the price touches the gap.) ➖ (Wicks: FVG is mitigated when the price wicks through the gap.) ➖ (Close: FVG is mitigated when the closing price is within the gap.) ➖ (Average: FVG is mitigated when the average price (average of high and low) is within the gap.)")
max_bullish_fvg = input.int(defval = 5, title = "🔍Max Bullish FVG:", minval = 0, maxval = 50 , inline = "O1" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
max_bearish_fvg = input.int(defval = 5, title = "🔍Max Bearish FVG:", minval = 0, maxval = 50 , inline = "O1_" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
i_mtfbearishfvgcolor = input.color(color.rgb(255, 166, 0, 75) , "" , inline = "O1_" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++', tooltip="⏩:Set the maximum number of Bearish FVG to display & select color. ❓:Don't see a FVG where supposed to?(Try increasing the max count)➖(It counts FVG & FVG Breaks)")
i_mtfbullishfvgcolor = input.color(color.rgb(255, 255, 255, 75), "" , inline = "O1" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++', tooltip="⏩:Set the maximum number of Bullish FVG to display & select color. ❓:Don't see a FVG where supposed to?(Try increasing the max count)➖(It counts FVG & FVG Breaks)")
length_extend = input.int(defval = 20,title = "↔ FVG Range:", minval = 0, maxval = 100 , inline = "O2" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
fvg_extend = input.bool(false,"Extend⏭" , inline = "O2" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
fvg_extend_B = input.bool(true,"Range⏯ " , inline = "O2" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++', tooltip="⏩:Select how far the FVG should go. ❓:(Adjustable length only works when both RANGE & EXTEND display OFF) ➖ (Range=current price) ➖ (Extend=Full Range)")
max_width_fvg = input.float(2.5, '↕ Max Width:', minval = 0, maxval = 5.0, step = 0.1 , inline = 'width' , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
remove_small = input.bool(false,"Filter FVG ♻" , inline = "width" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++', tooltip="⏩:Set the maximum width of FVG as a percentage of the price range. ❓:FVGs wider than this value will be ignored. ⏩:Toggle to filter out small FVGs. ❓:When set to true, FVGs smaller than the max_width_fvg value will be ignored.")
mid_style = input.string('Dotted', '➖Mid Line Style:', ['Solid', 'Dashed', 'Dotted'] , inline="mid" , group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++')
i_midPointColor = input.color(color.rgb(255, 255, 255), "" , inline="mid", group = '++++++++++++++ FAIR VALUE GAPS ++++++++++++++', tooltip="⏩:Select mid line style for FVG & Color.")
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////
// TRENDLINES INPUT SETTINGS //
//////////////////////////////
// INPUT TRENDLINES SETTINGS
showTrendlines = input.bool(true, "Trendlines & Trendlines Difference(%) ↕:", group="++++++++++ TRENDLINES ++++++++++", inline="TLlength")
percent_from_first_line = input.float(1.5, title="", minval=-10.0, maxval=10.0, step=0.1, group="++++++++++ TRENDLINES ++++++++++", inline="TLlength", tooltip="⏩: Enable or disable trendlines and set the percentage difference from the first trendline. ❓: Set the percentage to determine the second trendline distance.")
lengthOption = input.string("SHORT", "📏Trendline Length:", options=["SHORT", "MID", "LONG", "CUSTOM"], group="++++++++++ TRENDLINES ++++++++++", inline="TLlength2")
lengthCustom = input.int(5, "🔧custom:", minval=5, maxval=1000, group="++++++++++ TRENDLINES ++++++++++", inline="TLlength2", tooltip="⏩: Select the trendline length option and specify custom length if CUSTOM is selected. ❓: (SHORT=50, MID=100, LONG=200) ➖ (CUSTOM=Specify length)")
maxBearishCountOption = input.string("2", "🔍Max Trendlines Bearish:", options=["2","4","6","8","10","12","14","16","18","20"], group="++++++++++ TRENDLINES ++++++++++", inline="count")
dnCss = input.color(color.rgb(10, 130, 0), '', group="++++++++++ TRENDLINES ++++++++++", inline="count", tooltip="⏩: Set the maximum number of bearish trendlines and their color. ❓: Adjust to control how many bearish trendlines are displayed.")
maxBullishCountOption = input.string("2", "🔍Max Trendlines Bullish:", options=["2","4","6","8","10","12","14","16","18","20"], group="++++++++++ TRENDLINES ++++++++++", inline="count2")
upCss = input.color(color.rgb(130, 0, 10), '', group="++++++++++ TRENDLINES ++++++++++", inline="count2", tooltip="⏩: Set the maximum number of bullish trendlines and their color. ❓: Adjust to control how many bullish trendlines are displayed.")
showA = input.bool(true, '📐Degrees ° (💬 Size):', group="++++++++++ TRENDLINES ++++++++++", inline="Degrees")
textSizeOptionTL = input.string("M", "", options=["XS", "S", "M", "L", "XL"], group="++++++++++ TRENDLINES ++++++++++", inline="Degrees")
angleTextColor = input.color(color.rgb(255, 255, 255), "", group="++++++++++ TRENDLINES ++++++++++", inline="Degrees", tooltip="⏩: Enable or disable degrees text and set its size and color. ❓: Select the size from XS, S, M, L, XL.")
useAngleFilter = input.bool(false, '♻ Filter Degrees °:', group="++++++++++ TRENDLINES ++++++++++", inline="angleFilter")
anglA = input.float(10, '', minval=0.1, group="++++++++++ TRENDLINES ++++++++++", inline="angleFilter")
anglB = input.float(90, '-', minval=0.1, group="++++++++++ TRENDLINES ++++++++++", inline="angleFilter", tooltip="⏩: Enable or disable angle filtering and set the angle range. ❓: Angles outside this range will be filtered out.")
LineStyle1 = input.string("SOLID", "➖Style #1 & #2:", options=["SOLID", "DASHED", "DOTTED"], group="++++++++++ TRENDLINES ++++++++++", inline="linestyle")
LineStyle2 = input.string("DOTTED", "-", options=["SOLID", "DASHED", "DOTTED"], group="++++++++++ TRENDLINES ++++++++++", inline="linestyle")
lineThickness = input.int(2, ":", minval=1, maxval=5, group="++++++++++ TRENDLINES ++++++++++", inline="linestyle", tooltip="⏩: Select the line style and thickness for the trendlines. ❓: Choose from SOLID, DASHED, DOTTED for both primary and secondary lines.")
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////
// BOS & CHOCH MARKET STRUCTURE INPUT SETTINGS //
////////////////////////////////////////////////
// INPUT SETTINGS MARKET STRUCTURE
length_option = input.string("ALL", title="📏Market Structure:", options=["INTERNAL", "EXTERNAL", "ALL", "CUSTOM", "NONE"], group="++++++++++++++ MARKET STRUCTURE ++++++++++++++", tooltip="⏩:Select the market structure length option. ❓:(INTERNAL: Only internal structure) ➖ (EXTERNAL: Only external structure) ➖ (ALL: Both internal and external structures) ➖ (CUSTOM: Custom lengths) ➖ (NONE: No structure)")
internalLength = length_option == "INTERNAL" or length_option == "ALL" ? 10 : length_option == "CUSTOM" ? input.int(10, title="🔧Custom Internal:", inline="2_", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++") : na
label_sizes_Internal_ = input.string("S", options=["XS", "S", "M", "L", "XL"], title="💬", inline="2_", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
internalBullColor = input.color(color.rgb(0, 135, 0), title="", inline="2_", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
internalBearColor = input.color(color.rgb(135, 0, 0), title="", inline="2_", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++", tooltip="⏩:Set custom length, label size, and colors for internal market structure. ❓:(XS: Extra Small) ➖ (S: Small) ➖ (M: Medium) ➖ (L: Large) ➖ (XL: Extra Large)")
label_size_Internal_s = label_sizes_Internal_ == "XS" ? size.tiny : label_sizes_Internal_ == "S" ? size.small : label_sizes_Internal_ == "M" ? size.normal : label_sizes_Internal_ == "L" ? size.large : size.huge
label_size_Internal = label_size_Internal_s
externalLength = length_option == "EXTERNAL" or length_option == "ALL" ? 50 : length_option == "CUSTOM" ? input.int(50, title="🔧Custom External:", inline="3_", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++") : na
label_sizes_External_ = input.string("M", options=["XS", "S", "M", "L", "XL"], title="💬", inline="3_", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
externalBullColor = input.color(color.rgb(0, 255, 0), title="", inline="3_", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
externalBearColor = input.color(color.rgb(255, 0, 0), title="", inline="3_", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++", tooltip="⏩:Set custom length, label size, and colors for external market structure. ❓:(XS: Extra Small) ➖ (S: Small) ➖ (M: Medium) ➖ (L: Large) ➖ (XL: Extra Large)")
label_size_External_s = label_sizes_External_ == "XS" ? size.tiny : label_sizes_External_ == "S" ? size.small : label_sizes_External_ == "M" ? size.normal : label_sizes_External_ == "L" ? size.large : size.huge
label_size_External = label_size_External_s
show_equal_highlow = input(true, 'EQL & EQH📐:', inline='4', group='++++++++++++++ MARKET STRUCTURE ++++++++++++++')
eq_threshold = input.float(0.3, '', minval=0, maxval=10, step=0.1, inline='4', group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
label_size_Equal_ = input.string("S", options=["XS", "S", "M", "L", "XL"], title="💬", inline="4", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
eq_bull_color = input.color(color.rgb(0, 255, 0), '', inline="4", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
eq_bear_color = input.color(color.rgb(255, 0, 0), '', inline="4", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++", tooltip="⏩:Toggle visibility, set threshold, label size, and colors for equal highs and lows. ❓:(XS: Extra Small) ➖ (S: Small) ➖ (M: Medium) ➖ (L: Large) ➖ (XL: Extra Large)")
label_size_Equal_s = label_size_Equal_ == "XS" ? size.tiny : label_size_Equal_ == "S" ? size.small : label_size_Equal_ == "M" ? size.normal : label_size_Equal_ == "L" ? size.large : size.huge
label_size_Equal = label_size_Equal_s
showSwing = input.bool(true, title="Swing Points📏:", inline="1", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
swing_option = input.string("SHORT", title="", options=["SHORT", "MID", "LONG", "CUSTOM"], inline="1", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
label_sizes_swing_ = input.string("M", options=["XS", "S", "M", "L", "XL"], title="💬", inline="1", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++")
swingColor = input.color(color.rgb(255, 255, 255), '', inline="1", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++", tooltip="⏩:Toggle visibility, set length, label size, and color for swing points. ❓:(SHORT:10) ➖ (MID:28) ➖ (LONG:50) ➖ (CUSTOM:Adjustable length custom) ❓:(XS: Extra Small) ➖ (S: Small) ➖ (M: Medium) ➖ (L: Large) ➖ (XL: Extra Large)")
swingSize_swing = swing_option == "SHORT" ? 10 : swing_option == "MID" ? 28 : swing_option == "LONG" ? 50 : input.int(10, title="🔧Custom Swings:", inline="1_", group="++++++++++++++ MARKET STRUCTURE ++++++++++++++", tooltip="⏩:Set custom length for swing points. ❓:(Minimum value: 1)")
swingSize = 5
length_eqh = 5
color CLEAR = color.rgb(0, 0, 0, 100)
label_size_swing_s = label_sizes_swing_ == "XS" ? size.tiny : label_sizes_swing_ == "S" ? size.small : label_sizes_swing_ == "M" ? size.normal : label_sizes_swing_ == "L" ? size.large : size.huge
label_size_swing = label_size_swing_s
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// CALCULATIONS / FUNCTIONS /////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------- GLOBAL VARIABLES -----------------------------------------------------------//
//------------------------------------------------------------------------------------------------------------------------------------------------------//
// GLOBAL VARIABLES FUNCTIONS //
showInvalidated = true
OBsEnabled = true
const bool DEBUG = false
combineOBs = DEBUG ? input.bool(true,display = display.none) : true
maxATRMult = DEBUG ? input.float(3.5) : 3.5
bullishOrderBlocks = str.tonumber(zoneCountBullish)
bearishOrderBlocks = str.tonumber(zoneCountBearish)
extendZonesBy = DEBUG ? input.int(15) : 15
mirrorVolumeBars = DEBUG ? input.bool(true) : true
volumeBarsPlace = DEBUG ? input.string("Left") : "Left"
volumeBarsLeftSide = (volumeBarsPlace == "Left")
extendZonesByTime = extendZonesBy * timeframe.in_seconds(timeframe.period) * 1000
atr = ta.atr(10)
style = 'Colored'
color transparent = #ffffff00
length = 50
is_newbar(res) =>
t = time(res)
not na(t) and (na(t[1]) or t > t[1])
Show_MS(x, y, txt, css, dashed, down, lbl_size)=>
label.new(int(math.avg(x, bar_index)), y, txt, color = transparent, textcolor = css, style = down ? label.style_label_down : label.style_label_up, size = lbl_size)
line.new(x, y, bar_index, y, color = css, style = dashed ? line.style_dashed : line.style_solid)
f_barssince(_cond, _count) =>
_barssince = bar_index - ta.valuewhen(_cond, bar_index, _count)
_barssince
var t_MS = 0, var int_t_MS = 0
var internal_y_up = 0., var internal_x_up = 0, var internal_y_dn = 0., var internal_x_dn = 0
var y_up = 0., var x_up = 0 , var y_dn = 0., var x_dn = 0
var crossed_up = true, var crossed_down = true
var internal_up_broke = true, var internal_dn_broke = true
var up_trailing = high, var down_trailing = low
var up_trailing_x = 0, var down_trailing_x = 0
var high_text = '', var low_text = ''
bullish_OB_Break = false
bearish_OB_Break = false
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------- OB CALCULATIONS & FUNCTIONS ------------------------------------------------//
//------------------------------------------------------------------------------------------------------------------------------------------------------//
type orderBlockInfo
float top
float bottom
float obVolume
string obType
int startTime
float bbVolume
float obLowVolume
float obHighVolume
bool breaker
int breakTime
string timeframeStr
bool disabled = false
string combinedTimeframesStr = na
bool combined = false
type orderBlock
orderBlockInfo info
bool isRendered = false
box orderBox = na
box breakerBox = na
line orderBoxLineTop = na
line orderBoxLineBottom = na
line breakerBoxLineTop = na
line breakerBoxLineBottom = na
box orderBoxText = na
box orderBoxPositive = na
box orderBoxNegative = na
line orderSeperator = na
line orderTextSeperator = na
createOrderBlock (orderBlockInfo orderBlockInfoF) =>
orderBlock newOrderBlock = orderBlock.new(orderBlockInfoF)
newOrderBlock
safeDeleteOrderBlock (orderBlock orderBlockF) =>
orderBlockF.isRendered := false
box.delete(orderBlockF.orderBox)
box.delete(orderBlockF.breakerBox)
box.delete(orderBlockF.orderBoxText)
box.delete(orderBlockF.orderBoxPositive)
box.delete(orderBlockF.orderBoxNegative)
line.delete(orderBlockF.orderBoxLineTop)
line.delete(orderBlockF.orderBoxLineBottom)
line.delete(orderBlockF.breakerBoxLineTop)
line.delete(orderBlockF.breakerBoxLineBottom)
line.delete(orderBlockF.orderSeperator)
line.delete(orderBlockF.orderTextSeperator)
type timeframeInfo
int index = na
string timeframeStr = na
bool isEnabled = false
orderBlockInfo[] bullishOrderBlocksList = na
orderBlockInfo[] bearishOrderBlocksList = na
newTimeframeInfo (index, timeframeStr, isEnabled) =>
newTFInfo = timeframeInfo.new()
newTFInfo.index := index
newTFInfo.isEnabled := isEnabled
newTFInfo.timeframeStr := timeframeStr
newTFInfo
type obSwing
int x = na
float y = na
float swingVolume = na
bool crossed = false
const float overlapThresholdPercentage = 0
const int maxDistanceToLastBar = 1750
const int maxOrderBlocks = 30
var timeframeInfo[] timeframeInfos = array.from(newTimeframeInfo(1, timeframe1, timeframe1Enabled), newTimeframeInfo(2, timeframe2, timeframe2Enabled))
var bullishOrderBlocksList = array.new<orderBlockInfo>(0)
var bearishOrderBlocksList = array.new<orderBlockInfo>(0)
var allOrderBlocksList = array.new<orderBlock>(0)
moveLine(_line, _x, _y, _x2) =>
line.set_xy1(_line, _x, _y)
line.set_xy2(_line, _x2, _y)
moveBox (_box, _topLeftX, _topLeftY, _bottomRightX, _bottomRightY) =>
box.set_lefttop(_box, _topLeftX, _topLeftY)
box.set_rightbottom(_box, _bottomRightX, _bottomRightY)
isTimeframeLower (timeframe1F, timeframe2F) =>
timeframe.in_seconds(timeframe1F) < timeframe.in_seconds(timeframe2F)
getMinTimeframe (timeframe1F, timeframe2F) =>
if isTimeframeLower(timeframe1F, timeframe2F)
timeframe1F
else
timeframe2F
getMaxTimeframe (timeframe1F, timeframe2F) =>
if isTimeframeLower(timeframe1F, timeframe2F)
timeframe2F
else
timeframe1F
formatTimeframeString (formatTimeframe) =>
timeframeF = formatTimeframe == "" ? timeframe.period : formatTimeframe
if str.contains(timeframeF, "D") or str.contains(timeframeF, "W") or str.contains(timeframeF, "S") or str.contains(timeframeF, "M")
timeframeF
else
seconds = timeframe.in_seconds(timeframeF)
if seconds >= 3600
hourCount = int(seconds / 3600)
str.tostring(hourCount) + " Hour" + (hourCount > 1 ? "s" : "")
else
timeframeF + " Min"
betterCross(s1, s2) =>
string ret = na
if s1 >= s2 and s1[1] < s2
ret := "Bull"
if s1 < s2 and s1[1] >= s2
ret := "Bear"
ret
colorWithTransparency (colorF, transparencyX) =>
color.new(colorF, color.t(colorF) * transparencyX)
createOBBox (boxColor, textSize, transparencyX = 1.0, xlocType = xloc.bar_time) =>
box.new(na, na, na, na, text_size = textSize, xloc = xlocType, extend = extend.none, bgcolor = colorWithTransparency(boxColor, transparencyX), text_color = textColor, text_halign = text.align_center, border_color = #00000000)
getTextSize(textSizeOption) =>
if textSizeOption == "XS"
size.tiny
else if textSizeOption == "S"
size.small
else if textSizeOption == "M"
size.normal
else if textSizeOption == "L"
size.large
else if textSizeOption == "XL"
size.huge
renderOrderBlock (orderBlock ob) =>
orderBlockInfo info = ob.info
ob.isRendered := true
orderColor = ob.info.obType == "Bull" ? bullOrderBlockColor : bearOrderBlockColor
// Check if OBs or BBs should be displayed
showOB = not info.breaker and showOBs
showBB = info.breaker and showBBs
if OBsEnabled and (showOB or showBB) and not (not showInvalidated and info.breaker)
textSize = getTextSize(textSizeOption)
ob.orderBox := createOBBox(orderColor, textSize, 1.5)
if ob.info.combined
ob.orderBox.set_bgcolor(colorWithTransparency(orderColor, 1.1))
ob.orderBoxText := createOBBox(color.new(color.white, 100), textSize)
if showVolume or showPercentage
ob.orderBoxPositive := createOBBox(bullOrderBlockinColor, textSize)
ob.orderBoxNegative := createOBBox(bearOrderBlockinColor, textSize)
ob.orderSeperator := line.new(na,na,na,na,xloc.bar_time,extend.none,textColor,line.style_dashed,1)
ob.orderTextSeperator := line.new(na,na,na,na,xloc.bar_time,extend.none,textColor,line.style_solid,1)
zoneSize = if obBoxLengthOption == "RANGE"
time - info.startTime
else if obBoxLengthOption == "CUSTOM"
time - info.startTime + adjustableLength * timeframe.in_seconds(timeframe.period)
else
extendZonesByTime
startX = volumeBarsLeftSide ? info.startTime : info.startTime + zoneSize - zoneSize / 3
maxEndX = volumeBarsLeftSide ? info.startTime + zoneSize / 3 : info.startTime + zoneSize
moveBox(ob.orderBox, info.startTime, info.top, info.startTime + zoneSize, info.bottom)
moveBox(ob.orderBoxText, volumeBarsLeftSide ? maxEndX : info.startTime, info.top, volumeBarsLeftSide ? info.startTime + zoneSize : startX, info.bottom)
percentage = int((math.min(info.obHighVolume, info.obLowVolume) / math.max(info.obHighVolume, info.obLowVolume)) * 100.0)
OBText = (na(ob.info.combinedTimeframesStr) ? formatTimeframeString(ob.info.timeframeStr) : ob.info.combinedTimeframesStr) + " " + (info.breaker ? "BB" : "OB")
textToDisplay = ""
if showTimeframeOB
textToDisplay += OBText + " "
if showVolume
textToDisplay += str.tostring(ob.info.obVolume, format.volume) + " "
if showPercentage
textToDisplay += "(" + str.tostring(percentage) + "%)"
box.set_text(ob.orderBoxText, textToDisplay)
if showVolume or showPercentage
showHighLowBoxText = false
curEndXHigh = int(math.ceil((info.obHighVolume / info.obVolume) * (maxEndX - startX) + startX))
curEndXLow = int(math.ceil((info.obLowVolume / info.obVolume) * (maxEndX - startX) + startX))
moveBox(ob.orderBoxPositive, mirrorVolumeBars ? startX : curEndXLow, info.top, mirrorVolumeBars ? curEndXHigh : maxEndX, (info.bottom + info.top) / 2)
box.set_text(ob.orderBoxPositive, showHighLowBoxText ? str.tostring(info.obHighVolume, format.volume) : "")
moveBox(ob.orderBoxNegative, mirrorVolumeBars ? startX : curEndXHigh, info.bottom, mirrorVolumeBars ? curEndXLow : maxEndX, (info.bottom + info.top) / 2)
box.set_text(ob.orderBoxNegative, showHighLowBoxText ? str.tostring(info.obLowVolume, format.volume) : "")
moveLine(ob.orderSeperator, volumeBarsLeftSide ? startX : maxEndX, (info.bottom + info.top) / 2, volumeBarsLeftSide ? maxEndX : startX)
line.set_xy1(ob.orderTextSeperator, volumeBarsLeftSide ? maxEndX : startX, info.top)
line.set_xy2(ob.orderTextSeperator, volumeBarsLeftSide ? maxEndX : startX, info.bottom)
findOBSwings(len) =>
var swingType = 0
var obSwing top = obSwing.new(na, na)
var obSwing bottom = obSwing.new(na, na)
upper = ta.highest(len)
lower = ta.lowest(len)
swingType := high[len] > upper ? 0 : low[len] < lower ? 1 : swingType
if swingType == 0 and swingType[1] != 0
top := obSwing.new(bar_index[len], high[len], volume[len])
if swingType == 1 and swingType[1] != 1
bottom := obSwing.new(bar_index[len], low[len], volume[len])
[top, bottom]
findOrderBlocks (length) =>
if bar_index > last_bar_index - maxDistanceToLastBar
[top, btm] = findOBSwings(length)
useBody = false
max = useBody ? math.max(close, open) : high
min = useBody ? math.min(close, open) : low
// Bullish Order Block
bullishBreaked = 0
if array.size(bullishOrderBlocksList) > 0
for i = array.size(bullishOrderBlocksList) - 1 to 0
currentOB = array.get(bullishOrderBlocksList, i)
if not na(currentOB) and not currentOB.breaker
if (obEndMethod == "Wick" ? low : math.min(open, close)) < currentOB.bottom
currentOB.breaker := true
currentOB.breakTime := time
currentOB.bbVolume := volume
else
if not na(currentOB) and high > currentOB.top
array.remove(bullishOrderBlocksList, i)
else if not na(currentOB) and i < bullishOrderBlocks and top.y < currentOB.top and top.y > currentOB.bottom
bullishBreaked := 1
if close > top.y and not top.crossed
top.crossed := true
boxBtm = max[1]
boxTop = min[1]
boxLoc = time[1]
for i = 1 to (bar_index - top.x) - 1
boxBtm := math.min(min[i], boxBtm)
boxTop := boxBtm == min[i] ? max[i] : boxTop
boxLoc := boxBtm == min[i] ? time[i] : boxLoc
newOrderBlockInfo = orderBlockInfo.new(boxTop, boxBtm, volume + volume[1] + volume[2], "Bull", boxLoc)
newOrderBlockInfo.obLowVolume := volume[2]
newOrderBlockInfo.obHighVolume := volume + volume[1]
obSize = math.abs(newOrderBlockInfo.top - newOrderBlockInfo.bottom)
if obSize <= atr * maxATRMult
array.unshift(bullishOrderBlocksList, newOrderBlockInfo)
if array.size(bullishOrderBlocksList) > maxOrderBlocks
array.pop(bullishOrderBlocksList)
// Bearish Order Block
bearishBreaked = 0
if array.size(bearishOrderBlocksList) > 0
for i = array.size(bearishOrderBlocksList) - 1 to 0
currentOB = array.get(bearishOrderBlocksList, i)
if not na(currentOB) and not currentOB.breaker
if (obEndMethod == "Wick" ? high : math.max(open, close)) > currentOB.top
currentOB.breaker := true
currentOB.breakTime := time
currentOB.bbVolume := volume
else
if not na(currentOB) and low < currentOB.bottom
array.remove(bearishOrderBlocksList, i)
else if not na(currentOB) and i < bearishOrderBlocks and btm.y > currentOB.bottom and btm.y < currentOB.top
bearishBreaked := 1
if close < btm.y and not btm.crossed
btm.crossed := true
boxBtm = min[1]
boxTop = max[1]
boxLoc = time[1]
for i = 1 to (bar_index - btm.x) - 1
boxTop := math.max(max[i], boxTop)
boxBtm := boxTop == max[i] ? min[i] : boxBtm
boxLoc := boxTop == max[i] ? time[i] : boxLoc
newOrderBlockInfo = orderBlockInfo.new(boxTop, boxBtm, volume + volume[1] + volume[2], "Bear", boxLoc)
newOrderBlockInfo.obLowVolume := volume + volume[1]
newOrderBlockInfo.obHighVolume := volume[2]
obSize = math.abs(newOrderBlockInfo.top - newOrderBlockInfo.bottom)
if obSize <= atr * maxATRMult
array.unshift(bearishOrderBlocksList, newOrderBlockInfo)
if array.size(bearishOrderBlocksList) > maxOrderBlocks
array.pop(bearishOrderBlocksList)
true
areaOfOB (orderBlockInfo OBInfoF) =>
float XA1 = OBInfoF.startTime
float XA2 = na(OBInfoF.breakTime) ? time + 1 : OBInfoF.breakTime
float YA1 = OBInfoF.top
float YA2 = OBInfoF.bottom
float edge1 = math.sqrt((XA2 - XA1) * (XA2 - XA2) + (YA2 - YA2) * (YA2 - YA2))
float edge2 = math.sqrt((XA2 - XA2) * (XA2 - XA2) + (YA2 - YA1) * (YA2 - YA1))
float totalArea = edge1 * edge2
totalArea
doOBsTouch (orderBlockInfo OBInfo1, orderBlockInfo OBInfo2) =>
float XA1 = OBInfo1.startTime
float XA2 = na(OBInfo1.breakTime) ? time + 1 : OBInfo1.breakTime
float YA1 = OBInfo1.top
float YA2 = OBInfo1.bottom
float XB1 = OBInfo2.startTime
float XB2 = na(OBInfo2.breakTime) ? time + 1 : OBInfo2.breakTime
float YB1 = OBInfo2.top
float YB2 = OBInfo2.bottom
float intersectionArea = math.max(0, math.min(XA2, XB2) - math.max(XA1, XB1)) * math.max(0, math.min(YA1, YB1) - math.max(YA2, YB2))
float unionArea = areaOfOB(OBInfo1) + areaOfOB(OBInfo2) - intersectionArea
float overlapPercentage = (intersectionArea / unionArea) * 100.0
if overlapPercentage > overlapThresholdPercentage
true
else
false
isOBValid (orderBlockInfo OBInfo) =>
valid = true
if OBInfo.disabled
valid := false
valid
combineOBsFunc () =>
if array.size(allOrderBlocksList) > 0
lastCombinations = 999
while lastCombinations > 0
lastCombinations := 0
for i = 0 to array.size(allOrderBlocksList) - 1
curOB1 = array.get(allOrderBlocksList, i)
for j = 0 to array.size(allOrderBlocksList) - 1
curOB2 = array.get(allOrderBlocksList, j)
if i == j
continue
if not isOBValid(curOB1.info) or not isOBValid(curOB2.info)
continue
if curOB1.info.obType != curOB2.info.obType
continue
if doOBsTouch(curOB1.info, curOB2.info)
curOB1.info.disabled := true
curOB2.info.disabled := true
orderBlock newOB = createOrderBlock(orderBlockInfo.new(math.max(curOB1.info.top, curOB2.info.top), math.min(curOB1.info.bottom, curOB2.info.bottom), curOB1.info.obVolume + curOB2.info.obVolume, curOB1.info.obType))
newOB.info.startTime := math.min(curOB1.info.startTime, curOB2.info.startTime)
newOB.info.breakTime := math.max(nz(curOB1.info.breakTime), nz(curOB2.info.breakTime))
newOB.info.breakTime := newOB.info.breakTime == 0 ? na : newOB.info.breakTime
newOB.info.timeframeStr := curOB1.info.timeframeStr
newOB.info.obVolume := curOB1.info.obVolume + curOB2.info.obVolume
newOB.info.obLowVolume := curOB1.info.obLowVolume + curOB2.info.obLowVolume
newOB.info.obHighVolume := curOB1.info.obHighVolume + curOB2.info.obHighVolume
newOB.info.bbVolume := nz(curOB1.info.bbVolume, 0) + nz(curOB2.info.bbVolume, 0)
newOB.info.breaker := curOB1.info.breaker or curOB2.info.breaker
newOB.info.combined := true
if timeframe.in_seconds(curOB1.info.timeframeStr) != timeframe.in_seconds(curOB2.info.timeframeStr)
newOB.info.combinedTimeframesStr := (na(curOB1.info.combinedTimeframesStr) ? formatTimeframeString(curOB1.info.timeframeStr) : curOB1.info.combinedTimeframesStr) + " & " + (na(curOB2.info.combinedTimeframesStr) ? formatTimeframeString(curOB2.info.timeframeStr) : curOB2.info.combinedTimeframesStr)
array.unshift(allOrderBlocksList, newOB)
lastCombinations += 1
reqSeq (timeframeStr) =>
[bullishOrderBlocksListF, bearishOrderBlocksListF] = request.security(syminfo.tickerid, timeframeStr, [bullishOrderBlocksList, bearishOrderBlocksList])
[bullishOrderBlocksListF, bearishOrderBlocksListF]
getTFData (timeframeInfo timeframeInfoF, timeframeStr) =>
if timeframeInfoF.isEnabled
[bullishOrderBlocksListF, bearishOrderBlocksListF] = reqSeq(timeframeStr)
if na(bullishOrderBlocksListF) or na(bearishOrderBlocksListF)
[array.new<orderBlockInfo>(0), array.new<orderBlockInfo>(0)]
else
[bullishOrderBlocksListF, bearishOrderBlocksListF]
else
[array.new<orderBlockInfo>(0), array.new<orderBlockInfo>(0)]
handleTimeframeInfo (timeframeInfo timeframeInfoF, bullishOrderBlocksListF, bearishOrderBlocksListF) =>
if timeframeInfoF.isEnabled
if not na(bullishOrderBlocksListF)
timeframeInfoF.bullishOrderBlocksList := bullishOrderBlocksListF
else
timeframeInfoF.bullishOrderBlocksList := array.new<orderBlockInfo>(0)
if not na(bearishOrderBlocksListF)
timeframeInfoF.bearishOrderBlocksList := bearishOrderBlocksListF
else
timeframeInfoF.bearishOrderBlocksList := array.new<orderBlockInfo>(0)
handleOrderBlocksFinal () =>
if DEBUG
log.info("Bullish OB Count " + str.tostring(array.size(bullishOrderBlocksList)))
log.info("Bearish OB Count " + str.tostring(array.size(bearishOrderBlocksList)))
if array.size(allOrderBlocksList) > 0
for i = 0 to array.size(allOrderBlocksList) - 1
safeDeleteOrderBlock(array.get(allOrderBlocksList, i))
array.clear(allOrderBlocksList)
for i = 0 to array.size(timeframeInfos) - 1
curTimeframe = array.get(timeframeInfos, i)
if not curTimeframe.isEnabled
continue
if not na(curTimeframe.bullishOrderBlocksList) and array.size(curTimeframe.bullishOrderBlocksList) > 0
for j = 0 to math.min(array.size(curTimeframe.bullishOrderBlocksList) - 1, bullishOrderBlocks - 1)
orderBlockInfoF = array.get(curTimeframe.bullishOrderBlocksList, j)
orderBlockInfoF.timeframeStr := curTimeframe.timeframeStr
array.unshift(allOrderBlocksList, createOrderBlock(orderBlockInfo.copy(orderBlockInfoF)))
if not na(curTimeframe.bearishOrderBlocksList) and array.size(curTimeframe.bearishOrderBlocksList) > 0
for j = 0 to math.min(array.size(curTimeframe.bearishOrderBlocksList) - 1, bearishOrderBlocks - 1)
orderBlockInfoF = array.get(curTimeframe.bearishOrderBlocksList, j)
orderBlockInfoF.timeframeStr := curTimeframe.timeframeStr
array.unshift(allOrderBlocksList, createOrderBlock(orderBlockInfo.copy(orderBlockInfoF)))
if combineOBs
combineOBsFunc()
if array.size(allOrderBlocksList) > 0
for i = 0 to array.size(allOrderBlocksList) - 1
curOB = array.get(allOrderBlocksList, i)
if isOBValid(curOB.info)
renderOrderBlock(curOB)
if showOBs or showBBs
swingLength = switch swingLengthOption
"SHORT" => 10
"MID" => 28
"LONG" => 50
"CUSTOM" => swingLength
findOrderBlocks(swingLength)
[bullishOrderBlocksListTimeframe1, bearishOrderBlocksListTimeframe1] = getTFData(array.get(timeframeInfos, 0), timeframe1)
[bullishOrderBlocksListTimeframe2, bearishOrderBlocksListTimeframe2] = getTFData(array.get(timeframeInfos, 1), timeframe2)
if barstate.isconfirmed
handleTimeframeInfo(array.get(timeframeInfos, 0), bullishOrderBlocksListTimeframe1, bearishOrderBlocksListTimeframe1)
handleTimeframeInfo(array.get(timeframeInfos, 1), bullishOrderBlocksListTimeframe2, bearishOrderBlocksListTimeframe2)
handleOrderBlocksFinal()
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------- LIQUIDITY LEVELS CALCULATIONS & FUNCTIONS -----------------------------------//
//------------------------------------------------------------------------------------------------------------------------------------------------------//
liquidityLength = switch liquidityLengthOption
"SHORT" => 10
"MID" => 28
"LONG" => 50
"CUSTOM" => liquidityswingLength
// Function to adjust the leftBars based on the timeframe to avoid exceeding the max_bars_back
adjustedLeftBars(tf, baseLeftBars) =>
tf_seconds = timeframe.in_seconds(tf)
if tf_seconds <= 60 // If the timeframe is 1 minute or less
10
else if tf_seconds <= 300 // If the timeframe is 5 minutes or less
20
else
baseLeftBars
leftBars = adjustedLeftBars(htfTF, liquidityLength)
displayStyle_liq = "Boxes"
timediff = (time[1] - time[101]) / 100
highLineColor = highLineColorHTF
lowLineColor = lowLineColorHTF
highBoxBgColor = highLineColorHTF
highBoxBorderColor = highBoxBorderColorHTF
lowBoxBgColor = lowLineColorHTF
lowBoxBorderColor = lowBoxBorderColorHTF
atr_liq = ta.atr(300)
float thold_liq = atr_liq * (box_width / 10)
tf_multi(tf) =>
ts = timeframe.in_seconds("")
htfs = timeframe.in_seconds(tf)
htfs / ts
display_limit_lines(_array, _limit) =>
while array.size(_array) > _limit
line.delete(array.shift(_array))
display_limit_boxes(_array, _limit) =>
while array.size(_array) > _limit
box.delete(array.shift(_array))
remove_mitigated_lines(_array, _hl, _candleType, _mitiOptions, _lineColor, _lineStyle, _lineWidth) =>
if array.size(_array) > 0
for i = array.size(_array) - 1 to 0 by 1
l = array.get(_array, i)
hh = _candleType == "Close" ? close[1] : high
ll = _candleType == "Close" ? close[1] : low
if _hl == "High" and hh > line.get_y1(l)
array.remove(_array, i)
if _mitiOptions == "Show"
line.new(line.get_x1(l), line.get_y1(l), time, line.get_y1(l), xloc = xloc.bar_time, color = _lineColor, style = _lineStyle, width = _lineWidth)
line.delete(l)
if _hl == "Low" and ll < line.get_y1(l)
array.remove(_array, i)
if _mitiOptions == "Show"
line.new(line.get_x1(l), line.get_y1(l), time, line.get_y1(l), xloc = xloc.bar_time, color = _lineColor, style = _lineStyle, width = _lineWidth)
line.delete(l)
remove_mitigated_boxes(_array, _hl, _candleType, _mitiOptions, _bgColor, _borderColor, _lineStyle, _lineWidth) =>
if array.size(_array) > 0
for i = array.size(_array) - 1 to 0 by 1
b = array.get(_array, i)
hh = _candleType == "Close" ? close[1] : high
ll = _candleType == "Close" ? close[1] : low
if _hl == "High" and hh > box.get_top(b)
array.remove(_array, i)
if _mitiOptions == "Show"
box.new(box.get_left(b), box.get_top(b), time, box.get_bottom(b), xloc = xloc.bar_time, bgcolor = color.new(_bgColor, 90), border_color = color.new(_borderColor, 90), border_style = _lineStyle, border_width = _lineWidth)
box.delete(b)
if _hl == "Low" and ll < box.get_top(b)
array.remove(_array, i)
if _mitiOptions == "Show"
box.new(box.get_left(b), box.get_top(b), time, box.get_bottom(b), xloc = xloc.bar_time, bgcolor = color.new(_bgColor, 90), border_color = color.new(_borderColor, 90), border_style = _lineStyle, border_width = _lineWidth)
box.delete(b)
extend_line_to_current(lineArray, _length_extend, _timediff) =>
if array.size(lineArray) > 0
for i = array.size(lineArray) - 1 to 0 by 1
l = array.get(lineArray, i)
timeExt = timenow + ((_timediff) * _length_extend)
line.set_x2(l, timeExt)
extend_box_to_current(boxArray, _length_extend, _timediff) =>
if array.size(boxArray) > 0
for i = array.size(boxArray) - 1 to 0 by 1
b = array.get(boxArray, i)
timeExt = timenow + ((_timediff) * _length_extend)
box.set_right(b, timeExt)
var highLineArrayHTF = array.new_line()
var lowLineArrayHTF = array.new_line()
var highBoxArrayHTF = array.new_box()
var lowBoxArrayHTF = array.new_box()
[_time, _open, _high, _low, _close, vol] = request.security(syminfo.tickerid, htfTF, [time, open, high, low, close, volume])
pivotHighHTF = ta.pivothigh(_high, leftBars, leftBars)
pivotLowHTF = ta.pivotlow(_low, leftBars, leftBars)
timeExt = time + ((time[1] - time[2]) * 10)
dis = leftBars
label_size_external = switch textSize
"XS" => size.tiny
"S" => size.small
"M" => size.normal
"L" => size.large
"XL" => size.huge
highest_volume = ta.highest(vol, 300)
volume_percentage = (vol / highest_volume) * 100
format_volume(vol) =>
vol >= 1000000000 ? str.tostring(vol / 1000000000, '#.##') + "B" : vol >= 1000000 ? str.tostring(vol / 1000000, '#.##') + "M" : str.tostring(vol / 1000, '#.##') + "K"
format_tf(tf) =>
tf == "1" ? "1Min" :tf == "2" ? "2Min" : tf == "3" ? "3Min" : tf == "5" ? "5Min" : tf == "10" ? "10Min" : tf == "15" ? "15Min" : tf == "30" ? "30Min" : tf == "45" ? "45Min" : tf == "60" ? "1H" : tf == "120" ? "2H" : tf == "180" ? "3H" : tf == "240" ? "4H" : tf == "D" ? "1D" : tf == "W" ? "1W" : tf == "M" ? "1M" : tf == "M" ? "3M" :tf == "M" ? "6M" : tf == "Y" ? "1Y" : tf
if currentTF
if pivotHighHTF
if displayStyle_liq == "Lines"
array.push(highLineArrayHTF, line.new(_time[dis], _high[dis], _time[+1], _high[dis], color = highLineColorHTF, style = highLineStyleHTF, xloc = xloc.bar_time, extend = extentionMax ? extend.right : extend.none, width = lineWidthHTF))
else
y1 = _high[dis] - thold_liq
volume_text = show_text ? (htfTF == "" ? "" : "(" + format_tf(htfTF) + ") ") + "Buy Side 💲" : ""
if show_volume
volume_text := volume_text + format_volume(vol)
if show_percent
volume_text := volume_text + " (" + str.tostring(volume_percentage, '#.##') + "%)"
array.push(highBoxArrayHTF, box.new(_time[dis], _high[dis], _time[+1], y1, bgcolor = highLineColorHTF, border_color = highBoxBorderColorHTF, xloc = xloc.bar_time, border_style = highLineStyleHTF, extend = extentionMax ? extend.right : extend.none, border_width = lineWidthHTF, text = volume_text, text_halign = text.align_center, text_color = liquidity_text_color, text_size = label_size_external))
alert("Buy Side Liquidity Detected: {{ticker}}, Price = {{close}}, Volume = {{volume}}", alert.freq_once_per_bar)
if pivotLowHTF
if displayStyle_liq == "Lines"
array.push(lowLineArrayHTF, line.new(_time[dis], _low[dis], _time[+1], _low[dis], color = lowLineColorHTF, style = highLineStyleHTF, xloc = xloc.bar_time, extend = extentionMax ? extend.right : extend.none, width = lineWidthHTF))
else
y1 = _low[dis] + thold_liq
volume_text = show_text ? (htfTF == "" ? "" : "(" + format_tf(htfTF) + ") ") + "Sell Side 💲" : ""
if show_volume
volume_text := volume_text + format_volume(vol)
if show_percent
volume_text := volume_text + " (" + str.tostring(volume_percentage, '#.##') + "%)"
array.push(lowBoxArrayHTF, box.new(_time[dis], _low[dis], _time[+1], y1, bgcolor = lowLineColorHTF, border_color = lowBoxBorderColorHTF, xloc = xloc.bar_time, border_style = highLineStyleHTF, extend = extentionMax ? extend.right : extend.none, border_width = lineWidthHTF, text = volume_text, text_halign = text.align_center, text_color = liquidity_text_color, text_size = label_size_external))
alert("Sell Side Liquidity Detected: {{ticker}}, Price = {{close}}, Volume = {{volume}}", alert.freq_once_per_bar)
remove_mitigated_lines(highLineArrayHTF, "High", _candleType, mitiOptions, highLineColorHTF, highLineStyleHTF, lineWidthHTF)
remove_mitigated_boxes(highBoxArrayHTF, "High", _candleType, mitiOptions, highBoxBgColor, highBoxBorderColorHTF, highLineStyleHTF, lineWidthHTF)
remove_mitigated_lines(lowLineArrayHTF, "Low", _candleType, mitiOptions, lowLineColorHTF, highLineStyleHTF, lineWidthHTF)
remove_mitigated_boxes(lowBoxArrayHTF, "Low", _candleType, mitiOptions, lowBoxBgColor, lowBoxBorderColorHTF, highLineStyleHTF, lineWidthHTF)
display_limit_boxes(highBoxArrayHTF, displayLimitBuy)
display_limit_boxes(lowBoxArrayHTF, displayLimitSell)
extend_line_to_current(highLineArrayHTF, length_extend_liq, timediff)
extend_line_to_current(lowLineArrayHTF, length_extend_liq, timediff)
extend_box_to_current(highBoxArrayHTF, length_extend_liq, timediff)
extend_box_to_current(lowBoxArrayHTF, length_extend_liq, timediff)
tf1_buy_side_liquidity_break = array.size(highLineArrayHTF) > 0 ? close > line.get_y1(array.get(highLineArrayHTF, array.size(highLineArrayHTF) - 1)) : na
tf1_sell_side_liquidity_break = array.size(lowLineArrayHTF) > 0 ? close < line.get_y1(array.get(lowLineArrayHTF, array.size(lowLineArrayHTF) - 1)) : na
tf1_buy_side_liquidity_touch = array.size(highLineArrayHTF) > 0 ? high >= line.get_y1(array.get(highLineArrayHTF, array.size(highLineArrayHTF) - 1)) : na
tf1_sell_side_liquidity_touch = array.size(lowLineArrayHTF) > 0 ? low <= line.get_y1(array.get(lowLineArrayHTF, array.size(lowLineArrayHTF) - 1)) : na
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------- FAIR VALUE GAPS CALCULATIONS & FUNCTIONS ------------------------------------//
//------------------------------------------------------------------------------------------------------------------------------------------------------//
// Define missing variables
i_tfos = 10
i_mtfos = 50
i_fillByMid = true
i_bullishfvgcolor = #ffc40041
i_bearishfvgcolor = #ffc4003f
i_textColor = #ffffff
i_deleteonfill = true
i_mtf = "HTF"
// Variables for high and low of the current timeframe
var float htfH = na
var float htfL = na
// Variables for security function requests
var float sClose = na
var float sHighP2 = na
var float sLowP2 = na
var float sOpen = na
var float sBar = na
var float sClose2 = na
var float sHighP22 = na
var float sLowP22 = na
var float sOpen2 = na
var float sBar2 = na
// Variables for FVG management
var bullishgapholder = array.new_box(0)
var bearishgapholder = array.new_box(0)
var bullishgapholder_fill = array.new_box(0)
var bearishgapholder_fill = array.new_box(0)
var bullish_high_holder = array.new_line(0)
var bearish_high_holder = array.new_line(0)
var bullish_low_holder = array.new_line(0)
var bearish_low_holder = array.new_line(0)
var bullishmidholder = array.new_line(0)
var bearishmidholder = array.new_line(0)
var bullishlabelholder = array.new_label(0)
var bearishlabelholder = array.new_label(0)
var bullishgapholder2 = array.new_box(0)
var bearishgapholder2 = array.new_box(0)
var bullishgapholder_fill2 = array.new_box(0)
var bearishgapholder_fill2 = array.new_box(0)
var bullish_high_holder2 = array.new_line(0)
var bearish_high_holder2 = array.new_line(0)
var bullish_low_holder2 = array.new_line(0)
var bearish_low_holder2 = array.new_line(0)
var bullishmidholder2 = array.new_line(0)
var bearishmidholder2 = array.new_line(0)
var bullishlabelholder2 = array.new_label(0)
var bearishlabelholder2 = array.new_label(0)
var transparentcolor = color.new(color.white,100)
var fvg_apper=false
var fvg_break=false
fvg_apper:=false
fvg_break:=false
lineStyle(x) =>
switch x
'Solid' => line.style_solid
'Dashed' => line.style_dashed
'Dotted' => line.style_dotted
create_fvg_func(_upperlimit,_lowerlimit,_midlimit,_bar,_boxholder,_boxholder_fill,_midholder,_highholder,_lowholder,_labelholder,_boxcolor,_mtfboxcolor, _htf)=>
timeholder = str.tostring(i_tf)
offset = i_mtfos
boxbgcolor = _mtfboxcolor
bg_color = color.new(_mtfboxcolor,90)
if _htf == false
timeholder := str.tostring(timeframe.period)
offset := i_tfos
boxbgcolor := _boxcolor
array.push(_boxholder,box.new(_bar,_upperlimit,_bar+(timediff)*length_extend,_lowerlimit,border_color=fvg_color_fill? bg_color : na,bgcolor = fvg_color_fill? bg_color : na, extend = fvg_extend ? extend.right:extend.none,xloc = xloc.bar_time,text='',text_color=#787b86,text_halign=text.align_right,text_size=size.small))
array.push(_boxholder_fill,box.new(_bar,_upperlimit,_bar+(timediff)*length_extend,_lowerlimit,border_color=fvg_color_fill? bg_color : na ,bgcolor = fvg_color_fill? bg_color : na, extend = fvg_extend ? extend.right:extend.none,xloc = xloc.bar_time))
array.push(_midholder,line.new(_bar,(_lowerlimit+_upperlimit)/2.0,_bar+(timediff)*length_extend,_midlimit,color = i_midPointColor, extend = fvg_extend ? extend.right:extend.none,style=lineStyle(mid_style),width=1,xloc = xloc.bar_time))
array.push(_lowholder,line.new(_bar,_lowerlimit,_bar+(timediff)*length_extend,_lowerlimit,color = i_fillByMid?boxbgcolor:na, extend = fvg_extend ? extend.right:extend.none,width=1,xloc = xloc.bar_time))
array.push(_highholder,line.new(_bar,_upperlimit,_bar+(timediff)*length_extend,_upperlimit,color = i_fillByMid?boxbgcolor:na, extend = fvg_extend ? extend.right:extend.none,width=1,xloc = xloc.bar_time))
check_fvg_func(_close,_high,_highp2,_low,_lowp2,_open,_bar,_htf)=>
gap=0
thold_ = (ta.highest(_high,300) - ta.lowest(_low,300)) * math.max(max_width_fvg, 0.1) / 100.
if _open > _close // red
if _lowp2>_high
if not(remove_small) or math.abs(_lowp2 -_high) > thold_
upperlimit = _high
lowerlimit = _lowp2
midlimit = lowerlimit + ((upperlimit - lowerlimit) / 2.)
gap:=1
create_fvg_func(upperlimit,lowerlimit,midlimit,_bar,bullishgapholder,bullishgapholder_fill,bullishmidholder,bullish_high_holder,bullish_low_holder,bullishlabelholder,i_bullishfvgcolor,i_mtfbearishfvgcolor,_htf)
else
if _low>_highp2
if not(remove_small) or math.abs(_low - _highp2) > thold_
upperlimit = _low
lowerlimit = _highp2
midlimit = lowerlimit + ((upperlimit - lowerlimit) / 2.)
gap:=-1
create_fvg_func(upperlimit,lowerlimit,midlimit,_bar,bearishgapholder,bearishgapholder_fill,bearishmidholder,bearish_high_holder,bearish_low_holder,bearishlabelholder,i_bearishfvgcolor,i_mtfbullishfvgcolor,_htf)
gap
delete_fvg_func(_currentgap,_currentgap_fill,_i,_boxholder,_boxholder_fill,_midholder,_highholder,_lowholder,_labelholder)=>
if show_mitigated_fvg
currentmid=array.get(_midholder,_i)
currenthigh=array.get(_highholder,_i)
currentlow=array.get(_lowholder,_i)
if i_deleteonfill
line.delete(currentmid)
line.delete(currenthigh)
line.delete(currentlow)
else
line.set_extend(currentmid, extend.none)
line.set_x2(currentmid,time)
line.set_extend(currenthigh, extend.none)
line.set_x2(currenthigh,time)
line.set_extend(currentlow, extend.none)
line.set_x2(currentlow,time)
if i_deleteonfill
box.set_extend(_currentgap, extend.none)
box.set_right(_currentgap, time)
box.set_extend(_currentgap_fill, extend.none)
box.set_right(_currentgap_fill, time)
else
array.push(_boxholder, _currentgap)
array.push(_boxholder_fill, _currentgap_fill)
else
array.remove(_boxholder, _i)
array.remove(_boxholder_fill, _i)
currentmid=array.get(_midholder,_i)
currenthigh=array.get(_highholder,_i)
currentlow=array.get(_lowholder,_i)
array.remove(_midholder,_i)
array.remove(_highholder,_i)
array.remove(_lowholder,_i)
if i_deleteonfill
line.delete(currentmid)
line.delete(currenthigh)
line.delete(currentlow)
else
line.set_extend(currentmid, extend.none)
line.set_x2(currentmid,time)
line.set_extend(currenthigh, extend.none)
line.set_x2(currenthigh,time)
line.set_extend(currentlow, extend.none)
line.set_x2(currentlow,time)
if i_deleteonfill
box.delete(_currentgap)
box.delete(_currentgap_fill)
else
box.set_extend(_currentgap,extend.none)
box.set_right(_currentgap,time)
validate_fvg_func(_high,_low,_bearishgapholder,_bullishgapholder,_bearishgapholder_fill,_bullishgapholder_fill,_bearishmidholder,_bullishmidholder,_bearish_high_holder,_bullish_high_holder,_bearish_low_holder,_bullish_low_holder)=>
fvg_removed=0
if array.size(bullishgapholder) > 0
for i = array.size(bullishgapholder)-1 to 0
if fvg_extend_B
currentgap_fill = array.get(bullishgapholder_fill,i)
currentgap = array.get(bullishgapholder,i)
cmid = array.get(bullishmidholder,i)
chigh = array.get(bullish_high_holder,i)
clow = array.get(bullish_low_holder,i)
line.set_x2(cmid,timenow+(timediff)*length_extend)
line.set_x2(chigh,timenow+(timediff)*length_extend)
line.set_x2(clow,timenow+(timediff)*length_extend)
box.set_right(currentgap_fill,timenow+(timediff)*length_extend)
box.set_right(currentgap,timenow+(timediff)*length_extend)
if mittigation_filt_fvg=='Touch'
currentgap_fill = array.get(bullishgapholder_fill,i)
currentgap = array.get(bullishgapholder,i)
currentmid = array.get(bullishmidholder,i)
currenthigh = array.get(bullish_high_holder,i)
currentlow = array.get(bullish_low_holder,i)
currenttop = box.get_top(currentgap)
if high > currenttop
fvg_removed:=1
delete_fvg_func(currentgap,currentgap_fill,i,bullishgapholder,bullishgapholder_fill,bullishmidholder,bullish_high_holder,bullish_low_holder,bullishlabelholder)
if mittigation_filt_fvg=='Wicks'
currentgap_fill = array.get(bullishgapholder_fill,i)
currentgap = array.get(bullishgapholder,i)
currentmid = array.get(bullishmidholder,i)
currenthigh = array.get(bullish_high_holder,i)
currentlow = array.get(bullish_low_holder,i)
currenttop = box.get_bottom(currentgap)
currentbottom = box.get_top(currentgap_fill)
if high > currentbottom and fvg_shade_fill
currentgap_f = array.get(bullishgapholder_fill,i)
cur_bottom=box.get_bottom(currentgap_f)
_bottom=box.get_bottom(currentgap)
if _bottom==cur_bottom
box.set_bottom(currentgap_f,high)
else
box.set_bottom(currentgap_f,math.max(cur_bottom,high))
box.set_bgcolor(currentgap_f,#787b865e)
if high > currenttop
fvg_removed:=1
delete_fvg_func(currentgap,currentgap_fill,i,bullishgapholder,bullishgapholder_fill,bullishmidholder,bullish_high_holder,bullish_low_holder,bullishlabelholder)
if mittigation_filt_fvg=='Close'
currentgap_fill = array.get(bullishgapholder_fill,i)
currentgap = array.get(bullishgapholder,i)
currentmid = array.get(bullishmidholder,i)
currenthigh = array.get(bullish_high_holder,i)
currentlow = array.get(bullish_low_holder,i)
currenttop = box.get_bottom(currentgap)
currentbottom = box.get_top(currentgap_fill)
if high > currentbottom and fvg_shade_fill
currentgap_f = array.get(bullishgapholder_fill,i)
cur_bottom=box.get_bottom(currentgap_f)
_bottom=box.get_bottom(currentgap)
if _bottom==cur_bottom
box.set_bottom(currentgap_f,high)
else
box.set_bottom(currentgap_f,math.max(cur_bottom,high))
box.set_bgcolor(currentgap_f,#787b865e)
if close > currenttop
fvg_removed:=1
delete_fvg_func(currentgap,currentgap_fill,i,bullishgapholder,bullishgapholder_fill,bullishmidholder,bullish_high_holder,bullish_low_holder,bullishlabelholder)
if mittigation_filt_fvg=='Average'
currentgap_fill = array.get(bullishgapholder_fill,i)
currentgap = array.get(bullishgapholder,i)
currentmid = array.get(bullishmidholder,i)
currenthigh = array.get(bullish_high_holder,i)
currentlow = array.get(bullish_low_holder,i)
currenttop = line.get_y1(currentmid)
currentbottom = box.get_top(currentgap_fill)
if high > currentbottom and fvg_shade_fill
currentgap_f = array.get(bullishgapholder_fill,i)
cur_bottom=box.get_bottom(currentgap_f)
_bottom=box.get_bottom(currentgap)
if _bottom==cur_bottom
box.set_bottom(currentgap_f,high)
else
box.set_bottom(currentgap_f,math.max(cur_bottom,high))
box.set_bgcolor(currentgap_f,#787b865e)
if high > currenttop
fvg_removed:=1
delete_fvg_func(currentgap,currentgap_fill,i,bullishgapholder,bullishgapholder_fill,bullishmidholder,bullish_high_holder,bullish_low_holder,bullishlabelholder)
if array.size(bearishgapholder) > 0
for i = array.size(bearishgapholder)-1 to 0
if fvg_extend_B
currentgap_fill = array.get(bearishgapholder_fill,i)
currentgap = array.get(bearishgapholder,i)
cmid = array.get(bearishmidholder,i)
chigh = array.get(bearish_high_holder,i)
clow = array.get(bearish_low_holder,i)
line.set_x2(cmid,timenow+(timediff)*length_extend)
line.set_x2(chigh,timenow+(timediff)*length_extend)
line.set_x2(clow,timenow+(timediff)*length_extend)
box.set_right(currentgap_fill,timenow+(timediff)*length_extend)
box.set_right(currentgap,timenow+(timediff)*length_extend)
if mittigation_filt_fvg=='Touch'
currentgap_fill = array.get(bearishgapholder_fill,i)
currentgap = array.get(bearishgapholder,i)
currenttop = box.get_top(currentgap)
currentmid = array.get(bearishmidholder,i)
currenthigh = array.get(bearish_high_holder,i)
currentlow = array.get(bearish_low_holder,i)
if low < currenttop
fvg_removed:=-1
delete_fvg_func(currentgap,currentgap_fill,i,bearishgapholder,bearishgapholder_fill,bearishmidholder,bearish_high_holder,bearish_low_holder,bearishlabelholder)
if mittigation_filt_fvg=='Wicks'
currentgap_fill = array.get(bearishgapholder_fill,i)
currentgap = array.get(bearishgapholder,i)
currenttop = box.get_bottom(currentgap)
currentmid = array.get(bearishmidholder,i)
currenthigh = array.get(bearish_high_holder,i)
currentlow = array.get(bearish_low_holder,i)
currentbottom = box.get_top(currentgap_fill)
if low < currentbottom and fvg_shade_fill
currentgap_f = array.get(bearishgapholder_fill,i)
cur_bottom=box.get_bottom(currentgap_f)
_bottom=box.get_bottom(currentgap)
if _bottom==cur_bottom
box.set_bottom(currentgap_f,low)
else
box.set_bottom(currentgap_f,math.min(cur_bottom,low))
box.set_bgcolor(currentgap_f,#787b865e)
if low < currenttop
fvg_removed:=-1
delete_fvg_func(currentgap,currentgap_fill,i,bearishgapholder,bearishgapholder_fill,bearishmidholder,bearish_high_holder,bearish_low_holder,bearishlabelholder)
if mittigation_filt_fvg=='Close'
currentgap_fill = array.get(bearishgapholder_fill,i)
currentgap = array.get(bearishgapholder,i)
currenttop = box.get_bottom(currentgap)
currentmid = array.get(bearishmidholder,i)
currenthigh = array.get(bearish_high_holder,i)
currentlow = array.get(bearish_low_holder,i)
currentbottom = box.get_top(currentgap_fill)
if low < currentbottom and fvg_shade_fill
currentgap_f = array.get(bearishgapholder_fill,i)
cur_bottom=box.get_bottom(currentgap_f)
_bottom=box.get_bottom(currentgap)
if _bottom==cur_bottom
box.set_bottom(currentgap_f,low)
else
box.set_bottom(currentgap_f,math.min(cur_bottom,low))
box.set_bgcolor(currentgap_f,#787b865e)
if close < currenttop
fvg_removed:=-1
delete_fvg_func(currentgap,currentgap_fill,i,bearishgapholder,bearishgapholder_fill,bearishmidholder,bearish_high_holder,bearish_low_holder,bearishlabelholder)
if mittigation_filt_fvg=='Average'
currentgap_fill = array.get(bearishgapholder_fill,i)
currentgap = array.get(bearishgapholder,i)
currentmid = array.get(bearishmidholder,i)
currenttop = line.get_y1(currentmid)
currenthigh = array.get(bearish_high_holder,i)
currentlow = array.get(bearish_low_holder,i)
currentbottom = box.get_top(currentgap_fill)
if low < currentbottom and fvg_shade_fill
currentgap_f = array.get(bearishgapholder_fill,i)
cur_bottom=box.get_bottom(currentgap_f)
_bottom=box.get_bottom(currentgap)
if _bottom==cur_bottom
box.set_bottom(currentgap_f,low)
else
box.set_bottom(currentgap_f,math.min(cur_bottom,low))
box.set_bgcolor(currentgap_f,#787b865e)
if low < currenttop
fvg_removed:=-1
delete_fvg_func(currentgap,currentgap_fill,i,bearishgapholder,bearishgapholder_fill,bearishmidholder,bearish_high_holder,bearish_low_holder,bearishlabelholder)
fvg_removed
// Request security functions
sClose := request.security(ticker.standard(syminfo.tickerid), i_tf, close[1], barmerge.gaps_off, barmerge.lookahead_on)
sHighP2 := request.security(ticker.standard(syminfo.tickerid), i_tf, high[2], barmerge.gaps_off, barmerge.lookahead_on)
sLowP2 := request.security(ticker.standard(syminfo.tickerid), i_tf, low[2], barmerge.gaps_off, barmerge.lookahead_on)
sOpen := request.security(ticker.standard(syminfo.tickerid), i_tf, open[1], barmerge.gaps_off, barmerge.lookahead_on)
sBar := request.security(ticker.standard(syminfo.tickerid), i_tf, bar_index, barmerge.gaps_off, barmerge.lookahead_on)
if is_newbar(i_tf)
htfH := high
htfL := low
fvg_gap=0
validate_and_shift_fvg(_fvg_holder, _fvg_fill_holder, _mid_holder, _high_holder, _low_holder, _label_holder, max_fvg) =>
if array.size(_fvg_holder) > max_fvg
d_box=array.shift(_fvg_holder)
box.delete(d_box)
if array.size(_fvg_fill_holder) > max_fvg
d_box=array.shift(_fvg_fill_holder)
box.delete(d_box)
if array.size(_mid_holder) > max_fvg
d_line=array.shift(_mid_holder)
line.delete(d_line)
if array.size(_high_holder) > max_fvg
d_line=array.shift(_high_holder)
line.delete(d_line)
if array.size(_low_holder) > max_fvg
d_line=array.shift(_low_holder)
line.delete(d_line)
validate_and_shift_fvg(bullishgapholder, bullishgapholder_fill, bullishmidholder, bullish_high_holder, bullish_low_holder, bullishlabelholder, max_bearish_fvg)
validate_and_shift_fvg(bearishgapholder, bearishgapholder_fill, bearishmidholder, bearish_high_holder, bearish_low_holder, bearishlabelholder, max_bullish_fvg)
fvg_removed=validate_fvg_func(high,low, bearishgapholder,bullishgapholder, bearishgapholder_fill, bullishgapholder_fill, bearishmidholder, bullishmidholder, bearish_high_holder, bullish_high_holder, bearish_low_holder, bullish_low_holder)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------- TRENDLINES CALCULATIONS & FUNCTIONS -----------------------------------------//
//------------------------------------------------------------------------------------------------------------------------------------------------------//
// Linestyle options
get_line_style(style) =>
switch style
"SOLID" => line.style_solid
"DASHED" => line.style_dashed
"DOTTED" => line.style_dotted
LineStyleEnum1 = get_line_style(LineStyle1)
LineStyleEnum2 = get_line_style(LineStyle2)
get_max_count(option) =>
switch option
"2" => 2
"4" => 4
"6" => 6
"8" => 8
"10" => 10
"12" => 12
"14" => 14
"16" => 16
"18" => 18
"20" => 20
maxBearishCount = get_max_count(maxBearishCountOption)
maxBullishCount = get_max_count(maxBullishCountOption)
lengthTL = switch lengthOption
"SHORT" => 50
"MID" => 100
"LONG" => 200
"CUSTOM" => lengthCustom
get_text_size(option) =>
switch option
"XS" => size.tiny
"S" => size.small
"M" => size.normal
"L" => size.large
"XL" => size.huge
textSizeTL = get_text_size(textSizeOptionTL)
var float bs_H = na
var float bs_L = na
var int future_bars = 500 // Limit for future bars
// Variables
// Downtrendline
var int phx1 = na
var float phslope = na
var float phy1 = na
var float upper = na
var float plotH = na
var bool isOnH = false
var float secondUpper = na
var line[] bearishSolidLines = array.new_line()
var line[] bearishDottedLines = array.new_line()
var label[] bearishLabels = array.new_label()
// Uptrendline
var int plx1 = na
var float plslope = na
var float ply1 = na
var float lower = na
var float plotL = na
var bool isOnL = false
var float secondLower = na
var line[] bullishSolidLines = array.new_line()
var line[] bullishDottedLines = array.new_line()
var label[] bullishLabels = array.new_label()
var line testLine = line.new(na, na, na, na, color=color.rgb(255, 255, 255, 100))
// Variables to hold the lines for filling
var line bearishSolidLine1 = na
var line bearishSolidLine2 = na
var line bullishSolidLine1 = na
var line bullishSolidLine2 = na
// Calculations
n = bar_index
ph = ta.pivothigh(lengthTL, lengthTL)
pl = ta.pivotlow(lengthTL, lengthTL)
bars = 500
height = bars / 1
Xaxis = math.min(math.max(1, n), bars)
Yaxis = ta.highest(Xaxis) - ta.lowest(Xaxis)
// Function
calculate_slope(x1, x2, y1, y2) =>
diffX = x2 - x1
diffY = y2 - y1
diffY_to_Yaxis = Yaxis / diffY
normalised_slope = (height / diffY_to_Yaxis) / diffX
slope = diffY / diffX
angle = math.round(math.atan(normalised_slope) * 180 / math.pi, 2)
[normalised_slope, slope, angle]
add_trendline(line[] lines_array, line new_line, int max_count) =>
array.unshift(lines_array, new_line)
if array.size(lines_array) > max_count
line.delete(array.pop(lines_array))
add_label(label[] labels_array, label new_label, int max_count) =>
array.unshift(labels_array, new_label)
if array.size(labels_array) > max_count
label.delete(array.pop(labels_array))
draw_trendlines(line[] solid_lines, line[] dotted_lines, label[] labels_array) =>
for i = 0 to array.size(solid_lines) - 1
line solid_line = array.get(solid_lines, i)
line.set_xy1(solid_line, line.get_x1(solid_line), line.get_y1(solid_line))
line.set_xy2(solid_line, line.get_x2(solid_line), line.get_y2(solid_line))
if i < array.size(dotted_lines)
line dotted_line = array.get(dotted_lines, i)
line.set_xy1(dotted_line, line.get_x1(dotted_line), line.get_y1(dotted_line))
line.set_xy2(dotted_line, line.get_x2(dotted_line), line.get_y2(dotted_line))
if showA and i < array.size(labels_array)
label degree_label = array.get(labels_array, i)
label.set_xy(degree_label, line.get_x1(solid_line), line.get_y1(solid_line))
// Function to extend trendlines
extend_trendline(start_x, start_y, slope, color, style, width) =>
var int remaining_bars = future_bars
var int curr_x = start_x
var float curr_y = start_y
while remaining_bars > 0
end_x = curr_x + future_bars
end_y = curr_y + slope * future_bars
line.new(curr_x, curr_y, end_x, end_y, color=color, style=style, width=width)
curr_x := end_x
curr_y := end_y
remaining_bars -= future_bars
// Execution
if not na(ph)
if ph < phy1
[normalised_slope, slope, angle] = calculate_slope(phx1, n-lengthTL, phy1, ph)
testLine.set_xy1(phx1, phy1)
testLine.set_xy2(n, ph + slope * lengthTL)
src = close
max_bars_back(src, 2000)
isOnH := false
broken = false
if not useAngleFilter or (math.abs(angle) > anglA and math.abs(angle) < anglB)
if not broken
phslope := slope
isOnH := true
upper := ph + slope * lengthTL
secondUpper := upper * (1 + percent_from_first_line / 100)
if showTrendlines
solid_end_x = n
solid_end_y = upper
dotted_end_x = solid_end_x + future_bars
dotted_end_y = solid_end_y + phslope * future_bars
bearish_solid_line = line.new(phx1, phy1, solid_end_x, solid_end_y, color=dnCss, style=LineStyleEnum1, width=lineThickness)
bearish_dotted_line = line.new(solid_end_x, solid_end_y, dotted_end_x, dotted_end_y, color=dnCss, style=LineStyleEnum2, width=lineThickness)
add_trendline(bearishSolidLines, bearish_solid_line, maxBearishCount)
add_trendline(bearishDottedLines, bearish_dotted_line, maxBearishCount)
extend_trendline(solid_end_x, solid_end_y, phslope, dnCss, LineStyleEnum2, lineThickness)
bearishSolidLine1 := bearish_solid_line
if showA
degree_label = label.new(phx1, phy1, text=str.tostring(angle) + "°", style=label.style_label_down, size=textSizeTL, color=color.rgb(255, 255, 255, 100), textcolor=angleTextColor)
add_label(bearishLabels, degree_label, maxBearishCount)
if not useAngleFilter or (math.abs(angle) > anglA and math.abs(angle) < anglB)
if showTrendlines
second_solid_line = line.new(phx1, phy1 * (1 + percent_from_first_line / 100), n, secondUpper, color=dnCss, style=LineStyleEnum1, width=lineThickness)
second_dotted_line = line.new(n, secondUpper, n + future_bars, secondUpper + phslope * future_bars, color=dnCss, style=LineStyleEnum2, width=lineThickness)
add_trendline(bearishSolidLines, second_solid_line, maxBearishCount)
add_trendline(bearishDottedLines, second_dotted_line, maxBearishCount)
extend_trendline(n, secondUpper, phslope, dnCss, LineStyleEnum2, lineThickness)
bearishSolidLine2 := second_solid_line
if showA
degree_label = label.new(phx1, phy1 * (1 + percent_from_first_line / 100), text=str.tostring(angle) + "°", style=label.style_label_down, size=textSizeTL, color=color.rgb(255, 255, 255, 100), textcolor=color.rgb(255, 255, 255, 100))
add_label(bearishLabels, degree_label, maxBearishCount)
phy1 := ph
phx1 := n - lengthTL
upper += phslope
plotH := not na(ph) and ta.change(phslope) ? na : close[1] > upper[1] ? na : upper
bs_H := ta.barssince(na(plotH))
if not na(pl)
if pl > ply1
[normalised_slope, slope, angle] = calculate_slope(plx1, n-lengthTL, ply1, pl)
testLine.set_xy1(plx1, ply1)
testLine.set_xy2(n, pl + slope * lengthTL)
src = close
max_bars_back(src, 2000)
isOnL := false
broken = false
if not useAngleFilter or (angle > anglA and angle < anglB)
if not broken
plslope := slope
isOnL := true
lower := pl + slope * lengthTL
secondLower := lower * (1 - percent_from_first_line / 100)
if showTrendlines
solid_end_x = n
solid_end_y = lower
dotted_end_x = solid_end_x + future_bars
dotted_end_y = solid_end_y + plslope * future_bars
bullish_solid_line = line.new(plx1, ply1, solid_end_x, solid_end_y, color=upCss, style=LineStyleEnum1, width=lineThickness)
bullish_dotted_line = line.new(solid_end_x, solid_end_y, dotted_end_x, dotted_end_y, color=upCss, style=LineStyleEnum2, width=lineThickness)
add_trendline(bullishSolidLines, bullish_solid_line, maxBullishCount)
add_trendline(bullishDottedLines, bullish_dotted_line, maxBullishCount)
extend_trendline(solid_end_x, solid_end_y, plslope, upCss, LineStyleEnum2, lineThickness)
bullishSolidLine1 := bullish_solid_line
if showA
degree_label = label.new(plx1, ply1, text=str.tostring(angle) + "°", style=label.style_label_up, size=textSizeTL, color=color.rgb(255, 255, 255, 100), textcolor=angleTextColor)
add_label(bullishLabels, degree_label, maxBullishCount)
if not useAngleFilter or (angle > anglA and angle < anglB)
if showTrendlines
second_solid_line = line.new(plx1, ply1 * (1 - percent_from_first_line / 100), n, secondLower, color=upCss, style=LineStyleEnum1, width=lineThickness)
second_dotted_line = line.new(n, secondLower, n + future_bars, secondLower + plslope * future_bars, color=upCss, style=LineStyleEnum2, width=lineThickness)
add_trendline(bullishSolidLines, second_solid_line, maxBullishCount)
add_trendline(bullishDottedLines, second_dotted_line, maxBullishCount)
extend_trendline(n, secondLower, plslope, upCss, LineStyleEnum2, lineThickness)
bullishSolidLine2 := second_solid_line
if showA
degree_label = label.new(plx1, ply1 * (1 - percent_from_first_line / 100), text=str.tostring(angle) + "°", style=label.style_label_up, size=textSizeTL, color=color.rgb(255, 255, 255, 100), textcolor=color.rgb(255, 255, 255, 100))
add_label(bullishLabels, degree_label, maxBullishCount)
ply1 := pl
plx1 := n - lengthTL
lower += plslope
plotL := not na(pl) and ta.change(plslope) ? na : close[1] < lower[1] ? na : lower
bs_L := ta.barssince(na(plotL))
if array.size(bearishSolidLines) > 0 and array.size(bearishDottedLines) > 0
draw_trendlines(bearishSolidLines, bearishDottedLines, bearishLabels)
if array.size(bullishSolidLines) > 0 and array.size(bullishDottedLines) > 0
draw_trendlines(bullishSolidLines, bullishDottedLines, bullishLabels)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------- MARKET STRUCTURE CALCULATIONS & FUNCTION ------------------------------------//
//------------------------------------------------------------------------------------------------------------------------------------------------------//
// Market Structure Function
internalLength := na(internalLength) ? 10 : internalLength
externalLength := na(externalLength) ? 50 : externalLength
showInternalMS = (length_option == "INTERNAL" or length_option == "ALL" or length_option == "CUSTOM") and length_option != "NONE"
showExternalMS = (length_option == "EXTERNAL" or length_option == "ALL" or length_option == "CUSTOM") and length_option != "NONE"
calculate_swing_points(length)=>
var prev = 0
prev := high[length] > ta.highest(length) ? 0 : low[length] < ta.lowest(length) ? 1 : prev[1]
t = prev == 0 and prev[1] != 0 ? high[length] : 0
b = prev == 1 and prev[1] != 1 ? low[length] : 0
[t, b]
bosConfType = 'Candle High'
CHOCH = true
pivot_high_found = ta.pivothigh(high, swingSize_swing, swingSize_swing)
pivot_low_found = ta.pivotlow(low, swingSize_swing, swingSize_swing)
var float prevHigh_s = na, var float prevLow_s = na, var int prevHighIndex_s = na, var int prevLowIndex_s = na
bool higher_highs = false, bool lower_highs = false, bool higher_lows = false, bool lower_lows = false
var int prevSwing_s = 0
if not na(pivot_high_found)
if na(prevHigh_s) or pivot_high_found > prevHigh_s
higher_highs := true
lower_highs := false
prevSwing_s := 2
else
higher_highs := false
lower_highs := true
prevSwing_s := 1
prevHigh_s := pivot_high_found
prevHighIndex_s := bar_index - swingSize_swing
if not na(pivot_low_found)
if na(prevLow_s) or pivot_low_found < prevLow_s
higher_lows := false
lower_lows := true
prevSwing_s := -2
else
higher_lows := true
lower_lows := false
prevSwing_s := -1
prevLow_s := pivot_low_found
prevLowIndex_s := bar_index - swingSize_swing
if higher_highs and showSwing
label.new(bar_index - swingSize_swing, pivot_high_found, 'HH', color=CLEAR, style=label.style_label_down, textcolor=swingColor, size=label_size_swing)
if lower_highs and showSwing
label.new(bar_index - swingSize_swing, pivot_high_found, 'LH', color=CLEAR, style=label.style_label_down, textcolor=swingColor, size=label_size_swing)
if higher_lows and showSwing
label.new(bar_index - swingSize_swing, pivot_low_found, 'HL', color=CLEAR, style=label.style_label_up, textcolor=swingColor, size=label_size_swing)
if lower_lows and showSwing
label.new(bar_index - swingSize_swing, pivot_low_found, 'LL', color=CLEAR, style=label.style_label_up, textcolor=swingColor, size=label_size_swing)
// EQH & EQL //
atrEQ = ta.atr(200)
var float high_eqh = na, var float low_eqh = na
var high_eqh_pre = 0., var eq_top_x = 0, var low_eqh_pre = 0., var eq_btm_x = 0
if show_equal_highlow
high_eqh := ta.pivothigh(length_eqh, length_eqh)
low_eqh := ta.pivotlow(length_eqh, length_eqh)
if not na(low_eqh)
if math.min(low_eqh, low_eqh_pre) > math.max(low_eqh, low_eqh_pre) - atrEQ * eq_threshold
eql_line = line.new(eq_btm_x, low_eqh_pre, n-length_eqh, low_eqh, color=eq_bull_color, style=line.style_dotted)
eql_lbl = label.new(int(math.avg(n-length_eqh, eq_btm_x)), low_eqh, 'EQL', color=#00000000, textcolor=eq_bull_color, style=label.style_label_up, size=label_size_Equal)
alert("EQL found at " + str.tostring(low_eqh), alert.freq_once_per_bar)
low_eqh_pre := low_eqh
eq_btm_x := n-length_eqh
if not na(high_eqh)
if math.max(high_eqh, high_eqh_pre) < math.min(high_eqh, high_eqh_pre) + atrEQ * eq_threshold
eqh_line = line.new(eq_top_x, high_eqh_pre, n-length_eqh, high_eqh, color=eq_bear_color, style=line.style_dotted)
eqh_lbl = label.new(int(math.avg(n-length_eqh, eq_top_x)), high_eqh, 'EQH', color=#00000000, textcolor=eq_bear_color, style=label.style_label_down, size=label_size_Equal)
alert("EQH found at " + str.tostring(high_eqh), alert.freq_once_per_bar)
high_eqh_pre := high_eqh
eq_top_x := n-length_eqh
[high_ms, low_ms] = calculate_swing_points(externalLength)
n := bar_index
// HL OUTPUT FUNCTION //
hl() => [high, low]
var float thold = (ta.highest(300) - ta.lowest(300)) * math.max(0.5, 0.1) / 100.
[int_high_ms, int_low_ms] = calculate_swing_points(internalLength)
if low_ms
crossed_down := true
y_dn := low_ms
x_dn := n - externalLength
if high_ms
crossed_up := true
y_up := high_ms
x_up := n - externalLength
if int_low_ms
internal_dn_broke := true
internal_y_dn := int_low_ms
internal_x_dn := n - internalLength
if int_high_ms
internal_up_broke := true
internal_y_up := int_high_ms
internal_x_up := n - internalLength
bull_CHOCH = false, bull_CHOCH_ = false, bull_bos = false, bull_bos_ = false, bear_CHOCH = false, bear_CHOCH_ = false, bear_bos = false, bear_bos_ = false
if ta.crossover(close, internal_y_up) and internal_up_broke and y_up != internal_y_up
bool MSS = na
CHOCH := int_t_MS < 0
internal_up_broke := false
int_t_MS := 1
bull_CHOCH := CHOCH ? true : false
bull_bos := CHOCH ? false : true
if showInternalMS
Show_MS(internal_x_up, internal_y_up, CHOCH ? 'CHOCH' : 'BOS', internalBullColor, true, true, label_size_Internal_s)
if ta.crossunder(close, internal_y_dn) and internal_dn_broke and y_dn != internal_y_dn
bool MSS = false
CHOCH := int_t_MS > 0
internal_dn_broke := false
int_t_MS := -1
bear_CHOCH := CHOCH ? true : false
bear_bos := CHOCH ? false : true
if showInternalMS
Show_MS(internal_x_dn, internal_y_dn, CHOCH ? 'CHOCH' : 'BOS', internalBearColor, true, false, label_size_Internal_s)
if ta.crossover(close, y_up) and crossed_up
bool MSS = na
MSS := t_MS < 0
crossed_up := false
t_MS := 1
bull_CHOCH_ := MSS ? true : false
bull_bos_ := MSS ? false : true
if showExternalMS
Show_MS(x_up, y_up, MSS ? 'CHOCH+' : 'BOS+', externalBullColor, false, true, label_size_External_s)
if ta.crossunder(close, y_dn) and crossed_down
bool MSS = na
MSS := t_MS > 0
crossed_down := false
t_MS := -1
bear_CHOCH_ := MSS ? true : false
bear_bos_ := MSS ? false : true
if showExternalMS
Show_MS(x_dn, y_dn, MSS ? 'CHOCH+' : 'BOS+', externalBearColor, false, false, label_size_External_s)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------- ALERTS ---------------------------------------------------------------------//
//------------------------------------------------------------------------------------------------------------------------------------------------------///
// ALERTS OB & BB
// Predefined alert messages with placeholders
const string bullishOBMessage = "{{exchange}}:{{ticker}} New Bullish Order Block detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}"
const string bearishOBMessage = "{{exchange}}:{{ticker}} New Bearish Order Block detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}"
const string bullishBBMessage = "{{exchange}}:{{ticker}} New Bullish Breaker Block detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}"
const string bearishBBMessage = "{{exchange}}:{{ticker}} New Bearish Breaker Block detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}"
const string bullishOBTouchedMessage = "{{exchange}}:{{ticker}} Bullish Order Block Touched detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}"
const string bearishOBTouchedMessage = "{{exchange}}:{{ticker}} Bearish Order Block Touched detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}"
const string bullishBBTouchedMessage = "{{exchange}}:{{ticker}} Bullish Breaker Block Touched detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}"
const string bearishBBTouchedMessage = "{{exchange}}:{{ticker}} Bearish Breaker Block Touched detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}"
// Alert for new bullish order block
alertcondition(condition = bullish_OB_Break, title = "New Bullish Order Block", message = bullishOBMessage)
// Alert for new bearish order block
alertcondition(condition = bearish_OB_Break, title = "New Bearish Order Block", message = bearishOBMessage)
// Detecting bullish and bearish breaker blocks
bullishBreakerCreated = ta.crossover(high, ta.highest(high, 10))
bearishBreakerCreated = ta.crossunder(low, ta.lowest(low, 10))
// Alert for new bullish breaker block
alertcondition(condition = bullishBreakerCreated, title = "New Bullish Breaker Block", message = bullishBBMessage)
// Alert for new bearish breaker block
alertcondition(condition = bearishBreakerCreated, title = "New Bearish Breaker Block", message = bearishBBMessage)
// Conditions for touching OBs and BBs
bullishOBTouched = ta.crossover(close, high)
bearishOBTouched = ta.crossunder(close, low)
// Alert for bullish order block touched
alertcondition(condition = bullishOBTouched, title = "Bullish Order Block Touched", message = bullishOBTouchedMessage)
// Alert for bearish order block touched
alertcondition(condition = bearishOBTouched, title = "Bearish Order Block Touched", message = bearishOBTouchedMessage)
// Conditions for touching BBs
bullishBBTouched = ta.crossover(close, high)
bearishBBTouched = ta.crossunder(close, low)
// Alert for bullish breaker block touched
alertcondition(condition = bullishBBTouched, title = "Bullish Breaker Block Touched", message = bullishBBTouchedMessage)
// Alert for bearish breaker block touched
alertcondition(condition = bearishBBTouched, title = "Bearish Breaker Block Touched", message = bearishBBTouchedMessage)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ALERTS Liquidity Levels
alertcondition(pivotHighHTF, title="TF #1 Buy Side 💲 Detected", message="{{exchange}}:{{ticker}}, Buy Side 💲 Detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(pivotLowHTF, title="TF #1 Sell Side 💲 Detected", message="{{exchange}}:{{ticker}}, Sell Side 💲 Detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(tf1_buy_side_liquidity_break, title="TF #1 Buy Side 💲 Break", message="{{exchange}}:{{ticker}}, Buy Side 💲 Break on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(tf1_sell_side_liquidity_break, title="TF #1 Sell Side 💲 Break", message="{{exchange}}:{{ticker}}, Sell Side 💲 Break on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(tf1_buy_side_liquidity_touch, title="TF #1 Buy Side 💲 Touch", message="{{exchange}}:{{ticker}}, Buy Side 💲 Touch on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(tf1_sell_side_liquidity_touch, title="TF #1 Sell Side 💲 Touch", message="{{exchange}}:{{ticker}}, Sell Side 💲 Touch on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FVG ALERTS
if show_fvg and is_newbar(i_tf) and (i_mtf == "Current + HTF" or i_mtf == "HTF") and barstate.isconfirmed
fvg_gap:=check_fvg_func(sClose,htfH,sHighP2,htfL,sLowP2,sOpen,time[2],true)
// Alerts for bullish FVG detection
alertcondition(fvg_gap == 1, title="Bullish FVG Detected", message="{{exchange}}:{{ticker}}, Bullish FVG Detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}, FVG Indicator")
// Alerts for bearish FVG detection
alertcondition(fvg_gap == -1, title="Bearish FVG Detected", message="{{exchange}}:{{ticker}}, Bearish FVG Detected on SMC by WeloTrades, price = {{close}}, volume = {{volume}}, FVG Indicator")
// Alerts for bullish FVG break
alertcondition(fvg_removed == 1, title="Bullish FVG Break", message="{{exchange}}:{{ticker}}, Bullish FVG Break on SMC by WeloTrades, price = {{close}}, volume = {{volume}}, FVG Indicator")
// Alerts for bearish FVG break
alertcondition(fvg_removed == -1, title="Bearish FVG Break", message="{{exchange}}:{{ticker}}, Bearish FVG Break on SMC by WeloTrades, price = {{close}}, volume = {{volume}}, FVG Indicator")
// Alerts for bullish FVG touch
alertcondition(fvg_gap == 1 and (mittigation_filt_fvg == 'Touch' or mittigation_filt_fvg == 'Wicks' or mittigation_filt_fvg == 'Close' or mittigation_filt_fvg == 'Average'), title="Bullish FVG Touch", message="{{exchange}}:{{ticker}}, Bullish FVG Touch on SMC by WeloTrades, price = {{close}}, volume = {{volume}}, FVG Indicator")
// Alerts for bearish FVG touch
alertcondition(fvg_gap == -1 and (mittigation_filt_fvg == 'Touch' or mittigation_filt_fvg == 'Wicks' or mittigation_filt_fvg == 'Close' or mittigation_filt_fvg == 'Average'), title="Bearish FVG Touch", message="{{exchange}}:{{ticker}}, Bearish FVG Touch on SMC by WeloTrades, price = {{close}}, volume = {{volume}}, FVG Indicator")
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ALERTS TRENDLINES
const string bearishTrendlineMadeMessage = "{{exchange}}:{{ticker}}, (Bearish Trendline Made) on: Trend Lines By WeloTrades! price = {{close}}, volume = {{volume}}"
const string bullishTrendlineMadeMessage = "{{exchange}}:{{ticker}}, (Bullish Trendline Made) on: Trend Lines By WeloTrades! price = {{close}}, volume = {{volume}}"
const string bearishTrendlineBrokenMessage = "{{exchange}}:{{ticker}}, (Bearish Trendline Broken) on: Trend Lines By WeloTrades! price = {{close}}, volume = {{volume}}"
const string bullishTrendlineBrokenMessage = "{{exchange}}:{{ticker}}, (Bullish Trendline Broken) on: Trend Lines By WeloTrades! price = {{close}}, volume = {{volume}}"
const string bearishTrendlineTouchedMessage = "{{exchange}}:{{ticker}}, (Bearish Trendline Touched) on: Trend Lines By WeloTrades! price = {{close}}, volume = {{volume}}"
const string bullishTrendlineTouchedMessage = "{{exchange}}:{{ticker}}, (Bullish Trendline Touched) on: Trend Lines By WeloTrades! price = {{close}}, volume = {{volume}}"
// Alert conditions for trendlines made
alertcondition(not na(ph), title="Bearish Trendline Made", message=bearishTrendlineMadeMessage)
alertcondition(not na(pl), title="Bullish Trendline Made", message=bullishTrendlineMadeMessage)
// Alert conditions for trendlines broken
alertcondition(ta.cross(close, plotH), title="Bearish Trendline Broken", message=bearishTrendlineBrokenMessage)
alertcondition(ta.cross(close, plotL), title="Bullish Trendline Broken", message=bullishTrendlineBrokenMessage)
// Alert conditions for trendlines touched
bearishTrendlineTouched = not na(ta.valuewhen(ta.cross(close, plotH), close, 0))
bullishTrendlineTouched = not na(ta.valuewhen(ta.cross(close, plotL), close, 0))
alertcondition(bearishTrendlineTouched, title="Bearish Trendline Touched", message=bearishTrendlineTouchedMessage)
alertcondition(bullishTrendlineTouched, title="Bullish Trendline Touched", message=bullishTrendlineTouchedMessage)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Alerts for Market Structure Changes
alertcondition(bull_CHOCH, "Bullish CHOCH", "{{exchange}}:{{ticker}}, 'Bullish CHOCH' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(bear_CHOCH, "Bearish CHOCH", "{{exchange}}:{{ticker}}, 'Bearish CHOCH' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(bull_CHOCH_, "Bullish CHOCH+", "{{exchange}}:{{ticker}}, 'Bullish CHOCH+' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(bear_CHOCH_, "Bearish CHOCH+", "{{exchange}}:{{ticker}}, 'Bearish CHOCH+' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(bull_bos, "Bullish BOS", "{{exchange}}:{{ticker}}, 'Bullish BOS' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(bear_bos, "Bearish BOS", "{{exchange}}:{{ticker}}, 'Bearish BOS' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(bear_bos_, "Bearish BOS+", "{{exchange}}:{{ticker}}, 'Bearish BOS+' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(bull_bos_, "Bullish BOS+", "{{exchange}}:{{ticker}}, 'Bullish BOS+' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
// Alerts for EQH & EQL
alertcondition(not na(high_eqh), "Equal Highs", "{{exchange}}:{{ticker}}, 'EQH' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(not na(low_eqh), "Equal Lows", "{{exchange}}:{{ticker}}, 'EQL' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
// Alerts for Swing Points
alertcondition(higher_highs and showSwing , "Higher High (HH)", "{{exchange}}:{{ticker}}, 'HH' found on on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(lower_highs and showSwing , "Lower High (LH)", "{{exchange}}:{{ticker}}, 'LH' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(higher_lows and showSwing , "Higher Low (HL)", "{{exchange}}:{{ticker}}, 'HL' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
alertcondition(lower_lows and showSwing , "Lower Low (LL)", "{{exchange}}:{{ticker}}, 'LL' found on SMC by WeloTrades, price = {{close}}, volume = {{volume}}")
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////