// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ //@version=4 //@author=LucF // Delta Volume Candles [LucF] // v7.0, 2021.05.15 09:35 — LucF // This indicator plots replacement candles colored using delta volume calculated with intrabar information. // It can also help visualize delta volume by appending top and bottom segments to candles and plotting their averages. // This code was written using the following standards: // • PineCoders Coding Conventions for Pine: http://www.pinecoders.com/coding_conventions/ // • A modified version of the PineCoders 16-Color Gradient Framework: https://www.tradingview.com/script/EjLGV9qg-Color-Gradient-16-colors-Framework-PineCoders-FAQ/ // • Some functions from the PineCoders MTF Selection Framework: https://www.tradingview.com/script/90mqACUV-MTF-Selection-Framework-PineCoders-FAQ/ // Part of this code is borrowed from a comment by Kuan to a BacktestRookies presentation of an intrabar delta volume indicator here: https://backtest-rookies.com/2019/02/15/tradingview-volume-profile-with-lower-time-frame-data/ // My indicator displaying Delta Volume Columns using the same method of calculation is here: https://www.tradingview.com/script/YFBNr8I6-Delta-Volume-Columns-LucF/ // This indicator's page on TV: https://www.tradingview.com/script/h0yZPTiS-Delta-Volume-Candles-LucF/ study("Delta Volume Candles [LucF]", "Delta Volume Candles", true, max_labels_count = 500, linktoseries = true) // ———————————————————— Inputs // { string ON = "On", string OFF = "Off" string GP1 = "Display", string GP2 = "Settings", string GP3 = "Markers" C00 = "None", C01 = "Aqua", C02 = "Blue", C03 = "Coral", C04 = "Gold", C05 = "Gray", C06 = "Green", C07 = "Lime", C08 = "Maroon", C09 = "Orange", C10 = "Pink", C11 = "Red", C12 = "Violet", C13 = "Yellow" BW1 = "None", BW2 = "Bright", BW3 = "Dark" CB0 = "None", CB1 = "Chart Background", CB2 = "Price", CB3 = "Volume Balance on Bar", CB4 = "Volume Balance Average", CB5 = "Volume Balance Average — Gradient", CB6 = "Volume Balance Momentum", CB7 = "Volume Balance Momentum — Gradient" TB1 = "None", TB2 = "Volume Balance on Bar", TB3 = "Volume Balance Momentum" HL0 = "Full Range", HL1 = "Top and Bottom", HL2= "Open and Close", HL3 = "High and Low" DV0 = "Range: Full", DV1 = "Range: Top to Bottom", DV2= "Range: Open to Close", DV3 = "Range: High to Low", DV4 = "Level: Top or Bottom", DV5 = "Level: High or Low", DV6 = "Level: Close" TF1 = "Fast Auto-Steps (1min, 5min, 15min, 60min, 1D)", TF2 = "More Precise Auto-Steps (1min, 5min, 30min, 1D)", TF3 = "Fixed" MD1 = "Both", MD2 = "Longs Only", MD3 = "Shorts Only" _1 = input(true, "════════════ Candles ══════════════") bodiesMode = input(CB6, "Color calculation", options = [CB1, CB2, CB3, CB4, CB5, CB6, CB7]) bodyColorBull = input(C06, "Bull Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) bodyColorBear = input(C08, "Bear Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) bodyFillBrightness = input(16, "Brightness (1-16)", minval = 1, maxval = 16) * 0.625 borderWickDisplay = input(BW2, "Border and Wick Display", options = [BW1, BW2, BW3]) colorBodiesDivs = input(C13, "Divergences Color", options = [C00, C05, C09, C10, C13]) colorBodiesDivsBr = input(16, "Divergences Brightness", minval = 1, maxval = 16) * 0.625 hollowOutBodies = input(true, "Empty bodies on decreasing volume") _2 = input(true, "═══════════ Tops/Bottoms ═══════════") topBotMode = input(TB2, "Mode", options = [TB1, TB2, TB3]) topColorBull = input(C07, "Bull Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) botColorBear = input(C11, "Bear Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) topBotFillBright = input(7, "Dominant Volume Fill Brightness", minval = 1, maxval = 16) * 0.625 colorTopsBotsDivs = input(C13, "Divergences Color", options = [C00, C05, C09, C10, C13]) colorTopsBotsDivsBr = input(13, "Divergences Brightness", minval = 1, maxval = 16) * 0.625 _3 = input(true, "═══════════ Top/Bottom MAs ══════════") maMode = input(TB1, "Mode", options = [TB1, TB2, TB3]) colorMaTops = input(C06, "Bull Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) colorMaBots = input(C08, "Bear Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) topBotMasBrightness = input(10, "Brightness", minval = 1, maxval = 16) * 0.625 fillMas = input(true, "Fill MAs With Markers Bias") bgOnMarkerBias = input(false, "Fill Background With Markers Bias") _4 = input(true, "══════════ Divergence Levels ══════════") divLevelsMode = input(CB6, "Mode", options = [CB0, CB3, CB4, CB6]) divLevelsModeHiLo = input(HL2, "Hi/Lo Levels", options = [HL0, HL1, HL2, HL3]) divLevelsModeHiLoRef= input(DV2, "Breach Reference", options = [DV0, DV1, DV2, DV3, DV4, DV5, DV6]) colordivLevelsBull = input(C06, "Bull Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) colordivLevelsBear = input(C08, "Bear Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) colordivLevelsNeut = input(C05, "Neutral Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) filldivLevels = input(false, "Fill Levels") divLevelsBrightness = input(10, "Brightness", minval = 1, maxval = 16) * 0.625 _5 = input(true, "═════════ Intrabar Resolution ══════════") itfType = input(TF1, "Selection", options = [TF1, TF2, TF3]) itfTypeFixedRes = input("15", "  Fixed Resolution", type = input.resolution) itfShow = input(true, "Show Resolution") offsetLabels = input(3, "  Label Horizontal Offset") _6 = input(true, "═══════ Total Volume Discrepancies ═══════") bgColor = input(C00, "Background Color", options = [C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10, C11, C12, C13]) bgBrightness = input(1, "Background Brightness", minval = 1, maxval = 16) * 0.625 failureTolerance = input(1., "Failure Tolerance (%)", minval = 0., maxval = 50., step = 0.25) / 100 _7 = input(true, "════════════ Markers ══════════════") markerDirection = input(MD1, "Trade Direction", options = [MD1, MD2, MD3]) showMarker1 = input(false, "Marker 1: Bumps") showMarker2 = input(false, "Marker 2: Double Bumps") showMarker3 = input(false, "Marker 3: Divergence Confirmations") marker3Mode = input(CB6, "  Using...", options = [CB3, CB4, CB6]) showMarker4 = input(false, "Marker 4: Volume Balance Shifts") marker4Mode = input(CB6, "  Using...", options = [CB4, CB6]) showMarker5 = input(false, "Marker 5: Markers Bias Shifts") _8 = input(true, "════════════ Settings ══════════════") balAvgPeriod = input(30, "Volume Balance Average Period", minval = 2) balMomPeriod = input(14, "Volume Balance Momentum Period", minval = 2) topBotMasPeriod = input(10, "Tops/Bottoms MAs period", minval = 1) totalVolMaPeriod = input(20, "Total Volume MA Period", minval = 2) biasPeriod = input(10, "Markers Bias Period", minval = 2) bool i_realtimeMode = input(ON, "Realtime Mode", group = GP1, options = [OFF, ON], tooltip = "Enables a distinct calculation mode which works only on realtime bars and uses price and volume differences between realtime bar updates to determine Buy/Sell/Neutral volume.") == ON var longsOnly = markerDirection == MD2 var shortsOnly = markerDirection == MD3 // } // ———————————————————— Functions // { // ————— Returns 1 when boolean is true, 0 if false. f_01(_c) => _c ? 1 : 0 // —————————— Color // ————— Functions returning a color shade corresponding to one of 16 levels of intensity (>9.375 is brightest). f_c_aqua(_g) => _g > 9.375 ? #0080FFff : _g > 8.75 ? #0080FFef : _g > 8.125 ? #0080FFdf : _g > 7.5 ? #0080FFcf : _g > 6.875 ? #0080FFbf : _g > 6.25 ? #0080FFaf : _g > 5.625 ? #0080FF9f : _g > 5.0 ? #0080FF8f : _g > 4.375 ? #0080FF7f : _g > 3.75 ? #0080FF6f : _g > 3.125 ? #0080FF5f : _g > 2.5 ? #0080FF4f : _g > 1.875 ? #0080FF3f : _g > 1.25 ? #0080FF2f : _g > 0.625 ? #0080FF1f : #00C0FF10 f_c_blue(_g) => _g > 9.375 ? #013BCAff : _g > 8.75 ? #013BCAef : _g > 8.125 ? #013BCAdf : _g > 7.5 ? #013BCAcf : _g > 6.875 ? #013BCAbf : _g > 6.25 ? #013BCAaf : _g > 5.625 ? #013BCA9f : _g > 5.0 ? #013BCA8f : _g > 4.375 ? #013BCA7f : _g > 3.75 ? #013BCA6f : _g > 3.125 ? #013BCA5f : _g > 2.5 ? #013BCA4f : _g > 1.875 ? #013BCA3f : _g > 1.25 ? #013BCA2f : _g > 0.625 ? #013BCA1f : #013BCA10 f_c_coral(_g) => _g > 9.375 ? #FF8080ff : _g > 8.75 ? #FF8080ef : _g > 8.125 ? #FF8080df : _g > 7.5 ? #FF8080cf : _g > 6.875 ? #FF8080bf : _g > 6.25 ? #FF8080af : _g > 5.625 ? #FF80809f : _g > 5.0 ? #FF80808f : _g > 4.375 ? #FF80807f : _g > 3.75 ? #FF80806f : _g > 3.125 ? #FF80805f : _g > 2.5 ? #FF80804f : _g > 1.875 ? #FF80803f : _g > 1.25 ? #FF80802f : _g > 0.625 ? #FF80801f : #FF808010 f_c_gold(_g) => _g > 9.375 ? #CCCC00ff : _g > 8.75 ? #CCCC00ef : _g > 8.125 ? #CCCC00df : _g > 7.5 ? #CCCC00cf : _g > 6.875 ? #CCCC00bf : _g > 6.25 ? #CCCC00af : _g > 5.625 ? #CCCC009f : _g > 5.0 ? #CCCC008f : _g > 4.375 ? #CCCC007f : _g > 3.75 ? #CCCC006f : _g > 3.125 ? #CCCC005f : _g > 2.5 ? #CCCC004f : _g > 1.875 ? #CCCC003f : _g > 1.25 ? #CCCC002f : _g > 0.625 ? #CCCC001f : #CCCC0010 f_c_gray(_g) => _g > 9.375 ? #808080ff : _g > 8.75 ? #808080ef : _g > 8.125 ? #808080df : _g > 7.5 ? #808080cf : _g > 6.875 ? #808080bf : _g > 6.25 ? #808080af : _g > 5.625 ? #8080809f : _g > 5.0 ? #8080808f : _g > 4.375 ? #8080807f : _g > 3.75 ? #8080806f : _g > 3.125 ? #8080805f : _g > 2.5 ? #8080804f : _g > 1.875 ? #8080803f : _g > 1.25 ? #8080802f : _g > 0.625 ? #8080801f : #80808010 f_c_green(_g) => _g > 9.375 ? #008000ff : _g > 8.75 ? #008000ef : _g > 8.125 ? #008000df : _g > 7.5 ? #008000cf : _g > 6.875 ? #008000bf : _g > 6.25 ? #008000af : _g > 5.625 ? #0080009f : _g > 5.0 ? #0080008f : _g > 4.375 ? #0080007f : _g > 3.75 ? #0080006f : _g > 3.125 ? #0080005f : _g > 2.5 ? #0080004f : _g > 1.875 ? #0080003f : _g > 1.25 ? #0080002f : _g > 0.625 ? #0080001f : #00800010 f_c_lime(_g) => _g > 9.375 ? #00FF00ff : _g > 8.75 ? #00FF00ef : _g > 8.125 ? #00FF00df : _g > 7.5 ? #00FF00cf : _g > 6.875 ? #00FF00bf : _g > 6.25 ? #00FF00af : _g > 5.625 ? #00FF009f : _g > 5.0 ? #00FF008f : _g > 4.375 ? #00FF007f : _g > 3.75 ? #00FF006f : _g > 3.125 ? #00FF005f : _g > 2.5 ? #00FF004f : _g > 1.875 ? #00FF003f : _g > 1.25 ? #00FF002f : _g > 0.625 ? #00FF001f : #00FF0010 f_c_maroon(_g) => _g > 9.375 ? #800000ff : _g > 8.75 ? #800000ef : _g > 8.125 ? #800000df : _g > 7.5 ? #800000cf : _g > 6.875 ? #800000bf : _g > 6.25 ? #800000af : _g > 5.625 ? #8000009f : _g > 5.0 ? #8000008f : _g > 4.375 ? #8000007f : _g > 3.75 ? #8000006f : _g > 3.125 ? #8000005f : _g > 2.5 ? #8000004f : _g > 1.875 ? #8000003f : _g > 1.25 ? #8000002f : _g > 0.625 ? #8000001f : #80000010 f_c_orange(_g) => _g > 9.375 ? #FF8000ff : _g > 8.75 ? #FF8000ef : _g > 8.125 ? #FF8000df : _g > 7.5 ? #FF8000cf : _g > 6.875 ? #FF8000bf : _g > 6.25 ? #FF8000af : _g > 5.625 ? #FF80009f : _g > 5.0 ? #FF80008f : _g > 4.375 ? #FF80007f : _g > 3.75 ? #FF80006f : _g > 3.125 ? #FF80005f : _g > 2.5 ? #FF80004f : _g > 1.875 ? #FF80003f : _g > 1.25 ? #FF80002f : _g > 0.625 ? #FF80001f : #FF800010 f_c_pink(_g) => _g > 9.375 ? #FF0080ff : _g > 8.75 ? #FF0080ef : _g > 8.125 ? #FF0080df : _g > 7.5 ? #FF0080cf : _g > 6.875 ? #FF0080bf : _g > 6.25 ? #FF0080af : _g > 5.625 ? #FF00809f : _g > 5.0 ? #FF00808f : _g > 4.375 ? #FF00807f : _g > 3.75 ? #FF00806f : _g > 3.125 ? #FF00805f : _g > 2.5 ? #FF00804f : _g > 1.875 ? #FF00803f : _g > 1.25 ? #FF00802f : _g > 0.625 ? #FF00801f : #FF008010 f_c_red(_g) => _g > 9.375 ? #FF0000ff : _g > 8.75 ? #FF0000ef : _g > 8.125 ? #FF0000df : _g > 7.5 ? #FF0000cf : _g > 6.875 ? #FF0000bf : _g > 6.25 ? #FF0000af : _g > 5.625 ? #FF00009f : _g > 5.0 ? #FF00008f : _g > 4.375 ? #FF00007f : _g > 3.75 ? #FF00006f : _g > 3.125 ? #FF00005f : _g > 2.5 ? #FF00004f : _g > 1.875 ? #FF00003f : _g > 1.25 ? #FF00002f : _g > 0.625 ? #FF00001f : #FF000010 f_c_violet(_g) => _g > 9.375 ? #AA00FFff : _g > 8.75 ? #AA00FFef : _g > 8.125 ? #AA00FFdf : _g > 7.5 ? #AA00FFcf : _g > 6.875 ? #AA00FFbf : _g > 6.25 ? #AA00FFaf : _g > 5.625 ? #AA00FF9f : _g > 5.0 ? #AA00FF8f : _g > 4.375 ? #AA00FF7f : _g > 3.75 ? #AA00FF6f : _g > 3.125 ? #AA00FF5f : _g > 2.5 ? #AA00FF4f : _g > 1.875 ? #AA00FF3f : _g > 1.25 ? #AA00FF2f : _g > 0.625 ? #AA00FF1f : #AA00FF10 f_c_yellow(_g) => _g > 9.375 ? #FFFF00ff : _g > 8.75 ? #FFFF00ef : _g > 8.125 ? #FFFF00df : _g > 7.5 ? #FFFF00cf : _g > 6.875 ? #FFFF00bf : _g > 6.25 ? #FFFF00af : _g > 5.625 ? #FFFF009f : _g > 5.0 ? #FFFF008f : _g > 4.375 ? #FFFF007f : _g > 3.75 ? #FFFF006f : _g > 3.125 ? #FFFF005f : _g > 2.5 ? #FFFF004f : _g > 1.875 ? #FFFF003f : _g > 1.25 ? #FFFF002f : _g > 0.625 ? #FFFF001f : #FFFF0010 // —————————— Functions returning colors/brightnesses corresponding to user color selections. // ————— Returns color literal corresponding to color number and brightness level. f_color(_c, _g) => _c == C01 ? f_c_aqua(_g) : _c == C02 ? f_c_blue(_g) : _c == C03 ? f_c_coral(_g) : _c == C04 ? f_c_gold(_g) : _c == C05 ? f_c_gray(_g) : _c == C06 ? f_c_green(_g) : _c == C07 ? f_c_lime(_g) : _c == C08 ? f_c_maroon(_g) : _c == C09 ? f_c_orange(_g) : _c == C10 ? f_c_pink(_g) : _c == C11 ? f_c_red(_g) : _c == C12 ? f_c_violet(_g) : _c == C13 ? f_c_yellow(_g) : na // ————— Returns Bull/Bear candle color as per user choice. f_bodyColorBull(_g) => f_color(bodyColorBull, _g) f_bodyColorBear(_g) => f_color(bodyColorBear, _g) // ————— Returns Bull/Bear volume color as per user choice. f_volColorBull(_g) => f_color(topColorBull, _g) f_volColorBear(_g) => f_color(botColorBear, _g) // ————— Returns Body divergences color as per user choice. f_colorBodiesDivs(_g) => f_color(colorBodiesDivs, _g) // ————— Returns Tops/Bottoms divergences color as per user choice. f_colorTopsBotsDivs(_g) => f_color(colorTopsBotsDivs, _g) // ————— Returns Tops/Bottoms MA color as per user choice. f_colorMaH(_g) => f_color(colorMaTops, _g) f_colorMaL(_g) => f_color(colorMaBots, _g) // —————————— Gradient functions // ————— Returns a +10 to +0.001 or -10 to -0.001 gradient level out of 8 possible values, depending on whether _source is > or < _center. // • The level is determined by the number of advances/declines in the _source. // • When source rises/falls, the last calculated level increases/decreases by 1.25. f_gradientAdv(_source, _center) => // _source : input signal // _center : centerline used to determine if signal is bullwish/bearish. var _gradient = 0. _xUp = crossover(_source, _center) _xDn = crossunder(_source, _center) _up = change(_source) > 0 _dn = change(_source) < 0 _gradient := _source > _center ? _xUp ? 0.001 : _up ? min(10, _gradient + 1.25) : _dn ? max( 0.001, _gradient - 1.25) : _gradient : _source < _center ? _xDn ? -0.001 : _up ? min(-0.001, _gradient + 1.25) : _dn ? max(-10, _gradient - 1.25) : _gradient : _gradient // ————— Returns a color determined by: // 1. A selection between 2 colors on whether the source signal is above/below the centerline. // 2. The gradient level returned from the call to the "f_gradientAdv()" function. f_colorGradientAdv(_source, _center) => // _source : input signal // _center : centerline used to determine if signal is bullwish/bearish. _gradient = f_gradientAdv(_source, _center) var color _return = na _return := _gradient > 0 ? f_bodyColorBull(_gradient) : _gradient < 0 ? f_bodyColorBear(- _gradient) : _return f_colorGradientAdvMaFill(_source, _center) => // _source : input signal // _center : centerline used to determine if signal is bullwish/bearish. _gradient = f_gradientAdv(_source, _center) var color _return = na _return := _gradient > 0 ? f_colorMaH(_gradient) : _gradient < 0 ? f_colorMaL(- _gradient) : _return // —————————— Intrabar TF selection. // ————— Converts current "timeframe.multiplier" plus the TF into minutes of type float. f_resInMinutes() => _resInMinutes = timeframe.multiplier * ( timeframe.isseconds ? 1. / 60. : timeframe.isminutes ? 1. : timeframe.isdaily ? 1440. : timeframe.isweekly ? 10080. : timeframe.ismonthly ? 43800. : na) // ————— Returns resolution of _resolution period in minutes. f_tfResInMinutes(_res) => // _res: resolution of any TF (in "timeframe.period" string format). security(syminfo.tickerid, _res, f_resInMinutes()) // ————— Given current resolution, returns next step of HTF (faster version with coarser intrabar resolutions). f_resNextStepFast(_res) => // _res: current TF in fractional minutes. _res >= 60 * 24 * 7 ? "D" : _res >= 60 * 24 ? "60" : _res >= 60 * 6 ? "15" : _res >= 60 ? "5" : "1" // ————— Given current resolution, returns next step of HTF (slower version with finer intrabar resolutions). f_resNextStepPrecise(_res) => // _res: current TF in fractional minutes. _res >= 60 * 24 * 7 ? "D" : _res >= 60 * 24 ? "30" : _res >= 60 ? "5" : "1" // ————— Print a label at end of chart. f_htfLabel(_txt, _y, _color, _offsetLabels) => _t = int(time + (time - time[1]) * _offsetLabels) // Create the label on the dataset's first bar. var _lbl = label.new(_t, _y, _txt, xloc.bar_time, yloc.price, #00000000, label.style_none, color.gray, size.large) if barstate.islast // Rather than delete and recreate the label on every realtime bar update, update the label's information; it's more efficient. label.set_xy(_lbl, _t, _y) label.set_text(_lbl, _txt) label.set_textcolor(_lbl, _color) // ————— Function appends `_text` to `_msg` when `_cond` is true. f_addTextIf(_cond, _msg, _text) => _cond ? _msg + (_msg != "" ? "\n" : "") + _text : _msg // —————————— Intrabar volume. // These 3 functions and their calling code constitute the code reused from Kuan. Even though each function is called only once per current chart bar, once it is transported to the lower TF by the `security()` function, // it is executed once per intrabar in the dilation, starting from the earliest. The `security()` function thus handles the function similarly to how Pine's runtime environment handles a normal script, // but only for the number of intrabars in the dilation of the chart's resolution into intrabar resolution. Note that the number of bars in the dilation may be irregular (at 60min on chart, there will not always be 60 1min intrabars). // Thx to @theheirophant for working with me in figuring out how this works, and to Alex K. for confirming it. // ————— Neutral volume. f_getVolNeutral(_tf) => // Add intrabar volume when open == close. var float _vol = na if change(time(_tf)) // First intrabar detected: reset volume. _vol := open == close ? volume : 0 else // On all other intrabars than the first, add volume conditionally. _vol := _vol + (open == close ? volume : 0) _vol // ————— Buy volume. f_getVolBuy(_tf) => // Add intrabar volume when open < close. var float _vol = na if change(time(_tf)) // First intrabar detected: reset volume. _vol := open < close ? volume : 0 else // On all other intrabars than the first, add volume conditionally. _vol := _vol + (open < close ? volume : 0) _vol // ————— Sell volume. f_getVolSell(_tf) => // Add intrabar volume when open > close. var float _vol = na if change(time(_tf)) // First intrabar detected: reset volume. _vol := open > close ? volume : 0 else // On all other intrabars than the first, add volume conditionally. _vol := _vol + (open > close ? volume : 0) _vol // } // ———————————————————— Calculations // { // —————————— Fetch volume information. // ————— Determine intrabar resolution. var resInMinutes = f_resInMinutes() var lowerRes = itfType == TF1 ? f_resNextStepFast(resInMinutes) : itfType == TF2 ? f_resNextStepPrecise(resInMinutes) : itfTypeFixedRes var resNotSupported = not (resInMinutes == 43800 or resInMinutes == 10080 or resInMinutes == 1440 or resInMinutes == 720 or resInMinutes == 360 or resInMinutes == 240 or resInMinutes == 120 or resInMinutes == 60 or resInMinutes == 30 or resInMinutes == 15 or resInMinutes == 10 or resInMinutes == 5) // ————— Print label on error or to show intrabar res. if resNotSupported f_htfLabel("Unsupported\nchart resolution.", sma(high, 10)[1], color.silver, offsetLabels) else if resInMinutes <= f_tfResInMinutes(lowerRes) f_htfLabel("Chart\nresolution\nmust be > " + lowerRes, sma(high, 10)[1], color.silver, offsetLabels) else // Show calculated intrabar res when needed. if itfShow f_htfLabel(lowerRes, sma(high + 3 * tr, 10)[1], color.silver, offsetLabels) // ————— Fetch intrabar neutral/buy/sell volume. f_nv(_curRes) => security(syminfo.tickerid, lowerRes, f_getVolNeutral(_curRes)) f_bv(_curRes) => security(syminfo.tickerid, lowerRes, f_getVolBuy(_curRes)) f_sv(_curRes) => security(syminfo.tickerid, lowerRes, f_getVolSell(_curRes)) // ————— For realtime bars, calculate buy/sell/neutral volume on the fly, without using intrabars. // ————— Function returning, during realtime bars only, up, down and neutral volume determined by the movement of price between data feed updates. f_upDnNtVolume() => varip float _prevClose = open varip float _prevVolume = 0. varip float _volUp = 0. varip float _volDn = 0. varip float _volNt = 0. if barstate.isnew _volUp := 0. _volDn := 0. _volNt := 0. _prevClose := nz(close[1]) _prevVolume := 0. // Add this update's volume to the proper up/dn/nt slot, as per movement of price since the last update. float _newVolume = volume - _prevVolume if close > _prevClose _volUp += _newVolume else if close < _prevClose _volDn += _newVolume else _volNt += _newVolume _prevClose := close _prevVolume := volume [_volUp, _volDn, _volNt] [rtVolUp, rtVolDn, rtVolNt] = f_upDnNtVolume() // Only fetch volume if we are plotting bars. volBuy = barstate.isrealtime ? rtVolUp : timeframe.period == "M" ? f_bv("M" ) : timeframe.period == "W" ? f_bv("W" ) : timeframe.period == "D" ? f_bv("D" ) : timeframe.period == "720" ? f_bv("720") : timeframe.period == "360" ? f_bv("360") : timeframe.period == "240" ? f_bv("240") : timeframe.period == "120" ? f_bv("120") : timeframe.period == "60" ? f_bv("60" ) : timeframe.period == "30" ? f_bv("30" ) : timeframe.period == "15" ? f_bv("15" ) : timeframe.period == "10" ? f_bv("10" ) : timeframe.period == "5" ? f_bv("5" ) : 0 volSell = barstate.isrealtime ? rtVolDn : timeframe.period == "M" ? f_sv("M" ) : timeframe.period == "W" ? f_sv("W" ) : timeframe.period == "D" ? f_sv("D" ) : timeframe.period == "720" ? f_sv("720") : timeframe.period == "360" ? f_sv("360") : timeframe.period == "240" ? f_sv("240") : timeframe.period == "120" ? f_sv("120") : timeframe.period == "60" ? f_sv("60" ) : timeframe.period == "30" ? f_sv("30" ) : timeframe.period == "15" ? f_sv("15" ) : timeframe.period == "10" ? f_sv("10" ) : timeframe.period == "5" ? f_sv("5" ) : 0 volNeutral = barstate.isrealtime ? rtVolNt : timeframe.period == "M" ? f_nv("M" ) : timeframe.period == "W" ? f_nv("W" ) : timeframe.period == "D" ? f_nv("D" ) : timeframe.period == "720" ? f_nv("720") : timeframe.period == "360" ? f_nv("360") : timeframe.period == "240" ? f_nv("240") : timeframe.period == "120" ? f_nv("120") : timeframe.period == "60" ? f_nv("60" ) : timeframe.period == "30" ? f_nv("30" ) : timeframe.period == "15" ? f_nv("15" ) : timeframe.period == "10" ? f_nv("10" ) : timeframe.period == "5" ? f_nv("5" ) : volume // —————————— Assemble volume information. volTotal = volNeutral + volBuy + volSell barUp = close > open barDn = not barUp VolumeAvailable = not na(volume) // ————— Buy/Sell Volume MAs. volTotalMa = ema(volTotal, totalVolMaPeriod) volBuyMaFast = ema(volBuy, balAvgPeriod) volSellMaFast = ema(volSell, balAvgPeriod) volBuyMaSlow = sma(volBuy, balAvgPeriod * 2) volSellMaSlow = sma(volSell, balAvgPeriod * 2) // ————— Volume Balance on Bar. volUp = rising(volume, 1) volOverMa = volTotal > volTotalMa balBarBull = volBuy > volSell balBarBear = volBuy < volSell balBarDivUp = balBarBull and barDn balBarDivDn = balBarBear and barUp balBarDiv = balBarDivUp or balBarDivDn // ————— Volume Balance Average. balAvg = volBuyMaFast - volSellMaFast balAvgBull = balAvg > 0 balAvgBear = balAvg < 0 balAvgDivUp = balAvgBull and barDn balAvgDivDn = balAvgBear and barUp balAvgDiv = balAvgDivUp or balAvgDivDn // ————— Volume Balance Momentum. buyDeltaMa = volBuyMaFast - volBuyMaSlow sellDeltaMa = volSellMaFast - volSellMaSlow buySellDeltaMa = buyDeltaMa - sellDeltaMa balMom = rsi(buySellDeltaMa, balMomPeriod) - 50 balMomBull = balMom > 0 balMomBear = balMom < 0 balMomDivUp = balMomBull and barDn balMomDivDn = balMomBear and barUp balMomDiv = balMomDivUp or balMomDivDn // ————— Tops/Bottoms. barTop = max(close, open) barBot = min(close, open) barRange = barTop - barBot volTopBar = barTop + barRange * (volBuy / volTotal) volTopMom = barTop + barRange * max(balMom / 50, 0) volTop = topBotMode == TB2 ? volTopBar : topBotMode == TB3 ? volTopMom : float(na) volBotBar = barBot - barRange * (volSell / volTotal) volBotMom = barBot - barRange * - min(balMom / 50, 0) volBot = topBotMode == TB2 ? volBotBar : topBotMode == TB3 ? volBotMom : float(na) // ————— Divergence levels. divLevelsDivUp = divLevelsMode == CB3 ? balBarDivUp : divLevelsMode == CB4 ? balAvgDivUp : divLevelsMode == CB6 ? balMomDivUp : false divLevelsDivDn = divLevelsMode == CB3 ? balBarDivDn : divLevelsMode == CB4 ? balAvgDivDn : divLevelsMode == CB6 ? balMomDivDn : false divLevelsDiv = divLevelsDivUp or divLevelsDivDn and VolumeAvailable divLevelsHiNew = divLevelsModeHiLo == HL0 ? max(volTop, high) : divLevelsModeHiLo == HL1 ? volTop : divLevelsModeHiLo == HL2 ? max(open, close) : high divLevelsLoNew = divLevelsModeHiLo == HL0 ? min(volBot, low) : divLevelsModeHiLo == HL1 ? volBot : divLevelsModeHiLo == HL2 ? min(open, close) : low divLevelsHiRef = divLevelsModeHiLoRef == DV0 ? min(volBot, low) : divLevelsModeHiLoRef == DV1 ? volBot : divLevelsModeHiLoRef == DV2 ? min(open, close) : divLevelsModeHiLoRef == DV3 ? low : divLevelsModeHiLoRef == DV4 ? volTop : divLevelsModeHiLoRef == DV5 ? high : close divLevelsLoRef = divLevelsModeHiLoRef == DV0 ? max(volTop, high) : divLevelsModeHiLoRef == DV1 ? volTop : divLevelsModeHiLoRef == DV2 ? max(open, close) : divLevelsModeHiLoRef == DV3 ? high : divLevelsModeHiLoRef == DV4 ? volBot : divLevelsModeHiLoRef == DV5 ? low : close var divLevelsHi = VolumeAvailable ? divLevelsHiRef : float(na) var divLevelsLo = VolumeAvailable ? divLevelsLoRef : float(na) divLevelsHiBreachSize = max(0, divLevelsHiRef - nz(divLevelsHi[1])) divLevelsLoBreachSize = max(0, nz(divLevelsLo[1], 10e15) - divLevelsLoRef) divLevelsHState = divLevelsHiBreachSize > divLevelsLoBreachSize divLevelsLState = divLevelsHiBreachSize < divLevelsLoBreachSize divLevelsNState = not (divLevelsHState or divLevelsLState) var divLevelsBreached = false divLevelsBreached := divLevelsBreached or not divLevelsNState divLevelsChanged = false // We only change levels on divergences. if divLevelsDiv // Consecutive divergences; expand levels. if divLevelsDiv[1] divLevelsHi := max(divLevelsHi, divLevelsHiNew) divLevelsLo := min(divLevelsLo, divLevelsLoNew) else if divLevelsBreached // First divergence since breach out of levels; reset both levels. divLevelsHi := divLevelsHiNew divLevelsLo := divLevelsLoNew // Reset state to neutral. divLevelsHState := false divLevelsLState := false divLevelsNState := true divLevelsBreached := false // Indicate a break will occur in plotting. divLevelsChanged := true else if divLevelsNState // Still in channel; expand levels if necessary. divLevelsHi := max(divLevelsHi, divLevelsHiNew) divLevelsLo := min(divLevelsLo, divLevelsLoNew) // } // ———————————————————— Markers // { // ————— Marker Conditions. bumpUp = barUp and balBarBull and volBuy > volBuyMaFast and rising(volBuy, 1) bumpDn = barDn and balBarBear and volSell > volSellMaFast and rising(volSell, 1) divUp = marker3Mode == CB3 ? balBarDivUp : marker3Mode == CB4 ? balAvgDivUp : marker3Mode == CB6 ? balMomDivUp : false divDn = marker3Mode == CB3 ? balBarDivDn : marker3Mode == CB4 ? balAvgDivDn : marker3Mode == CB6 ? balMomDivDn : false c1U = bumpUp[1] c1D = bumpDn[1] c2U = bumpUp[1] and bumpUp[2] and rising(close, 1)[1] c2D = bumpDn[1] and bumpDn[2] and falling(close, 1)[1] c3U = divUp[2] and barUp[1] and not (divUp[1] or divDn[1]) c3D = divDn[2] and barDn[1] and not (divUp[1] or divDn[1]) c4U = marker4Mode == CB4 ? crossover( balAvg, 0)[1] : marker4Mode == CB6 ? crossover( balMom, 0)[1] : false c4D = marker4Mode == CB4 ? crossunder(balAvg, 0)[1] : marker4Mode == CB6 ? crossunder(balMom, 0)[1] : false // ————— Marker bias. cUps = f_01(c1U) + f_01(c2U) + f_01(c3U) + f_01(c4U) cDns = f_01(c1D) + f_01(c2D) + f_01(c3D) + f_01(c4D) markerBias = sum(cUps - cDns, biasPeriod) markerBiasBull = markerBias > 0 markerBiasBear = markerBias < 0 // Crosses above/below a middle buffer zone of +1 to -1. c5U = crossover( markerBias, 1) c5D = crossunder(markerBias, -1) // ————— Assembly. a1U = barstate.isconfirmed and showMarker1 and not shortsOnly and c1U a1D = barstate.isconfirmed and showMarker1 and not longsOnly and c1D a2U = barstate.isconfirmed and showMarker2 and not shortsOnly and c2U a2D = barstate.isconfirmed and showMarker2 and not longsOnly and c2D a3U = barstate.isconfirmed and showMarker3 and not shortsOnly and c3U a3D = barstate.isconfirmed and showMarker3 and not longsOnly and c3D a4U = barstate.isconfirmed and showMarker4 and not shortsOnly and c4U a4D = barstate.isconfirmed and showMarker4 and not longsOnly and c4D a5U = barstate.isconfirmed and showMarker5 and not shortsOnly and c5U a5D = barstate.isconfirmed and showMarker5 and not longsOnly and c5D // } // ———————————————————— Plots // { color c_commonBull = color.lime color c_commonBear = color.red color c_commonNeutral = color.gray bool okToPlot = barstate.ishistory or (i_realtimeMode and barstate.isrealtime) // ————— Data Window plotchar(okToPlot ? volTotal : volume, "Total Volume", "", location.top, balBarBull ? c_commonBull : c_commonBear) plotchar(okToPlot ? volBuy : na, "Buy Volume", "", location.top, c_commonBull) plotchar(okToPlot ? volSell : na, "Sell Volume", "", location.top, c_commonBear) plotchar(okToPlot ? volNeutral : na, "Neutral Volume", "", location.top, c_commonNeutral) plotchar(0, "═════════════", "", location.top, c_commonNeutral) plotchar(okToPlot ? balAvg : na, "Balance Average", "", location.top, c_commonNeutral) plotchar(okToPlot ? balMom : na, "Balance Momentum ", "", location.top, c_commonNeutral) plotchar(okToPlot ? markerBias : na, "Marker Bias", "", location.top, c_commonNeutral) plotchar(okToPlot ? volTop : na, "Top", "", location.top, c_commonBull) plotchar(okToPlot ? volBot : na, "Bottom", "", location.top, c_commonBear) // ————— Tops/Bottoms MAs c_markerBias = f_colorGradientAdvMaFill(markerBias, 0) p_tops = plot(colorMaTops != C00 and okToPlot ? ema(maMode == TB2 ? volTopBar : maMode == TB3 ? volTopMom : float(na), topBotMasPeriod) : na, "Tops MA", f_colorMaH(topBotMasBrightness)) p_bots = plot(colorMaBots != C00 and okToPlot ? ema(maMode == TB2 ? volBotBar : maMode == TB3 ? volBotMom : float(na), topBotMasPeriod) : na, "Botttoms MA", f_colorMaL(topBotMasBrightness)) // Fill with marker bias if needed. fill(p_tops, p_bots, fillMas ? c_markerBias : na) // ————— Divergence levels. brighterWhenBreached = divLevelsBreached ? 16 : divLevelsBrightness c_divLevels = divLevelsHState ? f_color(colordivLevelsBull, brighterWhenBreached) : divLevelsLState ? f_color(colordivLevelsBear, brighterWhenBreached) : f_color(colordivLevelsNeut, brighterWhenBreached) p_divLevelsHi = plot(divLevelsHi, "Divergence Hi Level", divLevelsChanged ? na : c_divLevels) p_divLevelsLo = plot(divLevelsLo, "Divergence Lo Level", divLevelsChanged ? na : c_divLevels) fill(p_divLevelsHi, p_divLevelsLo, filldivLevels and not divLevelsChanged ? c_divLevels : na) // Data Window separator. plotchar(0, "═════════════", "", location.top, c_commonNeutral) // ————— Candles // Build colors. c_fillNeutral = color(na) c_barsEmpty = color(na) c_barsDiv = f_colorBodiesDivs(colorBodiesDivsBr) c_barsUp = f_bodyColorBull(bodyFillBrightness) c_barsDn = f_bodyColorBear(bodyFillBrightness) c_volAvg = bodiesMode == CB5 ? f_colorGradientAdv(balAvg, 0) : color(na) c_volMom = bodiesMode == CB7 ? f_colorGradientAdv(balMom, 0) : color(na) // Body color. c_bars = barstate.islast ? barUp ? c_barsUp : c_barsDn : bodiesMode == CB2 ? colorBodiesDivs != C00 and balBarDiv ? c_barsDiv : hollowOutBodies and not volUp ? c_barsEmpty : barUp ? c_barsUp : barDn ? c_barsDn : c_fillNeutral : bodiesMode == CB3 ? colorBodiesDivs != C00 and balBarDiv ? c_barsDiv : hollowOutBodies and not volUp ? c_barsEmpty : balBarBull ? c_barsUp : balBarBear ? c_barsDn : c_fillNeutral : bodiesMode == CB4 ? colorBodiesDivs != C00 and balAvgDiv ? c_barsDiv : hollowOutBodies and not volUp ? c_barsEmpty : balAvgBull ? c_barsUp : balAvgBear ? c_barsDn : c_fillNeutral : bodiesMode == CB5 ? colorBodiesDivs != C00 and balAvgDiv ? c_barsDiv : hollowOutBodies and not volUp ? c_barsEmpty : c_volAvg : bodiesMode == CB6 ? colorBodiesDivs != C00 and balMomDiv ? c_barsDiv : hollowOutBodies and not volUp ? c_barsEmpty : balMomBull ? c_barsUp : balMomBear ? c_barsDn : c_fillNeutral : bodiesMode == CB7 ? colorBodiesDivs != C00 and balMomDiv ? c_barsDiv : hollowOutBodies and not volUp ? c_barsEmpty : c_volMom : na // Border and wick color. var xx_ = bodyColorBull var c_borderCandleBull = borderWickDisplay == BW2 ? xx_ == C01 ? #0080FFff : xx_ == C02 ? #013BCAff : xx_ == C03 ? #FF8080ff : xx_ == C04 ? #CCCC00ff : xx_ == C05 ? #808080ff : xx_ == C06 ? #008000ff : xx_ == C07 ? #00FF00ff : xx_ == C08 ? #800000ff : xx_ == C09 ? #FF8000ff : xx_ == C10 ? #FF0080ff : xx_ == C11 ? #FF0000ff : xx_ == C12 ? #AA00FFff : xx_ == C13 ? #FFFF00ff : na : borderWickDisplay == BW3 ? xx_ == C01 ? #0080FF8f : xx_ == C02 ? #013BCA8f : xx_ == C03 ? #FF80808f : xx_ == C04 ? #CCCC008f : xx_ == C05 ? #8080808f : xx_ == C06 ? #0080008f : xx_ == C07 ? #00FF008f : xx_ == C08 ? #8000008f : xx_ == C09 ? #FF80008f : xx_ == C10 ? #FF00808f : xx_ == C11 ? #FF00008f : xx_ == C12 ? #AA00FF8f : xx_ == C13 ? #FFFF008f : na : na var yy_ = bodyColorBear var c_borderCandleBear = borderWickDisplay == BW2 ? yy_ == C01 ? #0080FFff : yy_ == C02 ? #013BCAff : yy_ == C03 ? #FF8080ff : yy_ == C04 ? #CCCC00ff : yy_ == C05 ? #808080ff : yy_ == C06 ? #008000ff : yy_ == C07 ? #00FF00ff : yy_ == C08 ? #800000ff : yy_ == C09 ? #FF8000ff : yy_ == C10 ? #FF0080ff : yy_ == C11 ? #FF0000ff : yy_ == C12 ? #AA00FFff : yy_ == C13 ? #FFFF00ff : na : borderWickDisplay == BW3 ? yy_ == C01 ? #0080FF8f : yy_ == C02 ? #013BCA8f : yy_ == C03 ? #FF80808f : yy_ == C04 ? #CCCC008f : yy_ == C05 ? #8080808f : yy_ == C06 ? #0080008f : yy_ == C07 ? #00FF008f : yy_ == C08 ? #8000008f : yy_ == C09 ? #FF80008f : yy_ == C10 ? #FF00808f : yy_ == C11 ? #FF00008f : yy_ == C12 ? #AA00FF8f : yy_ == C13 ? #FFFF008f : na : na // Plot candles. plotCandleUp = barUp plotcandle(plotCandleUp ? open : na, plotCandleUp ? high : na, plotCandleUp ? low : na, plotCandleUp ? close : na, "Candle Up Structure", c_bars, wickcolor = c_borderCandleBull, bordercolor = c_borderCandleBull) plotCandleDn = barDn plotcandle(plotCandleDn ? open : na, plotCandleDn ? high : na, plotCandleDn ? low : na, plotCandleDn ? close : na, "Candle Dn Structure", c_bars, wickcolor = c_borderCandleBear, bordercolor = c_borderCandleBear) // ————— Tops/Bottoms // Build colors. c_fillDiv = topBotMode != TB1 ? f_colorTopsBotsDivs(colorTopsBotsDivsBr) : color(na) c_fillTopUp = f_volColorBull(topBotFillBright) c_fillBotDn = f_volColorBear(topBotFillBright) var x_ = topColorBull var c_borderTopBull = x_ == C01 ? #0080FFff : x_ == C02 ? #013BCAff : x_ == C03 ? #FF8080ff : x_ == C04 ? #CCCC00ff : x_ == C05 ? #808080ff : x_ == C06 ? #008000ff : x_ == C07 ? #00FF00ff : x_ == C08 ? #800000ff : x_ == C09 ? #FF8000ff : x_ == C10 ? #FF0080ff : x_ == C11 ? #FF0000ff : x_ == C12 ? #AA00FFff : x_ == C13 ? #FFFF00ff : na var c_borderTopBear = x_ == C01 ? #0080FF8f : x_ == C02 ? #013BCA8f : x_ == C03 ? #FF80808f : x_ == C04 ? #CCCC008f : x_ == C05 ? #8080808f : x_ == C06 ? #0080008f : x_ == C07 ? #00FF008f : x_ == C08 ? #8000008f : x_ == C09 ? #FF80008f : x_ == C10 ? #FF00808f : x_ == C11 ? #FF00008f : x_ == C12 ? #AA00FF8f : x_ == C13 ? #FFFF008f : na var y_ = botColorBear var c_borderBotBull = y_ == C01 ? #0080FF8f : y_ == C02 ? #013BCA8f : y_ == C03 ? #FF80808f : y_ == C04 ? #CCCC008f : y_ == C05 ? #8080808f : y_ == C06 ? #0080008f : y_ == C07 ? #00FF008f : y_ == C08 ? #8000008f : y_ == C09 ? #FF80008f : y_ == C10 ? #FF00808f : y_ == C11 ? #FF00008f : y_ == C12 ? #AA00FF8f : y_ == C13 ? #FFFF008f : na var c_borderBotBear = y_ == C01 ? #0080FFff : y_ == C02 ? #013BCAff : y_ == C03 ? #FF8080ff : y_ == C04 ? #CCCC00ff : y_ == C05 ? #808080ff : y_ == C06 ? #008000ff : y_ == C07 ? #00FF00ff : y_ == C08 ? #800000ff : y_ == C09 ? #FF8000ff : y_ == C10 ? #FF0080ff : y_ == C11 ? #FF0000ff : y_ == C12 ? #AA00FFff : y_ == C13 ? #FFFF00ff : na var c_invisible = #00000000 // Two different possible top brightnesses: bull (brighter) when volume balance agrees with up bar, not bull (darker) when it doesn't. topDiv = topBotMode == TB2 ? balBarBull and barDn : topBotMode == TB3 ? balMomDiv : false plotTopBull = ((topBotMode == TB2 and balBarBull) or (topBotMode == TB3 and balMomBull)) and volTop != barTop and not resNotSupported and okToPlot plotcandle(plotTopBull ? barTop : na, plotTopBull ? volTop : na, plotTopBull ? barTop : na, plotTopBull ? volTop : na, "Top Bullish", colorTopsBotsDivs != C00 and topDiv ? c_fillDiv : c_fillTopUp, bordercolor = c_borderTopBull) plotTopNotBull = ((topBotMode == TB2 and not balBarBull) or (topBotMode == TB3 and not balMomBull)) and volTop != barTop and not resNotSupported plotcandle(plotTopNotBull ? barTop : na, plotTopNotBull ? volTop : na, plotTopNotBull ? barTop : na, plotTopNotBull ? volTop : na, "Top not Bullish", colorTopsBotsDivs != C00 and topDiv ? c_fillDiv : c_invisible, bordercolor = c_borderTopBear) // Two possible possible bottom brightnesses: bear (brighter) when volume balance agrees with down bar, not bear (darker) when it doesn't. botDiv = topBotMode == TB2 ? balBarBear and barUp : topBotMode == TB3 ? balMomDiv : false plotBotBear = ((topBotMode == TB2 and balBarBear) or (topBotMode == TB3 and balMomBear)) and volBot != barBot and not resNotSupported and okToPlot plotcandle(plotBotBear ? barBot : na, plotBotBear ? volBot : na, plotBotBear ? barBot : na, plotBotBear ? volBot : na, "Bottom Bearish", colorTopsBotsDivs != C00 and botDiv ? c_fillDiv : c_fillBotDn, bordercolor = c_borderBotBear) plotBotNotBear = ((topBotMode == TB2 and not balBarBear) or (topBotMode == TB3 and not balMomBear)) and volBot != barBot and not resNotSupported plotcandle(plotBotNotBear ? barBot : na, plotBotNotBear ? volBot : na, plotBotNotBear ? barBot : na, plotBotNotBear ? volBot : na, "Bottom not Bearish", colorTopsBotsDivs != C00 and botDiv ? c_fillDiv : c_invisible, bordercolor = c_borderBotBull) // ————— Background // Color background on Marker bias or on total volume failure. bgcolor(okToPlot and bgOnMarkerBias ? c_markerBias : na) // Color background on total volume failure. totalVolumeDisc = abs(volTotal - volume) / volume > failureTolerance bgcolor(okToPlot and totalVolumeDisc ? f_color(bgColor, bgBrightness) : na) // —————————— Markers topPos = max(nz(volTop), high) botPos = min(nz(volBot, 10e15), low) var int MARKER_CONDITIONS = 5 bool[] markerCondUps = array.from(a1U, a2U, a3U, a4U, a5U) bool[] markerCondDns = array.from(a1D, a2D, a3D, a4D, a5D) // Build marker label's text from user-selected marker conditions. string labelMsgUp = "" string labelMsgDn = "" bool triggerLong = false bool triggerShort = false for _i = 0 to MARKER_CONDITIONS - 1 bool _cUp = array.get(markerCondUps, _i) bool _cDn = array.get(markerCondDns, _i) triggerLong := triggerLong or _cUp triggerShort := triggerShort or _cDn labelMsgUp := f_addTextIf(_cUp, labelMsgUp, "M" + tostring(_i + 1) + "▲") labelMsgDn := f_addTextIf(_cDn, labelMsgDn, "M" + tostring(_i + 1) + "▼") if triggerLong label.new(bar_index, botPos, labelMsgUp, style = label.style_label_up, color = color(na), textcolor = c_commonBull) if triggerShort label.new(bar_index, topPos, labelMsgDn, style = label.style_label_down, color = color(na), textcolor = c_commonBear) // }