TradingView indicators

Trend Strength Index: correlation-based trend consistency

The Trend Strength Index measures the linear relationship between closing price and bar index. A value near +1 describes a steadily rising line; a value near -1 describes a steadily falling line. It summarizes the selected history, without estimating the probability of the next price move.

Trend Strength Index = Pearson r(close, bar index, N)

Synthetic check: the same five prices give r = 1.00 in ascending order and r = 0.30 after the specified shuffle below. Order matters; the set of prices alone is insufficient.

Looking for the momentum oscillator with double smoothing? That is the True Strength Index. Both use the abbreviation TSI, but they are different indicators.

What TradingView's Trend Strength Index calculates

TradingView documents a correlation of closing prices with bar index, plus Length and bullish/bearish color inputs. This page uses that public definition and a Pine Script v6 example. It does not reproduce a private script or infer an indicator's release history from the Pine language version. TradingView's indicator reference.

Write the last N observations in chronological order. Let t be the bar position and p the closing price. Compute both means, subtract each mean from its observations, then use the following centered sums. The sample or population normalization cancels when covariance is divided by both standard deviations.

t̄ = Σt / N; p̄ = Σp / N

S_tt = Σ(t − t̄)²

S_pp = Σ(p − p̄)²

S_tp = Σ(t − t̄)(p − p̄)

r = S_tp / √(S_tt × S_pp)

This is the Pearson formula described by NIST. With positive variance in both series, r is between -1 and +1. An exact +1 or -1 requires a straight-line relationship, not merely a sequence of higher or lower closes. With N = 2, any two unequal prices produce an absolute correlation of 1, so that setting offers no gradation of consistency.

Replacing absolute bar indices with 0 through N − 1 leaves r unchanged: subtracting a constant does not change deviations from the mean. Bar index measures successive chart bars, not elapsed seconds. A weekend or overnight break does not insert extra time points. Correlation with timestamps can therefore give a different answer when time gaps are unequal.

Adding a constant to every price or multiplying every price by a positive constant also leaves r unchanged. A tiny straight-line drift and a large straight-line advance can both score +1. Price scale, return magnitude, volume and tradable opportunity are separate measurements.

Same prices, different order: a reproducible calculation

These are invented five-bar samples in arbitrary price units, not market data or a backtest. All rows use t = [0, 1, 2, 3, 4], t̄ = 2 and S_tt = 10. Prices are listed oldest to newest. Sorted, Reversed and Shuffled contain exactly the same five values.

Five-bar Pearson correlation fixtures
SamplePrices in chronological orderS_tpS_ppExpected r
Sorted100, 101, 102, 103, 1041010+1.000000
Reversed104, 103, 102, 101, 100-1010-1.000000
Shuffled102, 100, 104, 101, 103310+0.300000
U-shaped104, 101, 100, 101, 1040140.000000
Single jump100, 100, 100, 100, 1102080+0.707107
Constant100, 100, 100, 100, 10000Undefined (na)
Missing100, 101, na, 103, 104Not computedNot computedna (strict policy)

Work through the shuffle

For [102, 100, 104, 101, 103], the mean price is 102. Its deviations are [0, -2, 2, -1, 1], and time deviations are [-2, -1, 0, 1, 2]. Their products are [0, 2, 0, -1, 2], which sum to 3. Price squared deviations sum to 10, so r = 3 / √(10 × 10) = 0.30. Sorting this same set makes the deviations match time and changes r to 1.00.

Sorting is a diagnostic demonstration only. Never sort observed closes before calculating a trading indicator: doing so manufactures a trend that was absent from the chronological series. One chosen permutation is also not a randomization test or a distribution of possible shuffled results.

Counterexamples to common interpretations

The U-shaped sample has zero correlation despite a deterministic curved pattern. The Single jump sample has r = 20 / √800 = 0.707107 even though four closes are identical and only the last one jumps. A reading above 0.5 therefore cannot establish that prices rose consistently on each bar. The constant sample has zero price variance and an undefined denominator; its result is not zero.

For initialization at N = 5, [100], [100, 101], [100, 101, 102] and [100, 101, 102, 103] all return na under the script's full-window policy. The fifth observation, 104, produces +1. With [100, 101, na, 103, 104, 105, 106, 107], valid output first resumes at the eighth observation, when the window is [103, 104, 105, 106, 107].

Pine Script v6 with chart data and synthetic test modes

Paste the complete indicator into TradingView Pine Editor and add it to a chart. Chart close uses the adjustable Chart length, starting at 14. The other modes use exactly five samples and repeat the table's sequences. The script retains the purple line, reference levels and directional gradient fills, with editable fill colors.

Pine Script v6
//@version=6
indicator("Trend Strength Index: correlation and fixtures", overlay = false, precision = 6)

lengthInput = input.int(14, "Chart length", minval = 2, maxval = 500)
mode = input.string("Chart close", "Data", options = ["Chart close", "Sorted", "Reversed", "Shuffled", "U-shaped", "Single jump", "Constant", "Missing"])
bullColor = input.color(color.rgb(8, 153, 129), "Bullish color")
bearColor = input.color(color.rgb(242, 54, 69), "Bearish color")

// Fixtures repeat every five bars. Compare at step 4: the oldest-to-newest
// window then matches the five observations printed in the guide.
int step = bar_index % 5
var array<float> shuffled = array.from(102.0, 100.0, 104.0, 101.0, 103.0)
var array<float> curved = array.from(104.0, 101.0, 100.0, 101.0, 104.0)
float sample = switch mode
    "Sorted" => 100.0 + step
    "Reversed" => 104.0 - step
    "Shuffled" => array.get(shuffled, step)
    "U-shaped" => array.get(curved, step)
    "Single jump" => step == 4 ? 110.0 : 100.0
    "Constant" => 100.0
    "Missing" => step == 2 ? na : 100.0 + step
    => close
int length = mode == "Chart close" ? lengthInput : 5

// Explicit policy: require a full, contiguous, non-missing window.
// Missing values are never replaced by zero or carried forward.
bool complete = bar_index >= length - 1
for offset = 0 to length - 1
    if na(sample[offset])
        complete := false
float priceHigh = ta.highest(sample, length)
float priceLow = ta.lowest(sample, length)
float rawCorrelation = ta.correlation(sample, bar_index, length)
float trendStrength = complete and priceHigh > priceLow ? rawCorrelation : na

trendPlot = plot(trendStrength, "Trend Strength Index", color = color.purple, style = plot.style_linebr)
zeroPlot = plot(0, "Fill reference", display = display.none)
hline(1, "Positive limit", color = bullColor)
hline(0, "Zero", color = color.gray)
hline(-1, "Negative limit", color = bearColor)
fill(trendPlot, zeroPlot, 1, 0, top_color = bullColor, bottom_color = color.new(bullColor, 100), fillgaps = false)
fill(trendPlot, zeroPlot, 0, -1, top_color = color.new(bearColor, 100), bottom_color = bearColor, fillgaps = false)
plot(sample, "Input sample", display = display.data_window)
plot(mode == "Chart close" ? na : step, "Fixture step (compare at 4)", display = display.data_window)

crossUp = ta.crossover(trendStrength, 0)
crossDown = ta.crossunder(trendStrength, 0)
alertcondition(mode == "Chart close" and crossUp and barstate.isconfirmed, "Positive correlation cross", "Trend Strength Index crossed above zero on a closed bar.")
alertcondition(mode == "Chart close" and crossDown and barstate.isconfirmed, "Negative correlation cross", "Trend Strength Index crossed below zero on a closed bar.")
  1. Select Sorted in the Data input. Open the Data Window and inspect a bar where Fixture step equals 4. Expect +1.000000.
  2. On that same bar, select Shuffled. Expect +0.300000. Check Reversed, U-shaped and Single jump against the table.
  3. Select Constant or Missing. The Trend Strength Index output should be na; a missing or undefined value must not become a zero cross.
  4. Return Data to Chart close before interpreting market data. Match the length, symbol, session, chart type and closed bar with the TradingView indicator.

At other fixture steps, the rolling window rotates across repetitions and is no longer the table's chronological sample. At the start of the available dataset, the first four fixture bars have no output. The repeat pattern deliberately makes the same fixture available throughout a long chart; it does not simulate a market.

The calculation calls ta.correlation on every bar. The explicit completeness check then rejects any window containing na, and the high/low check rejects constant prices. This strict missing-data policy is part of this example; do not assume every built-in or third-party script makes the same choice. It avoids silently using older observations or filling missing prices with zero.

Alerts are available only in Chart close mode. They require a zero cross and barstate.isconfirmed, so they become true at the close of the chart bar. Create the alert in TradingView and select Once Per Bar Close. The line itself remains live during an open bar. TradingView's bar-state documentation explains this confirmation boundary. There are no orders or strategy performance calculations in this indicator.

QQQ daily chart with Trend Strength Index in a separate pane, a purple line, and positive green and negative red fills
Existing QQQ daily chart illustration. The fills show the sign and magnitude of the plotted correlation. This image is not a run of the synthetic fixtures or evidence of trading performance.

Read correlation without turning thresholds into probabilities

Interpretations and limits of a defined result
ObservationWhat the formula establishesWhat remains unproven
Positive rPositive slope of the fitted price-versus-bar line.The next return, the size of the move, or every bar closing higher.
Negative rNegative slope of the fitted line.A profitable short or an imminent further decline.
r near zeroWeak linear association in this window.Randomness, absence of a curved pattern, or an uneventful market.
Cross above zeroThe rolling linear association changed sign.The start of a lasting trend or an entry with positive expected return.
Absolute r near onePrice lies close to a rising or falling straight line.An overbought/oversold state, exhaustion, or a guaranteed reversal.

A threshold such as +0.5 or a dead zone from -0.2 to +0.2 is a rule chosen by an analyst. Neither is automatically a statistical significance boundary. A claim of significance needs a null model, a sample size and defensible assumptions about dependence. Price levels can be serially dependent, and adjacent rolling windows share most of their observations. Treating each reading as an independent test would ignore that structure.

For these five-point examples only, a fitted ordinary least-squares line with an intercept has R² = r². The shuffled row's R² is 0.09. That describes its in-sample linear fit; it is not a 9% win rate or probability of trend continuation. No trading outcome follows from this identity.

Choose a window and test a complete trading rule

Length counts chart bars. Fourteen five-minute bars and fourteen daily bars each supply fourteen observations but cover different periods. Shorter windows give a new observation a larger role; longer windows retain more of the prior path. A longer window need not change every zero cross later, and there is no fixed number of false signals removed by changing length.

Compare 7, 14 and 28 only as example research settings, holding source data and timeframe fixed. Record how the line changes around turns, isolated jumps and quiet drift. When an old extreme leaves the window, correlation can move sharply even if the latest price barely changes. Gaps are valid price observations, but a single gap may dominate a short-window fit, as the Single jump sample shows.

If testing a rule such as a confirmed zero cross with a moving average filter, specify entry timing, exit, size, costs and slippage before measuring results. Compare it with the same rule without the filter, then evaluate an untouched time period. Record turnover and drawdown as well as returns. Adding RSI, ADX or a moving average does not create independent evidence automatically; these indicators also use related price history.

Keep the two TSI names separate
IndicatorInput and calculationPine implementation
Trend Strength IndexClosing price levels versus successive bar positions; Pearson correlation.ta.correlation(close, bar_index, length), with explicit validity checks here.
True Strength IndexDouble-smoothed signed price changes divided by double-smoothed absolute changes.ta.tsi(source, shortLength, longLength); display scaling depends on the script.
ADXSmoothed directional movement strength; direction is read separately from +DI and -DI.A distinct calculation; its numeric thresholds cannot be copied to a correlation scale.

See the True Strength Index guide for the smoothing calculation, or ADX for directional movement. The official True Strength Index reference also distinguishes its inputs from price-time correlation.

Turn the explicit formula into a Pineify coding request

Pineify's Pine Script AI Coding Agent can draft and edit a script from written requirements and offers syntax checking. Give it the formula, the handling of incomplete windows, and the expected synthetic results so you can review the generated calculation. A successful syntax check does not prove the math or a trading edge.

Create a Pine v6 Trend Strength Index using Pearson correlation of close with bar index. Expose length, starting at 14. Require N consecutive non-missing samples and return na for a constant-price window. Preserve the five-bar Sorted and Shuffled fixture modes; their results at step 4 must be 1.00 and 0.30. Alert on confirmed chart-bar zero crosses only. Do not substitute True Strength Index.

Compare the generated output with the table and with matching closed bars in TradingView. Define a complete strategy separately if you want to evaluate trades. This workflow produces code for review; it does not automate profitable trading or verify a statistical claim merely by compiling.

Build a correlation indicator with Pineify

Trend Strength Index questions

It measures the Pearson correlation between closing prices and their bar index over a chosen window. A defined result lies between -1 and +1. Its sign gives the direction of the fitted linear price trend; its magnitude describes linear consistency within that window.

No. Trend Strength Index correlates price levels with bar index. True Strength Index divides double-smoothed price changes by double-smoothed absolute price changes. Both are abbreviated TSI, so check the full indicator name. Pine ta.tsi() is the True Strength Index function.

No. A chosen correlation threshold is not a significance test or a probability of continuation. Statistical inference needs a specified null model and assumptions about dependence. Price levels, overlapping rolling windows, and repeated parameter selection require particular care.

No. Zero correlation means no linear association in the measured window. The synthetic prices 104, 101, 100, 101, 104 have zero correlation with equally spaced time but form a clear U-shaped pattern. A constant-price window is different: its correlation is undefined.

There is no universal best length or timeframe. This script starts at 14 chart bars and exposes the length as an input. Changing the window changes the observations being measured. Compare settings on identical data and evaluate any trading rule separately with costs and an untouched test period.

This example requires the last N consecutive samples to exist and have nonzero price variance. Before N bars are available, after a missing value enters that window, or during a constant-price window, it returns na. A gap is not converted into a neutral zero reading.

Yes. The latest close changes during an open bar, so the correlation line can move and a zero cross can disappear. This script restricts alert conditions to confirmed chart bars. The live plot still updates, and confirmation does not protect against later data revisions.

Sources and related indicator guides

Official references checked October 18, 2026. All five-bar examples are synthetic calculations.

Continue with RSI, MACD, or the TradingView indicator collection.

Educational information, not investment advice. The examples verify arithmetic and edge cases, not strategy performance. Historical correlation and indicator thresholds cannot guarantee future returns.