//@version=6 indicator('COMBO=Divergence for Many Indicators v4+Linear Regression Channel', overlay=true, max_bars_back=1000, max_lines_count=400, max_labels_count=400) // ########## 1=indicator=Divergence for Many Indicators v4 ########## prd = input.int(defval=5, title='Pivot Period', minval=1, maxval=50) source = input.string(defval='Close', title='Source for Pivot Points', options=['Close', 'High/Low']) searchdiv = input.string(defval='Regular', title='Divergence Type', options=['Regular', 'Hidden', 'Regular/Hidden']) showindis = input.string(defval='Full', title='Show Indicator Names', options=['Full', 'First Letter', 'Do Not Show']) showlimit = input.int(1, title='Minimum Number of Divergences', minval=1, maxval=11) maxpp = input.int(defval=10, title='Max. Pivot Points to Check', minval=1, maxval=20) maxbars = input.int(defval=100, title='Max. Bars to Check', minval=30, maxval=200) shownum = input(defval=true, title='Show Divergence Number') showlast = input(defval=false, title='Show Only Last Divergence') dontconfirm = input(defval=false, title='Do Not Wait for Confirmation') showlines = input(defval=true, title='Show Divergence Lines') showpivot = input(defval=false, title='Show Pivot Points') calcmacd = input(defval=true, title='MACD') calcmacda = input(defval=true, title='MACD Histogram') calcrsi = input(defval=true, title='RSI') calcstoc = input(defval=true, title='Stochastic') calccci = input(defval=true, title='CCI') calcmom = input(defval=true, title='Momentum') calcobv = input(defval=true, title='OBV') calcvwmacd = input(true, title='VWmacd') calccmf = input(true, title='Chaikin Money Flow') calcmfi = input(true, title='Money Flow Index') calcext = input(false, title='Check External Indicator') externalindi = input(defval=close, title='External Indicator') pos_reg_div_col = input(defval=color.yellow, title='Positive Regular Divergence Color') neg_reg_div_col = input(defval=color.navy, title='Negative Regular Divergence Color') pos_hid_div_col = input(defval=color.lime, title='Positive Hidden Divergence Color') neg_hid_div_col = input(defval=color.red, title='Negative Hidden Divergence Color') pos_div_text_col = input(defval=color.black, title='Positive Divergence Text Color') neg_div_text_col = input(defval=color.white, title='Negative Divergence Text Color') reg_div_l_style_ = input.string(defval='Solid', title='Regular Divergence Line Style', options=['Solid', 'Dashed', 'Dotted']) hid_div_l_style_ = input.string(defval='Dashed', title='Hidden Divergence Line Style', options=['Solid', 'Dashed', 'Dotted']) reg_div_l_width = input.int(defval=2, title='Regular Divergence Line Width', minval=1, maxval=5) hid_div_l_width = input.int(defval=1, title='Hidden Divergence Line Width', minval=1, maxval=5) // Set line styles var reg_div_l_style = reg_div_l_style_ == 'Solid' ? line.style_solid : reg_div_l_style_ == 'Dashed' ? line.style_dashed : line.style_dotted var hid_div_l_style = hid_div_l_style_ == 'Solid' ? line.style_solid : hid_div_l_style_ == 'Dashed' ? line.style_dashed : line.style_dotted // Get indicator values rsi = ta.rsi(close, 14) // RSI [macd, signal, deltamacd] = ta.macd(close, 12, 26, 9) // MACD moment = ta.mom(close, 10) // Momentum cci = ta.cci(close, 10) // CCI Obv = ta.obv // OBV stk = ta.sma(ta.stoch(close, high, low, 14), 3) // Stochastic maFast = ta.vwma(close, 12) // Fast VWMA maSlow = ta.vwma(close, 26) // Slow VWMA vwmacd = maFast - maSlow // VWmacd Cmfm = (close - low - (high - close)) / (high - low) // Chaikin Money Flow (intermediate value) Cmfv = Cmfm * volume // Chaikin Money Flow (volume value) cmf = ta.sma(Cmfv, 21) / ta.sma(volume, 21) // Chaikin Money Flow (smoothed) Mfi = ta.mfi(close, 14) // Money Flow Index // Arrays for indicator names and divergence colors var indicators_name = array.new_string(11) var div_colors = array.new_color(4) if barstate.isfirst // Indicator names array.set(indicators_name, 0, showindis == 'Full' ? 'MACD' : showindis == 'First Letter' ? 'M' : '') array.set(indicators_name, 1, showindis == 'Full' ? 'Hist' : showindis == 'First Letter' ? 'H' : '') array.set(indicators_name, 2, showindis == 'Full' ? 'RSI' : showindis == 'First Letter' ? 'R' : '') array.set(indicators_name, 3, showindis == 'Full' ? 'Stoch' : showindis == 'First Letter' ? 'S' : '') array.set(indicators_name, 4, showindis == 'Full' ? 'CCI' : showindis == 'First Letter' ? 'C' : '') array.set(indicators_name, 5, showindis == 'Full' ? 'MOM' : showindis == 'First Letter' ? 'M' : '') array.set(indicators_name, 6, showindis == 'Full' ? 'OBV' : showindis == 'First Letter' ? 'O' : '') array.set(indicators_name, 7, showindis == 'Full' ? 'VWMACD' : showindis == 'First Letter' ? 'V' : '') array.set(indicators_name, 8, showindis == 'Full' ? 'CMF' : showindis == 'First Letter' ? 'C' : '') array.set(indicators_name, 9, showindis == 'Full' ? 'MFI' : showindis == 'First Letter' ? 'M' : '') array.set(indicators_name, 10, showindis == 'Full' ? 'Ext' : showindis == 'First Letter' ? 'E' : '') // Divergence colors array.set(div_colors, 0, pos_reg_div_col) array.set(div_colors, 1, neg_reg_div_col) array.set(div_colors, 2, pos_hid_div_col) array.set(div_colors, 3, neg_hid_div_col) // Check for new pivot points (High/Low) float ph = ta.pivothigh(source == 'Close' ? close : high, prd, prd) float pl = ta.pivotlow(source == 'Close' ? close : low, prd, prd) plotshape(bool(ph) and showpivot, text='H', style=shape.labeldown, color=color.new(color.white, 100), textcolor=color.new(color.red, 0), location=location.abovebar, offset=-prd) plotshape(bool(pl) and showpivot, text='L', style=shape.labelup, color=color.new(color.white, 100), textcolor=color.new(color.lime, 0), location=location.belowbar, offset=-prd) // Arrays for storing pivot point positions and values var int maxarraysize = 20 var ph_positions = array.new_int(maxarraysize, 0) var pl_positions = array.new_int(maxarraysize, 0) var ph_vals = array.new_float(maxarraysize, 0.) var pl_vals = array.new_float(maxarraysize, 0.) // Add High points to array if bool(ph) array.unshift(ph_positions, bar_index) array.unshift(ph_vals, ph) if array.size(ph_positions) > maxarraysize array.pop(ph_positions) array.pop(ph_vals) // Add Low points to array if bool(pl) array.unshift(pl_positions, bar_index) array.unshift(pl_vals, pl) if array.size(pl_positions) > maxarraysize array.pop(pl_positions) array.pop(pl_vals) // Functions for checking divergences // Function for checking positive regular or negative hidden divergence // cond == 1 => positive regular, cond == 2 => negative hidden positive_regular_positive_hidden_divergence(src, cond) => divlen = 0 prsc = source == 'Close' ? close : low // If indicator is above last value and close price is above last close price if dontconfirm or src > src[1] or close > close[1] startpoint = dontconfirm ? 0 : 1 // do not check the last candle // Search last 15 pivot points for x = 0 to maxpp - 1 by 1 len = bar_index - array.get(pl_positions, x) + prd // If reached uninitialized array element or exceeded bar limit, stop search if array.get(pl_positions, x) == 0 or len > maxbars break if len > 5 and (cond == 1 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(pl_vals, x)) or cond == 2 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(pl_vals, x))) slope1 = (src[startpoint] - src[len]) / (len - startpoint) virtual_line1 = src[startpoint] - slope1 slope2 = (close[startpoint] - close[len]) / (len - startpoint) virtual_line2 = close[startpoint] - slope2 arrived = true for y = 1 + startpoint to len - 1 by 1 if src[y] < virtual_line1 or nz(close[y]) < virtual_line2 arrived := false break virtual_line1 := virtual_line1 - slope1 virtual_line2 := virtual_line2 - slope2 virtual_line2 if arrived divlen := len break divlen // Function for checking negative regular or positive hidden divergence // cond == 1 => negative regular, cond == 2 => positive hidden negative_regular_negative_hidden_divergence(src, cond) => divlen = 0 prsc = source == 'Close' ? close : high // If indicator is below last value and close price is below last close price if dontconfirm or src < src[1] or close < close[1] startpoint = dontconfirm ? 0 : 1 // do not check the last candle // Search last 15 pivot points for x = 0 to maxpp - 1 by 1 len = bar_index - array.get(ph_positions, x) + prd // If reached uninitialized array element or exceeded bar limit, stop search if array.get(ph_positions, x) == 0 or len > maxbars break if len > 5 and (cond == 1 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(ph_vals, x)) or cond == 2 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(ph_vals, x))) slope1 = (src[startpoint] - src[len]) / (len - startpoint) virtual_line1 = src[startpoint] - slope1 slope2 = (close[startpoint] - nz(close[len])) / (len - startpoint) virtual_line2 = close[startpoint] - slope2 arrived = true for y = 1 + startpoint to len - 1 by 1 if src[y] > virtual_line1 or nz(close[y]) > virtual_line2 arrived := false break virtual_line1 := virtual_line1 - slope1 virtual_line2 := virtual_line2 - slope2 virtual_line2 if arrived divlen := len break divlen // Calculate 4 types of divergences if enabled in settings, and return result in array calculate_divs(cond, indicator_1) => divs = array.new_int(4, 0) array.set(divs, 0, cond and (searchdiv == 'Regular' or searchdiv == 'Regular/Hidden') ? positive_regular_positive_hidden_divergence(indicator_1, 1) : 0) array.set(divs, 1, cond and (searchdiv == 'Regular' or searchdiv == 'Regular/Hidden') ? negative_regular_negative_hidden_divergence(indicator_1, 1) : 0) array.set(divs, 2, cond and (searchdiv == 'Hidden' or searchdiv == 'Regular/Hidden') ? positive_regular_positive_hidden_divergence(indicator_1, 2) : 0) array.set(divs, 3, cond and (searchdiv == 'Hidden' or searchdiv == 'Regular/Hidden') ? negative_regular_negative_hidden_divergence(indicator_1, 2) : 0) divs // Array for storing all divergences var all_divergences = array.new_int(44) // 11 indicators * 4 divergences = 44 elements // Set corresponding array elements array_set_divs(div_pointer, index) => for x = 0 to 3 by 1 array.set(all_divergences, index * 4 + x, array.get(div_pointer, x)) // Set divergence array array_set_divs(calculate_divs(calcmacd, macd), 0) array_set_divs(calculate_divs(calcmacda, deltamacd), 1) array_set_divs(calculate_divs(calcrsi, rsi), 2) array_set_divs(calculate_divs(calcstoc, stk), 3) array_set_divs(calculate_divs(calccci, cci), 4) array_set_divs(calculate_divs(calcmom, moment), 5) array_set_divs(calculate_divs(calcobv, Obv), 6) array_set_divs(calculate_divs(calcvwmacd, vwmacd), 7) array_set_divs(calculate_divs(calccmf, cmf), 8) array_set_divs(calculate_divs(calcmfi, Mfi), 9) array_set_divs(calculate_divs(calcext, externalindi), 10) // Check minimum number of divergences, if less than showlimit, remove all divergences total_div = 0 for x = 0 to array.size(all_divergences) - 1 by 1 total_div := total_div + math.round(math.sign(array.get(all_divergences, x))) total_div if total_div < showlimit array.fill(all_divergences, 0) // Arrays for storing divergence lines and labels var pos_div_lines = array.new_line(0) var neg_div_lines = array.new_line(0) var pos_div_labels = array.new_label(0) var neg_div_labels = array.new_label(0) // Delete old lines and labels if showlast option is enabled delete_old_pos_div_lines() => if array.size(pos_div_lines) > 0 for j = 0 to array.size(pos_div_lines) - 1 by 1 line.delete(array.get(pos_div_lines, j)) array.clear(pos_div_lines) delete_old_neg_div_lines() => if array.size(neg_div_lines) > 0 for j = 0 to array.size(neg_div_lines) - 1 by 1 line.delete(array.get(neg_div_lines, j)) array.clear(neg_div_lines) delete_old_pos_div_labels() => if array.size(pos_div_labels) > 0 for j = 0 to array.size(pos_div_labels) - 1 by 1 label.delete(array.get(pos_div_labels, j)) array.clear(pos_div_labels) delete_old_neg_div_labels() => if array.size(neg_div_labels) > 0 for j = 0 to array.size(neg_div_labels) - 1 by 1 label.delete(array.get(neg_div_labels, j)) array.clear(neg_div_labels) // Delete last created lines and labels before new High/Low point delete_last_pos_div_lines_label(n) => if n > 0 and array.size(pos_div_lines) >= n asz = array.size(pos_div_lines) for j = 1 to n by 1 line.delete(array.get(pos_div_lines, asz - j)) array.pop(pos_div_lines) if array.size(pos_div_labels) > 0 label.delete(array.get(pos_div_labels, array.size(pos_div_labels) - 1)) array.pop(pos_div_labels) delete_last_neg_div_lines_label(n) => if n > 0 and array.size(neg_div_lines) >= n asz = array.size(neg_div_lines) for j = 1 to n by 1 line.delete(array.get(neg_div_lines, asz - j)) array.pop(neg_div_lines) if array.size(neg_div_labels) > 0 label.delete(array.get(neg_div_labels, array.size(neg_div_labels) - 1)) array.pop(neg_div_labels) // For deleting lines/labels before new High/Low point var last_pos_div_lines = 0 var last_neg_div_lines = 0 var remove_last_pos_divs = false var remove_last_neg_divs = false if bool(pl) remove_last_pos_divs := false last_pos_div_lines := 0 last_pos_div_lines if bool(ph) remove_last_neg_divs := false last_neg_div_lines := 0 last_neg_div_lines // Drawing divergence lines and labels divergence_text_top = '' divergence_text_bottom = '' distances = array.new_int(0) dnumdiv_top = 0 dnumdiv_bottom = 0 top_label_col = color.white bottom_label_col = color.white old_pos_divs_can_be_removed = true old_neg_divs_can_be_removed = true startpoint = dontconfirm ? 0 : 1 // used for "Do Not Wait for Confirmation" option for x = 0 to 10 by 1 div_type = -1 for y = 0 to 3 by 1 if array.get(all_divergences, x * 4 + y) > 0 // is there a divergence? div_type := y if y % 2 == 1 dnumdiv_top := dnumdiv_top + 1 top_label_col := array.get(div_colors, y) top_label_col if y % 2 == 0 dnumdiv_bottom := dnumdiv_bottom + 1 bottom_label_col := array.get(div_colors, y) bottom_label_col if not array.includes(distances, array.get(all_divergences, x * 4 + y)) // line does not exist yet? array.push(distances, array.get(all_divergences, x * 4 + y)) new_line = showlines ? line.new(x1=bar_index - array.get(all_divergences, x * 4 + y), y1=source == 'Close' ? close[array.get(all_divergences, x * 4 + y)] : y % 2 == 0 ? low[array.get(all_divergences, x * 4 + y)] : high[array.get(all_divergences, x * 4 + y)], x2=bar_index - startpoint, y2=source == 'Close' ? close[startpoint] : y % 2 == 0 ? low[startpoint] : high[startpoint], color=array.get(div_colors, y), style=y < 2 ? reg_div_l_style : hid_div_l_style, width=y < 2 ? reg_div_l_width : hid_div_l_width) : na if y % 2 == 0 if old_pos_divs_can_be_removed old_pos_divs_can_be_removed := false if not showlast and remove_last_pos_divs delete_last_pos_div_lines_label(last_pos_div_lines) last_pos_div_lines := 0 last_pos_div_lines if showlast delete_old_pos_div_lines() array.push(pos_div_lines, new_line) last_pos_div_lines := last_pos_div_lines + 1 remove_last_pos_divs := true remove_last_pos_divs if y % 2 == 1 if old_neg_divs_can_be_removed old_neg_divs_can_be_removed := false if not showlast and remove_last_neg_divs delete_last_neg_div_lines_label(last_neg_div_lines) last_neg_div_lines := 0 last_neg_div_lines if showlast delete_old_neg_div_lines() array.push(neg_div_lines, new_line) last_neg_div_lines := last_neg_div_lines + 1 remove_last_neg_divs := true remove_last_neg_divs // Get text for labels if div_type >= 0 divergence_text_top := divergence_text_top + (div_type % 2 == 1 ? showindis != 'Do Not Show' ? array.get(indicators_name, x) + '\n' : '' : '') divergence_text_bottom := divergence_text_bottom + (div_type % 2 == 0 ? showindis != 'Do Not Show' ? array.get(indicators_name, x) + '\n' : '' : '') divergence_text_bottom // Draw labels if showindis != 'Do Not Show' or shownum if shownum and dnumdiv_top > 0 divergence_text_top := divergence_text_top + str.tostring(dnumdiv_top) divergence_text_top if shownum and dnumdiv_bottom > 0 divergence_text_bottom := divergence_text_bottom + str.tostring(dnumdiv_bottom) divergence_text_bottom if divergence_text_top != '' if showlast delete_old_neg_div_labels() array.push(neg_div_labels, label.new(x=bar_index, y=math.max(high, high[1]), text=divergence_text_top, color=top_label_col, textcolor=neg_div_text_col, style=label.style_label_down)) if divergence_text_bottom != '' if showlast delete_old_pos_div_labels() array.push(pos_div_labels, label.new(x=bar_index, y=math.min(low, low[1]), text=divergence_text_bottom, color=bottom_label_col, textcolor=pos_div_text_col, style=label.style_label_up)) // END // ---------------------------------------------------------------------------------------- // ########## 2=indicator=Linear Regression Channel ########## src = input(defval = close, title = 'Source') len = input.int(defval = 100, title = 'Length', minval = 10) devlen = input.float(defval = 2., title = 'Deviation', minval = 0.1, step = 0.1) extendit = input(defval = false, title = 'Extend Lines') showfibo = input(defval = false, title = 'Show Fibonacci Levels') showbroken = input.bool(defval = false, title = 'Show Broken Channel', inline = 'brk') brokencol = input.color(defval = color.blue, title = '', inline = 'brk') upcol = input.color(defval = color.lime, title = 'Up/Down Trend Colors', inline = 'trcols') dncol = input.color(defval = color.red, title = '', inline = 'trcols') widt = input(defval = 2, title = 'Line Width') var fibo_ratios = array.new_float(0) var colors = array.new_color(2) if barstate.isfirst array.unshift(colors, upcol) array.unshift(colors, dncol) array.push(fibo_ratios, 0.236) array.push(fibo_ratios, 0.382) array.push(fibo_ratios, 0.618) array.push(fibo_ratios, 0.786) get_channel(src, len) => mid = math.sum(src, len) / len slope = ta.linreg(src, len, 0) - ta.linreg(src, len, 1) intercept = mid - slope * math.floor(len / 2) + (1 - len % 2) / 2 * slope endy = intercept + slope * (len - 1) dev = 0.0 for x = 0 to len - 1 by 1 dev := dev + math.pow(src[x] - (slope * (len - x) + intercept), 2) dev dev := math.sqrt(dev / len) [intercept, endy, dev, slope] [y1_, y2_, dev, slope] = get_channel(src, len) outofchannel = slope > 0 and close < y2_ - dev * devlen ? 0 : slope < 0 and close > y2_ + dev * devlen ? 2 : -1 // Исправление: используем булево значение для alertcondition isChannelBroken = outofchannel != -1 var reglines = array.new_line(3) var fibolines = array.new_line(4) for x = 0 to 2 by 1 if not showbroken or outofchannel != x or nz(outofchannel[1], -1) != -1 line.delete(array.get(reglines, x)) else line.set_color(array.get(reglines, x), color = brokencol) line.set_width(array.get(reglines, x), width = 2) line.set_style(array.get(reglines, x), style = line.style_dotted) line.set_extend(array.get(reglines, x), extend = extend.none) array.set(reglines, x, line.new(x1 = bar_index - (len - 1), y1 = y1_ + dev * devlen * (x - 1), x2 = bar_index, y2 = y2_ + dev * devlen * (x - 1), color = array.get(colors, math.round(math.max(math.sign(slope), 0))), style = x % 2 == 1 ? line.style_solid : line.style_dashed, width = widt, extend = extendit ? extend.right : extend.none)) if showfibo for x = 0 to 3 by 1 line.delete(array.get(fibolines, x)) array.set(fibolines, x, line.new(x1 = bar_index - (len - 1), y1 = y1_ - dev * devlen + dev * devlen * 2 * array.get(fibo_ratios, x), x2 = bar_index, y2 = y2_ - dev * devlen + dev * devlen * 2 * array.get(fibo_ratios, x), color = array.get(colors, math.round(math.max(math.sign(slope), 0))), style = line.style_dotted, width = widt, extend = extendit ? extend.right : extend.none)) var label sidelab = label.new(x = bar_index - (len - 1), y = y1_, text = 'S', size = size.large) txt = slope > 0 ? slope > slope[1] ? '⇑' : '⇗' : slope < 0 ? slope < slope[1] ? '⇓' : '⇘' : '⇒' stl = slope > 0 ? slope > slope[1] ? label.style_label_up : label.style_label_upper_right : slope < 0 ? slope < slope[1] ? label.style_label_down : label.style_label_lower_right : label.style_label_right label.set_style(sidelab, stl) label.set_text(sidelab, txt) label.set_x(sidelab, bar_index - (len - 1)) label.set_y(sidelab, slope > 0 ? y1_ - dev * devlen : slope < 0 ? y1_ + dev * devlen : y1_) label.set_color(sidelab, slope > 0 ? upcol : slope < 0 ? dncol : color.blue) // Исправленные alertcondition alertcondition(isChannelBroken, title='Channel Broken', message='Channel Broken') // direction trendisup = math.sign(slope) != math.sign(slope[1]) and slope > 0 trendisdown = math.sign(slope) != math.sign(slope[1]) and slope < 0 alertcondition(trendisup, title='Up trend', message='Up trend') alertcondition(trendisdown, title='Down trend', message='Down trend') // END // ==========================================================================================