//@version=6 indicator(title="My Trading Suite", shorttitle="My Trading Suite", max_lines_count = 500, max_labels_count = 500, max_bars_back = 5000, overlay = false) ////////////////////////////////////////////////// // VWAP Function getVWAP(vwap_newSession) => var float vwap_p = na var float vwap_vol = na vwap_p := vwap_newSession ? hlc3 * volume : nz(vwap_p[1]) + hlc3 * volume vwap_vol := vwap_newSession ? volume : nz(vwap_vol[1]) + volume vwap_p / vwap_vol // === TEMA Function === get_tema(src, len) => ema1 = ta.ema(src, len) ema2 = ta.ema(ema1, len) ema3 = ta.ema(ema2, len) 3 * (ema1 - ema2) + ema3 //-------------------------- // MA Funtion //-------------------------- f_ma(_type, _source, _length, _colorUp, _colorDown) => float ma = switch _type "SMA" => ta.sma(_source, _length) "EMA" => ta.ema(_source, _length) "WMA" => ta.wma(_source, _length) "RMA" => ta.rma(_source, _length) "HMA" => ta.hma(_source, _length) "TEMA" => get_tema(_source, _length) "VWMA" => ta.vwma(hlc3, _length) "VWAP Daily" => getVWAP(ta.change(time("D")) != 0) "VWAP Weekly" => getVWAP(ta.change(time("W")) != 0) "VWAP Monthly" => getVWAP(ta.change(time("MN")) != 0) "LinReg" => ta.linreg(_source, _length, 0) => na // MA color logic float prev = nz(ma[1]) color col = ma > prev ? _colorUp : ma < prev ? _colorDown : color.yellow [ma, col] //=> return MA value and MA color // @function Checks whether a specified timeframe string represents a smaller timeframe than the // script's main timeframe. If the specified string represents a higher timeframe, the // function raises a runtime error. // @param lowerTimeframe (series string) The timeframe string to inspect. // @returns (void) The function does not return a usable value. checkLTF(series string lowerTimeframe) => if timeframe.in_seconds(lowerTimeframe) > timeframe.in_seconds(timeframe.main_period) runtime.error( str.format( "Invalid lower timeframe: {2}{0}{2}. The timeframe must be lower than or equal to {2}{1}{2}", lowerTimeframe, timeframe.main_period, "'" ) ) // @function Calculates sums of polarized (positive and negative) `volume` values within a bar on // script's main timeframe and uses the sums to compute the bar's volume delta. The function // also tracks the highest and lowest volume delta values observed within the bar. // It uses the following logic based on `open` and `close` prices to categorize each `volume` // value: // - If the `close` is greater than the `open`, the `volume` is positive. // - If the `close` is less than the `open`, the `volume` is negative. // - If the current `close` equals the current `open` and the `close` is greater than its // previous value, the `volume` is positive. // - If the current `close` equals the current `open` and the `close` is less than its // previous value, the `volume` negative. // - If none of the above apply, the current bar's `volume` has the same positive/negative // status as that of the previous bar. // // This function's result is usable in lower-timeframe `request.*()` calls, as demonstrated in // `requestUpAndDownVolume()`. The results from such a request always represent volume data // based on all intrabars within a *single bar* on the script's *main timeframe*, because the // function resets its calculations at the open of each bar on the `timeframe.main_period` // timeframe. // In contrast to `timeframe.period`, the value of `timeframe.main_period` always represents // the script's main timeframe, even in requested contexts. // @returns ([float, float, float, float, float]) A tuple containing the following values: // - The total positive (up) volume within the bar on the script's main timeframe. // - The total negative (down) volume within the bar on the script's main timeframe, // expressed as a negative quantity. // - The bar's volume delta (i.e., the net difference between up and down volume). // - The highest volume delta observed within the bar. // - The lowest volume delta observed within the bar. upAndDownVolumeCalc() => var float posVol = 0.0 var float negVol = 0.0 var float hiVol = 0.0 var float loVol = 0.0 var bool isBuyVolume = true if timeframe.change(timeframe.main_period) posVol := 0.0 negVol := 0.0 hiVol := 0.0 loVol := 0.0 switch close > open => isBuyVolume := true close < open => isBuyVolume := false close > close[1] => isBuyVolume := true close < close[1] => isBuyVolume := false if isBuyVolume posVol += volume else negVol -= volume // float delta = posVol + negVol // float delta = high == low ? 0 : posVol + negVol float delta = posVol + negVol hiVol := math.max(delta, hiVol) loVol := math.min(delta, loVol) [posVol, negVol, delta, hiVol, loVol] // @function Requests data from a specified lower timeframe and categorizes the volume of each // intrabar within a bar on the script's main timeframe as positive (up) or negative (down). // The function uses this information to calculate the bar's volume delta, i.e., the difference // between the total up and down intrabar volume. // // If the call specifies a `cumulativePeriod` argument representing a period larger than the // main timeframe, it calculates the cumulative volume delta (CVD), which is a running sum // of volume delta across all bars within the period. In addition, the function tracks the // highest and lowest CVD values calculated within each bar over the period. The sum and // highest/lowest calculations reset when a new period starts. // // Calls to this function count toward a script's `request.*()` call limit. // @param lowerTimeframe (series string) The timeframe of the requested intrabar data. Accepts a valid timeframe // string (e.g., "5", "15", "1D"), an empty string, `timeframe.period`, or // `timeframe.main_period`. Smaller timeframes provide higher precision but cover fewer bars // on the script's main timeframe. Larger timeframes cover more bars on the script's main // timeframe but offer less granularity. If the specified timeframe is higher than the script's // main timeframe, it causes a runtime error. // @param cumulativePeriod (series string) Determines the span of the CVD period. Accepts a valid timeframe string // (e.g., "5", "15", "1D"), an empty string, `timeframe.period`, or `timeframe.main_period`. // The calculations reset after a new period starts. For example, a value of "1D" means that // the function accumulates and tracks the values from each bar within a "1D" period and resets // at the open of a new "1D" bar. // @returns ([float, float, float, float]) A tuple containing the following values: // - The opening volume delta/CVD at the start the bar on the script's main timeframe. // This value is always 0 when a new cumulative period starts. // - The maximum volume delta/CVD within the current cumulative period. // - The minimum volume delta/CVD within the current cumulative period. // - The current volume delta/CVD value. requestVolumeDelta(series string lowerTimeframe, series string cumulativePeriod = "") => checkLTF(lowerTimeframe) [_, _, delta, maxVolume, minVolume] = request.security(syminfo.tickerid, lowerTimeframe, upAndDownVolumeCalc()) var float lastVolume = 0.0 bool anchorChange = str.length(str.trim(cumulativePeriod)) == 0 or timeframe.change(cumulativePeriod) or (not na(lastVolume) and na(lastVolume[1])) float openVolume = anchorChange ? 0.0 : lastVolume[1] float hiVolume = openVolume + maxVolume float loVolume = openVolume + minVolume lastVolume := openVolume + delta [openVolume, hiVolume, loVolume, lastVolume] ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// lowerTimeframeTooltip = "The indicator scans lower timeframe data to approximate up and down volume used in the delta calculation. By default, the timeframe is chosen automatically. These inputs override this with a custom timeframe. \n\nHigher timeframes provide more historical data, but the data will be less precise." CDVuseCustomTimeframe = input.bool(true, "Use Auto custom timeframe", tooltip = lowerTimeframeTooltip, group="CDV Candle") CDVltf = input.timeframe('1', 'LTF Manual (when Auto custom TF = false)', group="CDV Candle") CDVcolorup = input.color(color.new(#00ff00,0), title="Up", inline="col", group="CDV Candle") //color.lime CDVcolordown = input.color(color.new(#ff0000,0), title="Down", inline="col", group="CDV Candle") //color.red CDVuseVSAcolor = input(true, title="Use VSA Color?", group="CDV Candle") // --- use CDVuseCustomTimeframe --- var string CDVlowerTimeframe = na CDVlowerTimeframe := switch CDVuseCustomTimeframe == false => CDVltf timeframe.isseconds => "1S" timeframe.isintraday => "1" timeframe.isdaily => "15" => "60" // --- Function CDV --- CDVrequestVolumeDelta(series string lowerTimeframe, float lastVolume) => checkLTF(lowerTimeframe) [_, _, delta, maxVolume, minVolume] = request.security(syminfo.tickerid, lowerTimeframe, upAndDownVolumeCalc()) float CDVopenVolume = nz(lastVolume, 0) float CDVhiVolume = CDVopenVolume + maxVolume float CDVloVolume = CDVopenVolume + minVolume float CDVlastVolume = CDVopenVolume + delta [CDVopenVolume, CDVhiVolume, CDVloVolume, CDVlastVolume] // --- Candle cho CDV var float CDVlastVolume = 0.0 [ltf_o, ltf_h, ltf_l, ltf_c] = CDVrequestVolumeDelta(CDVlowerTimeframe, CDVlastVolume) CDVlastVolume := ltf_c o_ = ltf_o c_ = ltf_c h_ = ltf_h l_ = ltf_l ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// //Ratio High Volume Highlight_Candle = input.bool(true, title="Highlight Candles", group = "Volume Spread Analysis") lengthVolumeMA = input(defval=20, title="Length of MA applied on Volume", group ="Volume Spread Analysis") colorUltraHigh = input.color(color.purple, title="", inline="UHV" , group="Volume Spread Analysis") //color.red colorVeryHigh = input.color(color.blue, title="", inline="VHV" , group="Volume Spread Analysis") //color.orange colorHighVol = input.color(color.orange, title="", inline="HV" , group="Volume Spread Analysis") //color.green colorNormalVol = input.color(color.silver, title="", inline="NV" , group="Volume Spread Analysis") //color.blue colorLowVol = input.color(#636363, title="", inline="LV" , group="Volume Spread Analysis") //color.silver colorVeryLowVol = input.color(#2e2e2e, title="", inline="VLV" , group="Volume Spread Analysis") //color.silver ratioUltraVolume = input.float(defval=2.2, step=0.1, title="Ultra High Volume", inline="UHV", group ="Volume Spread Analysis") //2.2 - 3.0 ratioVeryHighVolume = input.float(defval=1.8, step=0.1, title="Very High Volume" , inline="VHV", group ="Volume Spread Analysis") //1.8 - 2.5 ratioHighVolume = input.float(defval=1.4, step=0.1, title="High Volume" , inline="HV", group ="Volume Spread Analysis") //1.2 - 1.4 ratioNormalVolume = input.float(defval=1.0, step=0.1, title="Normal Volume" , inline="NV", group ="Volume Spread Analysis") //0.8 - 1.0 ratioLowVolume = input.float(defval=0.5, step=0.1, title="Low Volume" , inline="LV", group ="Volume Spread Analysis") //0.3 - 0.5 ratioVeryLowVolume = input.float(defval=0.5, step=0.1, title="Very Low Volume" , inline="VLV", group ="Volume Spread Analysis") //0.3 - 0.5 ////////////////////////////////////////////////// volumeMA = ta.sma(volume, lengthVolumeMA) // Volume Zones ultraHighVolumeMin = volumeMA * ratioUltraVolume veryHighVolumeMin = volumeMA * ratioVeryHighVolume highVolumeMin = volumeMA * ratioHighVolume normalVolumeMin = volumeMA * ratioNormalVolume lowVolumeMin = volumeMA * ratioLowVolume veryLowVolumeMin = volumeMA * ratioVeryLowVolume volUltraHigh = volume >= ultraHighVolumeMin and high != low volVeryHigh = volume >= veryHighVolumeMin and volume < ultraHighVolumeMin and high != low volHigh = volume >= highVolumeMin and volume < veryHighVolumeMin and high != low volNormal = volume >= normalVolumeMin and volume < highVolumeMin and high != low volLow = volume >= lowVolumeMin and volume < normalVolumeMin and high != low volVeryLow = volume < lowVolumeMin and high != low //---------------------- // Logic color //---------------------- colorVSA = volUltraHigh ? colorUltraHigh : volVeryHigh ? colorVeryHigh : volHigh ? colorHighVol : volNormal ? colorNormalVol : volLow ? colorLowVol : volVeryLow ? colorVeryLowVol : na ////////////////////////////////////////////////// ////////////////////////////////////////////////// spread_price = math.abs(close - open) spread_CDV = math.abs(c_ - o_) price_CDV_div = (spread_price > spread_price[1] and spread_CDV < spread_CDV[1] and high != low) or (spread_price < spread_price[1] and spread_CDV > spread_CDV[1] and high != low) plotcandle(o_, h_, l_, c_, "CDV Candles", color = CDVuseVSAcolor ? color.new(colorVSA, price_CDV_div ? 50 : 0) : o_ <= c_ ? CDVcolorup : CDVcolordown, bordercolor = CDVuseVSAcolor ? colorVSA : o_ <= c_ ? CDVcolorup : CDVcolordown, wickcolor = o_ <= c_ ? CDVcolorup : CDVcolordown) ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// // ===== ===== All CDVma input // --- Input MA of CDV Candles showCDVMA = input.bool(true, "Show MA of CDV Candles", group="MA of CDV") CDVmaType = input.string("TEMA", "Type of MA", options = ["SMA","EMA","WMA","RMA","HMA","TEMA","VWMA", "VWAP Daily","VWAP Weekly","VWAP Monthly","LinReg"], group="MA of CDV") CDVmaLength = input.int(20, "MA Length", group="MA of CDV") CDVmaWidth = input.int(2, "MA Width", group="MA of CDV") CDVma_colorup = input.color(color.lime, title="Up", inline="col", group="MA of CDV") CDVma_colordown = input.color(color.red, title="Down", inline="col", group="MA of CDV") // --- Input CDVma Cross CDVma_useSpreadFilter = input.bool(true, "Use OC/HL Spread Filter?", group="MA of CDV") CDVma_SpreadRatio = input.int(30, "OC Compare to HL Ratio %", minval=0, step=5, group="MA of CDV") CDVma_useMAVol = input.bool(false, "Use MA Volume To Check Signal?", group="MA of CDV") CDVma_VolRatio = input.float(1.0, "MA Volume Ratio", minval=0.1, step=0.1, group="MA of CDV") // --- Input CDVma shadow + signal + box showCDVma_shadow = input.bool(true, "Show CDV_MA Shadow", group="CDV_MA Shadow") CDVma_shadow_transp = input.int(70, "Transparency", minval=0, maxval=100, group="CDV_MA Shadow Trend") showCDVma_shadow_break = input.bool(true, "Show CDV_MA Shadow Cross", group="CDV_MA Shadow Break") CDVma_shadow_break_useMAVol = input.bool(true, "Use MA Volume To Check Signal?", group="BCDV_MA Shadow Break") CDVma_shadow_break_VolRatio = input.float(1.0, "MA Volume Ratio", minval=0.1, step=0.1, group="CDV_MA Shadow Break") showCDVma_trend_signal = input.bool(true, "Show Trend Signal", group="CDV_MA Shadow Trend") showCDVma_trend_bg = input.bool(true, "Show Trend Background", group="CDV_MA Shadow Trend") CDVma_trend_bg_transp = input.int(90, "Transparency", minval=0, maxval=100, group="CDV_MA Shadow Trend") ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// // ===== ===== All CDVma LOGIC // --- Get value CDVma and color [CDVmaLine, CDVmaLine_color] = f_ma(CDVmaType, c_, CDVmaLength, CDVma_colorup, CDVma_colordown) ////////////////////////////////////////////////// // ===== CDVma_cross logic // --- Body Candle Condition CDVma_spread = math.abs(close - open) CDVma_spreadCondition = not CDVma_useSpreadFilter or ((high-low) > 0 and (math.abs(close - open) / (high-low) * 100 >= CDVma_SpreadRatio)) // --- MA Volume Condition CDVma_MAVol = ta.sma(volume, CDVmaLength) CDVma_volCondition = CDVma_useMAVol ? (volume > CDVma_MAVol * CDVma_VolRatio) : (volume > volume[1]) // --- Cross signals CDVma_crossUp_weak = ta.crossover(c_, CDVmaLine) CDVma_crossDown_weak = ta.crossunder(c_, CDVmaLine) CDVma_crossUp_strong1 = CDVma_crossUp_weak and low <= low[1] and CDVma_spread >= CDVma_spread[1] CDVma_crossDown_strong1 = CDVma_crossDown_weak and high >= high[1] and CDVma_spread >= CDVma_spread[1] CDVma_crossUp_strong2 = ta.crossover(c_, CDVmaLine) and CDVma_volCondition and CDVma_spreadCondition CDVma_crossDown_strong2 = ta.crossunder(c_, CDVmaLine) and CDVma_volCondition and CDVma_spreadCondition CDVma_crossUp_strong = CDVma_crossUp_strong1 or CDVma_crossUp_strong2 CDVma_crossDown_strong = CDVma_crossDown_strong1 or CDVma_crossDown_strong2 ////////////////////////////////////////////////// // ===== CDVma Shadow logic // ===================================================== // CDV MA Cross – Candle Shadow State (Array-based) // This block replaces the original CDVma_CrossCandleShadow() function // using manual array-based state management (no helper functions). // ===================================================== // ===== Candle shadow (current / previous) ===== // [0] = current candle // [1] = previous candle var float[] arr_candleLow = array.new_float(2, na) var float[] arr_candleHigh = array.new_float(2, na) // ===== Previous-confirm candle (trend confirmation) ===== // These values are captured ONLY when a valid cross occurs // They store the candle state BEFORE the cross bar var float[] arr_candleLow_prevConfirm = array.new_float(2, na) var float[] arr_candleHigh_prevConfirm = array.new_float(2, na) // ===== CDV candle shadow (current / previous) ===== var float[] arr_cdvLow = array.new_float(2, na) var float[] arr_cdvHigh = array.new_float(2, na) // ===== Signal state & visual color ===== var bool[] arr_crossValid = array.new_bool(2, false) var color[] arr_shadowColor = array.new_color(2, na) // ===================================================== // Cross detection // ===================================================== bool IsCDVma_CrossCandle = CDVma_crossUp_strong or CDVma_crossDown_strong // Check if a previous candle shadow already exists bool hasPrev = not na(array.get(arr_candleHigh, 1)) and not na(array.get(arr_candleLow, 1)) // ===================================================== // Cross validity logic (same as original function) // ===================================================== bool crossValid = (CDVma_crossUp_strong and (not hasPrev or low >= array.get(arr_candleHigh, 1))) or (CDVma_crossDown_strong and (not hasPrev or high <= array.get(arr_candleLow, 1))) or (not CDVma_crossUp_strong and not CDVma_crossDown_strong) // ===================================================== // State update logic // ===================================================== if IsCDVma_CrossCandle and crossValid // --------------------------------- // Push candle shadow (current → previous) // --------------------------------- array.set(arr_candleLow, 1, array.get(arr_candleLow, 0)) array.set(arr_candleHigh, 1, array.get(arr_candleHigh, 0)) // --------------------------------- // Set current candle shadow // --------------------------------- array.set(arr_candleLow, 0, low) array.set(arr_candleHigh, 0, high) // --------------------------------- // Store previous-confirm candle // Captured only at the cross bar // --------------------------------- array.set(arr_candleLow_prevConfirm, 1, array.get(arr_candleLow_prevConfirm, 0)) array.set(arr_candleHigh_prevConfirm, 1, array.get(arr_candleHigh_prevConfirm, 0)) array.set(arr_candleLow_prevConfirm, 0, array.get(arr_candleLow, 1)) array.set(arr_candleHigh_prevConfirm, 0, array.get(arr_candleHigh, 1)) // --------------------------------- // CDV candle shadow update // --------------------------------- array.set(arr_cdvLow, 1, array.get(arr_cdvLow, 0)) array.set(arr_cdvHigh, 1, array.get(arr_cdvHigh, 0)) array.set(arr_cdvLow, 0, l_) array.set(arr_cdvHigh, 0, h_) // --------------------------------- // Cross state flag // --------------------------------- array.set(arr_crossValid, 1, array.get(arr_crossValid, 0)) array.set(arr_crossValid, 0, true) // --------------------------------- // Shadow color selection // --------------------------------- array.set(arr_shadowColor, 1, array.get(arr_shadowColor, 0)) array.set( arr_shadowColor, 0, CDVma_crossUp_strong ? CDVma_colorup : CDVma_crossDown_strong ? CDVma_colordown : array.get(arr_shadowColor, 1) ) else // --------------------------------- // Carry forward candle shadow state // --------------------------------- array.set(arr_candleLow, 1, array.get(arr_candleLow, 0)) array.set(arr_candleHigh, 1, array.get(arr_candleHigh, 0)) array.set(arr_candleLow, 0, array.get(arr_candleLow, 0)) array.set(arr_candleHigh, 0, array.get(arr_candleHigh, 0)) // --------------------------------- // Carry forward previous-confirm state // --------------------------------- array.set(arr_candleLow_prevConfirm, 1, array.get(arr_candleLow_prevConfirm, 0)) array.set(arr_candleHigh_prevConfirm, 1, array.get(arr_candleHigh_prevConfirm, 0)) array.set(arr_candleLow_prevConfirm, 0, array.get(arr_candleLow_prevConfirm, 0)) array.set(arr_candleHigh_prevConfirm, 0, array.get(arr_candleHigh_prevConfirm, 0)) // --------------------------------- // Carry forward CDV candle state // --------------------------------- array.set(arr_cdvLow, 1, array.get(arr_cdvLow, 0)) array.set(arr_cdvHigh, 1, array.get(arr_cdvHigh, 0)) array.set(arr_cdvLow, 0, array.get(arr_cdvLow, 0)) array.set(arr_cdvHigh, 0, array.get(arr_cdvHigh, 0)) // --------------------------------- // Reset cross flag & keep last color // --------------------------------- array.set(arr_crossValid, 1, array.get(arr_crossValid, 0)) array.set(arr_crossValid, 0, false) array.set(arr_shadowColor, 1, array.get(arr_shadowColor, 0)) array.set(arr_shadowColor, 0, array.get(arr_shadowColor, 1)) // ===================================================== // Output variables (drop-in replacement for function return) // ===================================================== bool CDVma_Cross_crossValid = array.get(arr_crossValid, 0) bool CDVma_Cross_hasPrev = hasPrev float CDVma_Cross_candleLow = array.get(arr_candleLow, 0) float CDVma_Cross_candleHigh = array.get(arr_candleHigh, 0) float CDVma_Cross_candleLow_prev = array.get(arr_candleLow_prevConfirm, 0) float CDVma_Cross_candleHigh_prev = array.get(arr_candleHigh_prevConfirm, 0) float CDVma_Cross_CDVcandleLow = array.get(arr_cdvLow, 0) float CDVma_Cross_CDVcandleHigh = array.get(arr_cdvHigh, 0) color CDVma_Cross_colorShadow = array.get(arr_shadowColor, 0) ////////////////////////////////////////////////// // ===== CDVma Shadow break logic //================================================== // CDV MA Break Shadow – State Management (Array-based) //================================================== //-------------------------------------------------- // WAIT BREAK STATE (Buy / Sell) //-------------------------------------------------- var bool[] arr_waitbreak_buy = array.new_bool(2, false) // [0]=current, [1]=previous var bool[] arr_waitbreak_sell = array.new_bool(2, false) //-------------------------------------------------- // SIGNAL STATE // 0 = no signal // 1 = BUY // -1 = SELL //-------------------------------------------------- var int[] arr_breakshadow_state = array.new_int(2, 0) //-------------------------------------------------- // UPDATE WAIT-BREAK FLAGS (ON BAR CLOSE) //-------------------------------------------------- // Shift previous state array.set(arr_waitbreak_buy , 1, array.get(arr_waitbreak_buy , 0)) array.set(arr_waitbreak_sell, 1, array.get(arr_waitbreak_sell, 0)) // New cross candle → allow waiting for break if IsCDVma_CrossCandle array.set(arr_waitbreak_buy , 0, true) array.set(arr_waitbreak_sell, 0, true) else // Keep previous state array.set(arr_waitbreak_buy , 0, array.get(arr_waitbreak_buy , 1)) array.set(arr_waitbreak_sell, 0, array.get(arr_waitbreak_sell, 1)) //-------------------------------------------------- // MA VOLUME CONDITION //-------------------------------------------------- breakshadow_maLength = CDVmaLength breakshadow_MAVol = ta.sma(volume, breakshadow_maLength) breakshadow_volCondition = CDVma_shadow_break_useMAVol ? (volume > breakshadow_MAVol * CDVma_shadow_break_VolRatio) : (volume > volume[1]) //-------------------------------------------------- // BREAK SHADOW CONDITIONS //-------------------------------------------------- breakshadow_cond_buy = close >= CDVma_Cross_candleHigh and (breakshadow_volCondition or c_ > CDVma_Cross_CDVcandleHigh) and close >= open and close > high[1] breakshadow_cond_sell = close <= CDVma_Cross_candleLow and (breakshadow_volCondition or c_ < CDVma_Cross_CDVcandleLow) and close <= open and close < low[1] //-------------------------------------------------- // DETECT NEW SIGNAL (ON BAR CLOSE) //-------------------------------------------------- int breakshadow_cond_new_signal = 0 int prevState = array.get(arr_breakshadow_state, 0) if breakshadow_cond_buy and prevState != 1 breakshadow_cond_new_signal := 1 else if breakshadow_cond_sell and prevState != -1 breakshadow_cond_new_signal := -1 //-------------------------------------------------- // UPDATE SIGNAL STATE //-------------------------------------------------- // Shift previous state array.set(arr_breakshadow_state, 1, array.get(arr_breakshadow_state, 0)) // Update current state if breakshadow_cond_new_signal != 0 array.set(arr_breakshadow_state, 0, breakshadow_cond_new_signal) else array.set(arr_breakshadow_state, 0, array.get(arr_breakshadow_state, 1)) //-------------------------------------------------- // OUTPUT STATES (FOR EA / OTHER LOGIC) //-------------------------------------------------- // 1 = BUY // -1 = SELL // 0 = NONE bool CDVma_waitBreakBuy = array.get(arr_waitbreak_buy , 0) bool CDVma_waitBreakSell = array.get(arr_waitbreak_sell, 0) int CDVma_breakSignalState = array.get(arr_breakshadow_state, 0) ////////////////////////////////////////////////// // ===== CDVma Shadow Trend logic //──────────────────────────────────────────────────────────────────────────── // CDVma_Cross Shadow TREND (COMPACT – ARRAY BASED) //──────────────────────────────────────────────────────────────────────────── // === Trend State === // 1 = Up Trend // -1 = Down Trend // 0 = Neutral var int[] arr_trendState = array.new_int(2, 0) // === Trend Zones === var float[] arr_trendUp_upper = array.new_float(2, na) var float[] arr_trendUp_lower = array.new_float(2, na) var float[] arr_trendDown_upper = array.new_float(2, na) var float[] arr_trendDown_lower = array.new_float(2, na) var float[] arr_trend_mid = array.new_float(2, na) //────────────────── // Trend Conditions //────────────────── // Up Trend condition bool CDVma_isTrendUp = (CDVma_Cross_crossValid and CDVma_crossUp_strong and (not CDVma_Cross_hasPrev or low >= CDVma_Cross_candleHigh_prev)) or (close > CDVma_Cross_candleHigh_prev and close > CDVma_Cross_candleHigh) // Down Trend condition bool CDVma_isTrendDown = (CDVma_Cross_crossValid and CDVma_crossDown_strong and (not CDVma_Cross_hasPrev or high <= CDVma_Cross_candleLow_prev)) or (close < CDVma_Cross_candleLow_prev and close < CDVma_Cross_candleLow) //────────────────── // Update Trend State //────────────────── // push previous trend state array.set(arr_trendState, 1, array.get(arr_trendState, 0)) // assign current trend state if CDVma_isTrendUp and close > high[1] array.set(arr_trendState, 0, 1) else if CDVma_isTrendDown and close < low[1] array.set(arr_trendState, 0, -1) else array.set(arr_trendState, 0, array.get(arr_trendState, 1)) //────────────────── // Detect New Trend //────────────────── bool CDVma_isNewTrendUp = array.get(arr_trendState, 0) == 1 and array.get(arr_trendState, 1) != 1 bool CDVma_isNewTrendDown = array.get(arr_trendState, 0) == -1 and array.get(arr_trendState, 1) != -1 //────────────────── // Push Previous Zones //────────────────── array.set(arr_trendUp_upper, 1, array.get(arr_trendUp_upper, 0)) array.set(arr_trendUp_lower, 1, array.get(arr_trendUp_lower, 0)) array.set(arr_trendDown_upper, 1, array.get(arr_trendDown_upper, 0)) array.set(arr_trendDown_lower, 1, array.get(arr_trendDown_lower, 0)) array.set(arr_trend_mid, 1, array.get(arr_trend_mid, 0)) //────────────────── // Create New Trend Zones //────────────────── // New Up Trend if CDVma_isNewTrendUp array.set(arr_trendUp_upper, 0, math.max(open, close)) array.set(arr_trendUp_lower, 0, math.min(CDVma_Cross_candleLow, CDVma_Cross_candleLow_prev)) array.set(arr_trend_mid, 0, math.min(CDVma_Cross_candleHigh, CDVma_Cross_candleHigh_prev)) // New Down Trend if CDVma_isNewTrendDown array.set(arr_trendDown_upper, 0, math.max(CDVma_Cross_candleHigh, CDVma_Cross_candleHigh_prev)) array.set(arr_trendDown_lower, 0, math.min(open, close)) array.set(arr_trend_mid, 0, math.max(CDVma_Cross_candleLow, CDVma_Cross_candleLow_prev)) //────────────────── // Export Values //────────────────── int CDVma_trendState = array.get(arr_trendState, 0) float CDVma_TrendUp_upper = array.get(arr_trendUp_upper, 0) float CDVma_TrendUp_lower = array.get(arr_trendUp_lower, 0) float CDVma_TrendDown_upper = array.get(arr_trendDown_upper, 0) float CDVma_TrendDown_lower = array.get(arr_trendDown_lower, 0) float CDVma_Trend_mid = array.get(arr_trend_mid, 0) ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// // ===== ===== All CDVma plot + signal // ===== Plot line MA of CDV Candles plot(showCDVMA ? CDVmaLine : na, color= CDVmaLine_color, linewidth=CDVmaWidth, title="MA of CDV") // ===== CDVma Shadow plot_CDVma_Cross_candleLow = plot(showCDVma_shadow and CDVma_Cross_candleLow == CDVma_Cross_candleLow[1] ? CDVma_Cross_CDVcandleLow : na, "Shadow Low", color = CDVma_Cross_colorShadow, style = plot.style_steplinebr) // add Alert, Send Notification, Send Mail when CDVma_Cross_candleLow != CDVma_Cross_candleLow[1] plot_CDVma_Cross_candleHigh = plot(showCDVma_shadow and CDVma_Cross_candleHigh == CDVma_Cross_candleHigh[1] ? CDVma_Cross_CDVcandleHigh : na, "Shadow High", color = CDVma_Cross_colorShadow, style = plot.style_steplinebr) // add Alert, Send Notification, Send Mail when CDVma_Cross_candleLow != CDVma_Cross_candleLow[1] // add fill as background CDVma_Cross_fillcolorShadow = c_ > CDVma_Cross_CDVcandleHigh ? CDVma_colorup : c_ < CDVma_Cross_CDVcandleLow ? CDVma_colordown : color.yellow fill(plot_CDVma_Cross_candleHigh, plot_CDVma_Cross_candleLow, color = color.new(CDVma_Cross_fillcolorShadow, CDVma_shadow_transp)) ////////////////////////////////////////////////// // ===== CDVma Shadow break plotshape(showCDVma_shadow_break and breakshadow_cond_new_signal == 1 ? l_ - (h_ - l_) / 2 : na, "Shadow Break up", style = shape.triangleup, location = location.absolute, color = CDVma_colorup, size = size.tiny) // add Alert, Send Notification, Send Mail plotshape(showCDVma_shadow_break and breakshadow_cond_new_signal == -1 ? h_ + (h_ - l_) / 2 : na, "Shadow Break down", style = shape.triangledown, location = location.absolute, color = CDVma_colordown, size = size.tiny) // add Alert, Send Notification, Send Mail ////////////////////////////////////////////////// // ===== CDVma Shadow trend //──────────────────────────────────────────────────────────── // Plotshape Signals for Trend Up / Trend Down (First bar of new trend) //──────────────────────────────────────────────────────────── // Plotshape for Trend Up: plotshape( showCDVma_trend_signal and CDVma_isNewTrendUp ? l_ - (h_ - l_) / 2 : na, title = "CDVma Trend Up", style = shape.triangleup, location = location.absolute, color = CDVma_colorup, size = size.small) // Plotshape for Trend Down: // Appears at the high of the candle plotshape( showCDVma_trend_signal and CDVma_isNewTrendDown ? h_ + (h_ - l_) / 2 : na, title = "CDVma Trend Down", style = shape.triangledown, location = location.absolute, color = CDVma_colordown, size = size.small) //──────────────────────────────────────────────────────────────────────────── // Background Coloring Based on Trend State //──────────────────────────────────────────────────────────────────────────── // If Trend Up → use CDVma_colorup // If Trend Down → use CDVma_colordown // If Neutral → use yellow color bgcolor(showCDVma_trend_bg and CDVma_trendState == 1 ? color.new(CDVma_colorup, CDVma_trend_bg_transp) : showCDVma_trend_bg and CDVma_trendState == -1 ? color.new(CDVma_colordown, CDVma_trend_bg_transp) : color.new(color.yellow, CDVma_trend_bg_transp)) ////////////////////////////////////////////////// ////////////////////////////////////////////////// //////////////////////////////////////////////////