Skip to content

Free TradingView indicator

True Strength Index

True Strength Index with signal line, difference histogram, signal-line crosses and zero-line crosses, all with alerts.

Momentumv1.0TradingView (Pine Script v6) Non-repainting signals Alerts

What it does

The True Strength Index (TSI), introduced by William Blau, is a momentum oscillator that double-smooths price changes. The result is a line between −100 and +100 that is much smoother than raw momentum yet still responsive.

This version adds a signal line, a histogram of the gap between TSI and its signal line, reference levels at ±25, and markers plus alerts for signal-line crosses and zero-line crosses.

How it works

  1. Price change = source − previous source.
  2. Double-smoothed change = EMA(EMA(price change, long), short).
  3. Double-smoothed absolute change = EMA(EMA(|price change|, long), short).
  4. TSI = 100 × double-smoothed change ÷ double-smoothed absolute change.
  5. Signal = EMA(TSI, signal length). Histogram = TSI − signal.

Because the numerator can never be larger than the denominator in size, TSI stays within ±100. A reading of +40 means recent smoothed movement has been strongly one-directional upward.

Signals, all confirmed on bar close:

  • TSI crosses above or below its signal line (small triangles).
  • TSI crosses above or below zero (circles).

How to use it

  • The zero line divides bullish from bearish momentum. A zero-line cross is slower and more meaningful for trend direction than a signal-line cross.
  • Signal-line crosses work better as timing tools in the direction of the zero-line reading: in positive territory, a cross back above the signal after a dip can mark the end of a pullback.
  • Readings beyond ±25 show stretched momentum. They are not automatic reversal signals but can warn that a move is extended.
  • Divergence between price and TSI can also be read manually, in the same way as with other oscillators. TSI's smoothness makes H1 to W1 charts a natural fit. Combine it with technical analysis basics such as structure and levels.

Settings

InputDefaultWhat it changes
SourceclosePrice used for momentum.
Long smoothing25First smoothing pass. Longer = slower.
Short smoothing13Second smoothing pass.
Signal length13Speed of the signal line.
Upper / lower reference level25 / −25Positions of the dashed reference lines.
Show signal-line crossesOnTriangle markers.
Show zero-line crossesOnCircle markers.
Show TSI − signal histogramOnGap histogram.

Limitations

  • Double smoothing means real lag: zero-line crosses usually come well after a turn in price.
  • Signal-line crosses are frequent in ranges and often reverse within a few bars.
  • The ±25 levels are conventions; how far TSI typically stretches varies by market and timeframe.
  • TSI measures momentum only and ignores volatility, levels and costs. Use it alongside a clear risk plan.

Pine Script source

In TradingView open Pine Editor, paste the code, click Save and then Add to chart.

FXP_TrueStrengthIndex.pine

61 lines

// © FXPIPS ONLINE — https://fxpips.online/tradingview-indicators/true-strength-index/
// License: MIT. Educational tool — not financial advice. Trading involves substantial risk.
//@version=6
// True Strength Index: double-smoothed price momentum divided by double-smoothed absolute
// momentum, scaled to ±100, with a signal line, signal-line crosses and zero-line crosses.
indicator("FXP True Strength Index", shorttitle = "FXP TSI", overlay = false)

// ── Inputs ─────────────────────────────────────────────────────────────
grpT     = "TSI"
src      = input.source(close, "Source", group = grpT)
longLen  = input.int(25, "Long smoothing", minval = 1, group = grpT)
shortLen = input.int(13, "Short smoothing", minval = 1, group = grpT)
sigLen   = input.int(13, "Signal length", minval = 1, group = grpT)

grpL      = "Levels"
upLevel   = input.float(25.0, "Upper reference level", minval = 0.0, maxval = 100.0, group = grpL)
downLevel = input.float(-25.0, "Lower reference level", minval = -100.0, maxval = 0.0, group = grpL)

grpS       = "Signals"
showSigX   = input.bool(true, "Show signal-line crosses", group = grpS)
showZeroX  = input.bool(true, "Show zero-line crosses", group = grpS)
showHist   = input.bool(true, "Show TSI − signal histogram", group = grpS)

grpV    = "Display"
colTsi  = input.color(#2962ff, "TSI line", group = grpV)
colSig  = input.color(#ff6d00, "Signal line", group = grpV)
colBull = input.color(#26a69a, "Bullish", group = grpV)
colBear = input.color(#ef5350, "Bearish", group = grpV)

// ── Calculation ────────────────────────────────────────────────────────
pc       = nz(ta.change(src))
dblPc    = ta.ema(ta.ema(pc, longLen), shortLen)
dblAbsPc = ta.ema(ta.ema(math.abs(pc), longLen), shortLen)
tsi      = dblAbsPc != 0 ? 100.0 * dblPc / dblAbsPc : 0.0
signal   = ta.ema(tsi, sigLen)
diff     = tsi - signal

sigUp   = ta.crossover(tsi, signal) and barstate.isconfirmed
sigDown = ta.crossunder(tsi, signal) and barstate.isconfirmed
zeroUp  = ta.crossover(tsi, 0) and barstate.isconfirmed
zeroDn  = ta.crossunder(tsi, 0) and barstate.isconfirmed

// ── Plots ──────────────────────────────────────────────────────────────
plot(showHist ? diff : na, "TSI − signal", color = diff >= 0 ? color.new(colBull, 60) : color.new(colBear, 60), style = plot.style_columns)
plot(tsi, "TSI", color = colTsi, linewidth = 2)
plot(signal, "Signal", color = colSig)
hline(0, "Zero line", color = color.new(color.gray, 40))
hline(upLevel, "Upper level", color = color.new(color.gray, 60), linestyle = hline.style_dashed)
hline(downLevel, "Lower level", color = color.new(color.gray, 60), linestyle = hline.style_dashed)

plotshape(showSigX and sigUp, "TSI crosses above signal", style = shape.triangleup, location = location.bottom, color = colBull, size = size.tiny)
plotshape(showSigX and sigDown, "TSI crosses below signal", style = shape.triangledown, location = location.top, color = colBear, size = size.tiny)
plotshape(showZeroX and zeroUp, "TSI crosses above zero", style = shape.circle, location = location.bottom, color = colBull, size = size.small)
plotshape(showZeroX and zeroDn, "TSI crosses below zero", style = shape.circle, location = location.top, color = colBear, size = size.small)

// ── Alerts ─────────────────────────────────────────────────────────────
alertcondition(sigUp, "TSI bullish signal cross", "TSI crossed above its signal line on {{ticker}} ({{interval}})")
alertcondition(sigDown, "TSI bearish signal cross", "TSI crossed below its signal line on {{ticker}} ({{interval}})")
alertcondition(zeroUp, "TSI above zero", "TSI crossed above zero on {{ticker}} ({{interval}})")
alertcondition(zeroDn, "TSI below zero", "TSI crossed below zero on {{ticker}} ({{interval}})")

Key inputs

Key inputs of True Strength Index
InputDefaultDescription
Long smoothing25First EMA applied to price change.
Short smoothing13Second EMA applied to the first.
Signal length13EMA of TSI used as the signal line.
Upper / lower reference level25 / -25Reference lines for stretched readings.
Show TSI − signal histogramOnColumns showing the gap between TSI and its signal line.

Educational tools, not advice. Indicators and Expert Advisors describe price; they do not predict it, and past behaviour does not guarantee future results. Test everything on a demo account first and never risk money you cannot afford to lose. See our disclaimer.

Keep exploring

Related tradingview indicators