//@version=6
// ============================================================================
// Relative Strength Line [WavesUnchained]
// Version: 2.0.2
// Author: WavesUnchained
// Build: 2026-06-30 00:00:00
// ============================================================================
// Relative strength of the chart symbol vs. a benchmark (SPY / QQQ / any),
// turned into an ACTIONABLE signal: a long/short mark fires only when relative
// strength AND the stock's own price trend agree (confluence) — so a signal can
// never contradict the chart (no "green while price falls").
//
// Features:
// ✓ RS line (price ÷ benchmark) or Mansfield RS oscillator (around zero)
// ✓ Mansfield RS: % distance of RS from its own moving average
// ✓ Confluence signal: LONG = outperforming benchmark AND price above its
// trend EMA; SHORT = underperforming AND price below it
// ✓ Markers follow trading convention: long below the line, short above
// ✓ Dashboard: relative strength, price trend, and the confluence verdict
// ✓ Right-edge tag with the live setup (LONG / SHORT / Neutral)
// ✓ Alerts: long/short confluence, Mansfield zero cross up/down
//
// ============================================================================
indicator("Relative Strength Line [WavesUnchained]", shorttitle="RS Line", overlay=false, max_labels_count=200)
// ─── Inputs ──────────────────────────────────────────────────────────────────
grpRS = "Relative Strength"
benchSym = input.symbol("AMEX:SPY", "Benchmark", group=grpRS,
tooltip="Symbol the chart is measured against. SPY = broad market (S&P 500), QQQ = Nasdaq 100 (better for tech/momentum names like TSLA, NET, MSFT).")
displayMode = input.string("Mansfield RS", "Display", options=["Mansfield RS", "Raw RS Line"], group=grpRS,
tooltip="Mansfield RS = normalized oscillator around zero (above 0 = outperforming the benchmark). Raw RS Line = the price/benchmark ratio itself; its slope is what matters, not the absolute level.")
mrsLen = input.int(50, "Mansfield MA Length", minval=5, group=grpRS,
tooltip="Moving-average length the Mansfield RS measures distance from. Weinstein's original uses ~52 weeks on weekly charts; 50 is a sensible all-timeframe default.")
grpSig = "Confluence Signal"
trendLen = input.int(50, "Price Trend EMA", minval=5, group=grpSig,
tooltip="EMA of the stock's own price that defines its absolute trend. A long signal needs price ABOVE this EMA (real uptrend) on top of relative strength — so signals never contradict the chart.")
showLead = input.bool(true, "Show Confluence Markers", group=grpSig)
minGap = input.int(5, "Min Bars Between Markers", minval=0, group=grpSig)
markerGap = input.float(0.4, "Marker Distance from Line", minval=0.0, maxval=2.0, step=0.1, group=grpSig, tooltip="Vertical gap between a marker and the line, in units of the RS line's standard deviation. 0 = right on the line.")
grpDisp = "Display"
showDash = input.bool(true, "Show Dashboard", group=grpDisp)
dashPos = input.string("Top Right", "Dashboard Position", options=["Top Right", "Top Left", "Bottom Right", "Bottom Left"], group=grpDisp)
bullC = input.color(#00c853, "Outperforming", group=grpDisp)
bearC = input.color(#d50000, "Underperforming", group=grpDisp)
// ─── Helpers ─────────────────────────────────────────────────────────────────
safeDiv(a, b) =>
b == 0.0 or na(b) ? na : a / b
// ─── Core: relative strength ─────────────────────────────────────────────────
benchClose = request.security(benchSym, timeframe.period, close, lookahead=barmerge.lookahead_off)
rs = safeDiv(close, benchClose)
// Mansfield RS: percentage distance of RS from its own moving average.
// Positive = RS above its mean → outperforming and accelerating; negative = lagging.
rsMa = ta.sma(rs, mrsLen)
mrs = safeDiv(rs - rsMa, rsMa) * 100.0
// ─── Confluence: relative strength AND absolute price direction agree ─────────
// A signal only fires when the stock is BOTH outperforming the benchmark
// (Mansfield > 0) AND in its own uptrend (price above its trend EMA). This is
// the actionable case — a relative leader that is also rising — and structurally
// rules out the contradictory "RS green while price falls".
priceEma = ta.ema(close, trendLen)
bool priceBull = close > priceEma
bool priceBear = close < priceEma
bool rsBull = not na(mrs) and mrs > 0
bool rsBear = not na(mrs) and mrs < 0
bool longRegime = priceBull and rsBull
bool shortRegime = priceBear and rsBear
// Fire on entry into the regime (not every bar), throttled by minGap
bool longEntry = longRegime and not longRegime[1]
bool shortEntry = shortRegime and not shortRegime[1]
var int lastUpBar = na
var int lastDownBar = na
bool fireUp = longEntry and (na(lastUpBar) or bar_index - lastUpBar >= minGap)
bool fireDown = shortEntry and (na(lastDownBar) or bar_index - lastDownBar >= minGap)
if fireUp
lastUpBar := bar_index
if fireDown
lastDownBar := bar_index
// ─── Plots ───────────────────────────────────────────────────────────────────
bool isMansfield = displayMode == "Mansfield RS"
plotSeries = isMansfield ? mrs : rs
plotColor = na(mrs) ? color.new(color.gray, 20) : (isMansfield ? (mrs >= 0 ? bullC : bearC) : (rs >= rsMa ? bullC : bearC))
plot(plotSeries, "RS", color=plotColor, linewidth=2)
plot(isMansfield ? na : rsMa, "RS MA", color=color.new(color.gray, 40), linewidth=1)
plot(isMansfield ? 0.0 : na, "Zero", color=color.new(color.gray, 55), linewidth=1)
// Mansfield fill for quick read of regime
mrsPlot = isMansfield ? mrs : na
zeroPlot = isMansfield ? 0.0 : na
p1 = plot(mrsPlot, display=display.none)
p2 = plot(zeroPlot, display=display.none)
fill(p1, p2, color=na(mrs) ? na : color.new(mrs >= 0 ? bullC : bearC, 88))
// Confluence markers are actionable long/short signals, so they follow the
// standard convention: green up-triangle BELOW the line (long), red down-triangle
// ABOVE (short). Offset uses the line's standard deviation for a steady gap.
markOff = ta.stdev(plotSeries, 50) * markerGap
upMark = showLead and fireUp ? plotSeries - markOff : na
dnMark = showLead and fireDown ? plotSeries + markOff : na
plotshape(upMark, "Long Confluence", shape.triangleup, location.absolute, color=color.new(bullC, 15), size=size.tiny)
plotshape(dnMark, "Short Confluence", shape.triangledown, location.absolute, color=color.new(bearC, 15), size=size.tiny)
// Live setup state (relative strength + price trend confluence)
string setupTxt = longRegime ? "LONG" : shortRegime ? "SHORT" : "Neutral"
color setupCol = longRegime ? bullC : shortRegime ? bearC : color.new(color.gray, 20)
// Single tidy tag at the right edge showing the live setup
var label rsTag = na
if barstate.islast
string tagTxt = longRegime ? "LONG ▲" : shortRegime ? "SHORT ▼" : "Neutral"
if na(rsTag)
rsTag := label.new(bar_index, plotSeries, tagTxt, xloc=xloc.bar_index, yloc=yloc.price,
style=label.style_label_left, textcolor=color.white, color=setupCol, size=size.small)
else
label.set_xy(rsTag, bar_index, plotSeries)
label.set_text(rsTag, tagTxt)
label.set_color(rsTag, setupCol)
// ─── Dashboard (light theme) ─────────────────────────────────────────────────
color tc = color.new(color.gray, 20)
color hd = color.new(color.gray, 90)
var table t = table.new(
dashPos == "Top Right" ? position.top_right : dashPos == "Top Left" ? position.top_left : dashPos == "Bottom Right" ? position.bottom_right : position.bottom_left,
2, 5,
bgcolor=color.new(color.white, 5),
border_color=color.new(color.gray, 60), border_width=1,
frame_color=color.new(color.gray, 40), frame_width=1)
if showDash and barstate.islast
string ptTxt = priceBull ? "Up ▲" : priceBear ? "Down ▼" : "Flat"
color ptCol = priceBull ? bullC : priceBear ? bearC : tc
benchName = str.replace_all(benchSym, "AMEX:", "")
benchName := str.replace_all(benchName, "NASDAQ:", "")
table.cell(t, 0, 0, "RS Line", text_color=tc, bgcolor=hd, text_size=size.small)
table.cell(t, 1, 0, "vs " + benchName, text_color=tc, bgcolor=hd, text_size=size.small)
// Relative strength (vs benchmark)
table.cell(t, 0, 1, "Rel. Strength", text_color=tc, text_size=size.small)
table.cell(t, 1, 1, na(mrs) ? "—" : (rsBull ? "Leads " : "Lags ") + str.tostring(mrs, "#.#") + "%", text_color=color.white, bgcolor=na(mrs) ? color.new(color.gray, 20) : (rsBull ? bullC : bearC), text_size=size.small)
// Absolute price trend
table.cell(t, 0, 2, "Price Trend", text_color=tc, text_size=size.small)
table.cell(t, 1, 2, ptTxt, text_color=ptCol, text_size=size.small)
// Confluence verdict — the actionable line
table.cell(t, 0, 3, "Setup", text_color=tc, text_size=size.small)
table.cell(t, 1, 3, setupTxt, text_color=color.white, bgcolor=setupCol, text_size=size.small)
// Reminder of what "Setup" needs
table.cell(t, 0, 4, "Needs", text_color=tc, text_size=size.small)
table.cell(t, 1, 4, "RS + trend agree", text_color=tc, text_size=size.small)
// ─── Alerts ──────────────────────────────────────────────────────────────────
mrsCrossUp = ta.crossover(mrs, 0)
mrsCrossDown = ta.crossunder(mrs, 0)
bool alertsOnBarClose = input.bool(true, "Alerts only on bar close (confirmed)", group="Alerts")
bool alertOk = not alertsOnBarClose or barstate.isconfirmed
alertcondition(alertOk and (fireUp), "RS Long Confluence", "RSL · Long Confluence · {{ticker}} {{interval}}")
alertcondition(alertOk and (fireDown), "RS Short Confluence", "RSL · Short Confluence · {{ticker}} {{interval}}")
alertcondition(alertOk and (mrsCrossUp), "Mansfield Cross Up", "RSL · Mansfield Cross Up · {{ticker}} {{interval}}")
alertcondition(alertOk and (mrsCrossDown), "Mansfield Cross Down", "RSL · Mansfield Cross Down · {{ticker}} {{interval}}")
Overview
Relative Strength Line [WavesUnchained] plots either a raw relative strength ratio or a Mansfield RS oscillator in a separate pane. Confluence signals trigger when relative strength performance aligns with the price trend relative to an exponential moving average. Configurable settings include the benchmark symbol, Mansfield moving average length, price trend EMA length, signal marker spacing, and dashboard display options.
Mansfield RS oscillator and raw relative strength line
Benchmark symbol comparison
Confluence signals combining relative strength and price trend
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
Benchmark
symbol
AMEX:SPY
benchSym
Display
string
Mansfield RS
displayMode
Mansfield MA Length
int
50
mrsLen
Price Trend EMA
int
50
trendLen
Show Confluence Markers
bool
true
showLead
Min Bars Between Markers
int
5
minGap
Marker Distance from Line
float
0.4
markerGap
Show Dashboard
bool
true
showDash
Dashboard Position
string
Top Right
dashPos
Outperforming
color
#00c853
bullC
Underperforming
color
#d50000
bearC
Alerts only on bar close (confirmed)
bool
true
alertsOnBarClose
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.
Multi-Timeframe Analysis Suite calculates trend direction and momentum conditions across five user-selected timeframes using moving averages, RSI, and Stochastic oscillators. It evaluates moving average slope and oscillator levels to compute trend alignment, m
KamaFama is an indicator that translates a Freqtrade trading strategy into Pine Script for visualization. It combines Kaufman Adaptive Moving Average (KAMA), MAMA/FAMA calculations derived via Hilbert Transform, Williams %R, and correlation trend filters to ev
Manias, Panics and Crashes is a separate-pane market regime indicator that quantifies market sentiment and systemic risk. It processes technical metrics including RSI, moving averages, and volume alongside optional intermarket data such as VIX volatility and c
Nexural Pressure Pro is a composite pressure indicator that measures directional market momentum using volume-weighted directional movement, order flow delta, aggression, and efficiency ratio metrics. It filters out low-activity bars using configurable volume
The Asset Rotation System evaluates relative trend strength and rotational performance across up to six selectable assets. It calculates trend classification based on user-selected technical indicators including RSI, CCI, SuperTrend, DMI, and Parabolic SAR. Th
This indicator analyzes historical candle direction and price range over a configurable lookback window to gauge market trend. It categorizes trend direction using candle count, price range sum, or both. Signals are filtered using a Simple Moving Average to en