// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. // If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/ // © Venture Lab – https://venturelab-bots.pages.dev/pine/ // // RSI with regular divergence marks. // What it does: plots the RSI and marks REGULAR divergences between two confirmed pivots: // bullish = price makes a lower low while the RSI makes a higher low, // bearish = price makes a higher high while the RSI makes a lower high. // What it does NOT do: it does not predict price, it is not a trading system and it is not financial advice. // A pivot is only confirmed "Pivot lookback right" bars after it happened, so every mark appears that many // bars late in real time (it is drawn back at the pivot bar). Hidden divergences are not detected. //@version=6 indicator("RSI with Divergence Marks [Venture Lab]", shorttitle = "RSI Div", overlay = false, max_lines_count = 500) // ---- Inputs int rsiLen = input.int(14, "RSI length", minval = 2) float src = input.source(close, "RSI source") int lbL = input.int(5, "Pivot lookback left", minval = 1) int lbR = input.int(5, "Pivot lookback right", minval = 1) int rangeMin = input.int(5, "Min bars between pivots", minval = 1) int rangeMax = input.int(60, "Max bars between pivots", minval = 2) bool showBull = input.bool(true, "Show bullish divergence") bool showBear = input.bool(true, "Show bearish divergence") // ---- RSI and pivots (calculated on every bar, outside of any condition) float rsi = ta.rsi(src, rsiLen) float plRsi = ta.pivotlow(rsi, lbL, lbR) float phRsi = ta.pivothigh(rsi, lbL, lbR) // ---- State of the previous confirmed pivots var float prevLowRsi = na var float prevLowPrice = na var int prevLowBar = na var float prevHighRsi = na var float prevHighPrice = na var int prevHighBar = na bool bullDiv = false bool bearDiv = false if not na(plRsi) float curPrice = low[lbR] int curBar = bar_index - lbR if not na(prevLowBar) int gap = curBar - prevLowBar bullDiv := gap >= rangeMin and gap <= rangeMax and curPrice < prevLowPrice and plRsi > prevLowRsi if bullDiv and showBull line.new(prevLowBar, prevLowRsi, curBar, plRsi, color = color.green, width = 2) prevLowRsi := plRsi prevLowPrice := curPrice prevLowBar := curBar if not na(phRsi) float curPrice = high[lbR] int curBar = bar_index - lbR if not na(prevHighBar) int gap = curBar - prevHighBar bearDiv := gap >= rangeMin and gap <= rangeMax and curPrice > prevHighPrice and phRsi < prevHighRsi if bearDiv and showBear line.new(prevHighBar, prevHighRsi, curBar, phRsi, color = color.red, width = 2) prevHighRsi := phRsi prevHighPrice := curPrice prevHighBar := curBar // ---- Plots plot(rsi, "RSI", color = color.purple, linewidth = 2) hline(70, "Overbought", color = color.gray, linestyle = hline.style_dashed) hline(50, "Middle", color = color.gray, linestyle = hline.style_dotted) hline(30, "Oversold", color = color.gray, linestyle = hline.style_dashed) plotshape(showBull and bullDiv ? plRsi : na, "Bullish divergence", shape.labelup, location.absolute, color.green, offset = -lbR, text = "Bull", textcolor = color.white, size = size.tiny) plotshape(showBear and bearDiv ? phRsi : na, "Bearish divergence", shape.labeldown, location.absolute, color.red, offset = -lbR, text = "Bear", textcolor = color.white, size = size.tiny) // ---- Alerts (fire on the bar where the divergence is confirmed, i.e. lbR bars after the pivot) alertcondition(bullDiv, "Bullish RSI divergence", "Bullish RSI divergence confirmed on {{ticker}} ({{interval}})") alertcondition(bearDiv, "Bearish RSI divergence", "Bearish RSI divergence confirmed on {{ticker}} ({{interval}})")