Oscillators measure momentum, overbought/oversold pressure, and trend strength. Most return a single stream; a few return several. The multi-output ones expose named streams so you can plot or test each component on its own instead of indexing into an array: macd.macd / .signal / .histogram, stoch.k / .d, adx as [ADX, DI+, DI-].
Every oscillator needs a warmup window. Until enough bars have loaded to fill its longest period, the value is na and nothing plots. RSI(14) is na for its seed window; MACD warms up over the slow EMA plus the signal period; ADX takes longest because it smooths directional movement twice. This is expected: leading bars are blank, then the line begins.
Reference
rsi
rsi(source, period?) — Relative Strength Index, bounded 0–100.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series (usually close) |
period | number | Lookback (default 14) |
Returns a single stream. Warmup is roughly period bars.
var rsiValue = rsi(source=close, period=14)wpr
wpr(length, source) — Williams %R over an OHLC source. Pass source explicitly.
| Parameter | Type | Description |
|---|---|---|
length | number | High/low lookback |
source | TimeSeries | OHLC source |
var wprValue = wpr(length=14, source=trade)cmo
cmo(source, length) — Chande Momentum Oscillator. It compares summed gains and losses over the lookback and returns 0 when up + down == 0.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
length | number | Momentum lookback |
var cmoValue = cmo(source=close, length=14)tsi
tsi(source, short, long) — True Strength Index. It double-smooths momentum and absolute momentum, then returns their ratio.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
short | number | Short smoothing length |
long | number | Long smoothing length |
var tsiValue = tsi(source=close, short=13, long=25)macd
macd(source, fastPeriod?, slowPeriod?, signalPeriod?) — Moving Average Convergence Divergence.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
fastPeriod | number | Fast EMA (default 12) |
slowPeriod | number | Slow EMA (default 26) |
signalPeriod | number | Signal EMA (default 9) |
Returns [MACD, Signal, Histogram], with named streams .macd, .signal, .histogram. Warmup runs over the slow EMA plus the signal period before the histogram settles. Plot the histogram against a zero baseline, or test crossover(m.macd, m.signal) for the classic signal-line cross.
var m = macd(source=close, fastPeriod=12, slowPeriod=26, signalPeriod=9)
plotLine(value=m.macd, colors=["#2563eb"], width=2, label=["MACD"], desc=["MACD line"])
plotLine(value=m.signal, colors=["#f97316"], width=2, label=["Signal"], desc=["signal line"])stoch
stoch(periodK?, smoothK?, periodD?) — Stochastic oscillator over the chart's OHLC.
| Parameter | Type | Description |
|---|---|---|
periodK | number | %K lookback (default 14) |
smoothK | number | %K smoothing (default 3) |
periodD | number | %D smoothing (default 3) |
Returns [%K, %D], named .k and .d. Both are bounded 0–100. This form reads OHLC implicitly; pass no source.
var s = stoch(periodK=14, smoothK=3, periodD=3)
plotLine(value=s.k, colors=["#0891b2"], width=2, label=["%K"], desc=["stochastic %K"])
plotLine(value=s.d, colors=["#be123c"], width=2, label=["%D"], desc=["stochastic %D"])stochastic
stochastic(source, kPeriod?, kSmoothing?, dPeriod?) — the explicit-source variant of the stochastic.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | OHLC series to read high/low/close from |
kPeriod | number | %K lookback (default 14) |
kSmoothing | number | %K smoothing (default 3) |
dPeriod | number | %D smoothing (default 3) |
Same math as stoch, but you hand it the source explicitly. Use this when you want the stochastic of a series you already opened.
var s = stochastic(source=trade, kPeriod=14, kSmoothing=3, dPeriod=3)cci
cci(source, period?, constant?) — Commodity Channel Index, oscillating around zero.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | OHLC series |
period | number | Lookback (default 20) |
constant | number | Scaling constant (default 0.015) |
Returns a single stream. Readings beyond +100 / −100 mark momentum extremes.
var cciValue = cci(source=trade, period=20, constant=0.015)mfi
mfi(source, period?) — Money Flow Index, a volume-weighted RSI bounded 0–100.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | OHLC series (needs volume) |
period | number | Lookback (default 14) |
Returns a single stream. Like RSI but it weights each bar by volume, so it reads pressure rather than price alone.
var mfiValue = mfi(source=trade, period=14)mom
mom(source, n?) — Momentum, the raw difference between the current value and the value n bars ago.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
n | number | Bars back to compare (default 10) |
Returns a single stream centered on zero. Positive means price is above where it was n bars ago.
var momValue = mom(source=close, n=10)adx
adx(source, period?) — Average Directional Index, plus the directional indicators.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | OHLC series |
period | number | Lookback (default 14) |
Returns [ADX, DI+, DI-]. ADX measures trend strength regardless of direction (above 25 is a strong trend, below 20 is a range); DI+ over DI− signals upward directional pressure. ADX warms up the slowest of the oscillators here because it smooths directional movement twice.
var a = adx(source=trade, period=14)
plotLine(value=a, colors=["#111827", "#2563eb", "#dc2626"], width=1, label=["ADX"], desc=["ADX, DI+, DI-"])obv
obv(source) — On-Balance Volume, a running cumulative volume line.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | OHLC series (needs volume) |
Returns a single cumulative stream with no period. It adds the bar's volume on up bars and subtracts it on down bars, so its slope tracks whether volume confirms price.
var obvValue = obv(source=trade)Putting them together
One script wiring every oscillator above, including the named-stream accessors for MACD and Stochastic. Note that multi-output indicators can be plotted whole (pass the array) or one stream at a time (pass .macd, .k, and so on).
//@version=2
define(title="Oscillators", position="offchart", axis=true)
timeseries trade = ohlcv(symbol=currentSymbol, exchange=currentExchange)
timeseries closeSeries = trade.close
var rsiValue = rsi(source=closeSeries, period=14)
var macdValue = macd(source=closeSeries, fastPeriod=12, slowPeriod=26, signalPeriod=9)
var stochValue = stoch(periodK=14, smoothK=3, periodD=3)
var stochasticValue = stochastic(source=trade, kPeriod=14, kSmoothing=3, dPeriod=3)
var cciValue = cci(source=trade, period=20, constant=0.015)
var mfiValue = mfi(source=trade, period=14)
var momValue = mom(source=closeSeries, n=10)
var adxValue = adx(source=trade, period=14)
var obvValue = obv(source=trade)
plotLine(value=rsiValue, colors=["#7c3aed"], width=2, label=["RSI"], desc=["14 period relative strength index"])
plotLine(value=macdValue, colors=["#2563eb", "#f97316", "#16a34a"], width=1, label=["MACD output"], desc=["MACD multi output"])
plotLine(value=macdValue.macd, colors=["#1d4ed8"], width=2, label=["MACD named"], desc=["macd.macd named stream"])
plotLine(value=macdValue.signal, colors=["#ea580c"], width=2, label=["Signal named"], desc=["macd.signal named stream"])
plotLine(value=macdValue.histogram, colors=["#15803d"], width=2, label=["Histogram named"], desc=["macd.histogram named stream"])
plotLine(value=stochValue, colors=["#0891b2", "#be123c"], width=1, label=["Stoch output"], desc=["Stoch multi output"])
plotLine(value=stochValue.k, colors=["#0e7490"], width=2, label=["K named"], desc=["stoch.k named stream"])
plotLine(value=stochValue.d, colors=["#be123c"], width=2, label=["D named"], desc=["stoch.d named stream"])
plotLine(value=stochasticValue, colors=["#0f766e", "#b45309"], width=1, label=["Stochastic output"], desc=["stochastic multi output"])
plotLine(value=cciValue, colors=["#4b5563"], width=2, label=["CCI"], desc=["20 period commodity channel index"])
plotLine(value=mfiValue, colors=["#16a34a"], width=2, label=["MFI"], desc=["14 period money flow index"])
plotLine(value=momValue, colors=["#9333ea"], width=2, label=["Momentum"], desc=["10 period momentum"])
plotLine(value=adxValue, colors=["#111827", "#2563eb", "#dc2626"], width=1, label=["ADX output"], desc=["ADX multi output"])
plotLine(value=obvValue, colors=["#0f766e"], width=2, label=["OBV"], desc=["on balance volume"])Pine-parity oscillators
This script wires wpr, cmo, and tsi together. Two extra lines make their edge behavior visible: WPR stays na until its length window fills, and CMO returns 0 on a flat series, where the summed gains and losses are both zero.
//@version=2
define(title="WPR CMO TSI", position="offchart", axis=true)
timeseries trade = ohlcv(symbol=currentSymbol, exchange=currentExchange)
timeseries closeSeries = trade.close
timeseries flatSeries = closeSeries - closeSeries + 100
var wprValue = wpr(length=14, source=trade)
var cmoValue = cmo(source=closeSeries, length=14)
var tsiValue = tsi(source=closeSeries, short=13, long=25)
var cmoFlat = cmo(source=flatSeries, length=5)
var wprWarmupCheck = (barIndex < 13 && isna(wprValue)) || (barIndex >= 13 && isnum(wprValue)) ? closeSeries : na
var cmoFlatCheck = barIndex >= 5 && cmoFlat == 0 ? closeSeries : na
plotLine(value=wprValue, colors=["#2563eb"], width=2, label=["WPR"], desc=["14 period Williams percent R"])
plotLine(value=cmoValue, colors=["#16a34a"], width=2, label=["CMO"], desc=["14 period Chande Momentum Oscillator"])
plotLine(value=tsiValue, colors=["#7c3aed"], width=2, label=["TSI"], desc=["True Strength Index short 13 long 25"])
plotLine(value=wprWarmupCheck, colors=["#dc2626"], width=2, label=["WPR warmup"], desc=["Williams percent R is na until its length window is ready"])
plotLine(value=cmoFlatCheck, colors=["#ea580c"], width=2, label=["CMO flat"], desc=["CMO returns zero when up plus down equals zero"])Warmup in practice
To see warmup directly, plot a few oscillators and watch where each line begins. The leading gap is the seed window: each line stays blank until its longest period has enough bars, then turns finite. ADX starts last, RSI and Stochastic start earliest.
//@version=2
define(title="Oscillator Warmup Boundary", position="offchart", axis=true)
timeseries trade = ohlcv(symbol=currentSymbol, exchange=currentExchange)
timeseries closeSeries = trade.close
var rsiValue = rsi(source=closeSeries, period=14)
var macdValue = macd(source=closeSeries, fastPeriod=12, slowPeriod=26, signalPeriod=9)
var stochValue = stoch(periodK=14, smoothK=3, periodD=3)
var adxValue = adx(source=trade, period=14)
plotLine(value=rsiValue, colors=["#7c3aed"], width=2, label=["RSI"], desc=["RSI finite values begin after its seed window"])
plotLine(value=macdValue.macd, colors=["#2563eb"], width=2, label=["MACD"], desc=["macd.macd finite values begin after its seed window"])
plotLine(value=stochValue.k, colors=["#0891b2"], width=2, label=["Stoch K"], desc=["stoch.k finite values begin after its seed window"])
plotLine(value=adxValue.adx, colors=["#111827"], width=2, label=["ADX"], desc=["adx.adx finite values begin after its seed window"])