Connors RSI: three components and short-term signals
Connors RSI averages price RSI, RSI of the up/down closing streak, and the rank of the latest percentage return. Its conventional setting is CRSI(3, 2, 100). A reading near an extreme describes recent momentum; it does not say when price will reverse.
Example: (60 + 50 + 60) / 3 = 56.67
What each component measures
The three lengths control different inputs. In particular, the third component ranks one-bar returns; it is not the percentage return over 100 bars.
| Component | Default | Input and operation |
|---|---|---|
| Price RSI | 3 bars | Wilder RSI of closing prices, using smoothed gains and losses. |
| Streak RSI | 2 bars | Wilder RSI of the signed streak series, not the raw streak count. |
| Return rank | 100 prior returns | 100 × count of prior returns below the current return / 100. |
For closes 100, 101, 102, 101, 101, 102, a zero-initialized streak is 0, +1, +2, −1, 0, +1. Changing direction starts at +1 or −1. An equal close resets it to zero. A doji concerns open versus close and is a different test.
These definitions follow the 2012 Connors Research guidebook, hosted by coauthor Cesar Alvarez. TradingView documents the same three default lengths.
A worked calculation, including tied returns
The following are separate arithmetic checks with supplied inputs, not a reconstruction of one market history. For a full chart match, retain the earlier RSI smoothing state as well as the return window.
- Price RSI check: suppose the previous smoothed gain is 0.4 and loss is 0.6. With length 3 and a new price change of +1, the updated gain is (2 × 0.4 + 1) / 3 = 0.6 and loss is (2 × 0.6 + 0) / 3 = 0.4. RSI = 100 − 100 / (1 + 0.6 / 0.4) = 60.
- Streak RSI check: suppose the streak moves from 0 to +1 and its previous smoothed gain/loss are 0.5 and 1.5. At length 2, they become (0.5 + 1) / 2 = 0.75 and (1.5 + 0) / 2 = 0.75. Streak RSI is 50.
- Rank check: let the current return be +1% and the five prior returns, sorted for inspection, be −2%, −1%, 0%, +1%, +1%. Three are strictly smaller, so the rank is 100 × 3 / 5 = 60. The two equal values do not count as smaller.
- For a component tuple of 60, 50 and 60, CRSI is 170 / 3 = 56.67. The length 5 rank window above is deliberately short for hand checking; the script defaults to 100.
An inclusive comparison would rank the same five-return fixture at 100, producing CRSI 70 instead. That 13.33-point difference is a convention change, not a different price move. Do not round returns before comparing them; apparently equal displayed percentages may differ at full precision.
The RSI updates use Wilder smoothing documented by TradingView: new average = ((length − 1) × previous average + current gain or loss) / length.
Pine Script v6 with an explicit rank convention
This educational implementation follows the guidebook's strictly-lower comparison against the previous N returns. The loop exposes both choices instead of delegating rank semantics to a helper. It is not a claim of exact parity with every TradingView or Pineify-generated CRSI variant.
//@version=6
indicator("Connors RSI: explicit prior-return rank", overlay = false, max_bars_back = 1002)
priceLength = input.int(3, "Price RSI length", minval = 1)
streakLength = input.int(2, "Streak RSI length", minval = 1)
rankLength = input.int(100, "Prior returns to rank against", minval = 1, maxval = 1000)
showParts = input.bool(false, "Show the three components")
// The first observed close starts at zero; equal closes reset the streak.
var float streak = 0.0
if na(close) or na(close[1])
streak := 0.0
else if close == close[1]
streak := 0.0
else if close > close[1]
streak := streak[1] > 0 ? streak[1] + 1 : 1
else
streak := streak[1] < 0 ? streak[1] - 1 : -1
priceRsi = ta.rsi(close, priceLength)
streakRsi = ta.rsi(streak, streakLength)
oneBarReturn = not na(close[1]) and close[1] != 0 ? 100 * (close / close[1] - 1) : na
// Strictly lower, previous N returns only. Ties do not count.
int validCount = 0
int lowerCount = 0
for offset = 1 to rankLength
pastReturn = oneBarReturn[offset]
if not na(pastReturn)
validCount += 1
if not na(oneBarReturn) and pastReturn < oneBarReturn
lowerCount += 1
rank = validCount == rankLength and not na(oneBarReturn) ? 100.0 * lowerCount / rankLength : na
ready = not na(priceRsi) and not na(streakRsi) and not na(rank)
crsi = ready ? (priceRsi + streakRsi + rank) / 3 : na
plot(crsi, "CRSI", color = color.blue, linewidth = 2)
plot(showParts ? priceRsi : na, "Price RSI", color = color.orange)
plot(showParts ? streakRsi : na, "Streak RSI", color = color.purple)
plot(showParts ? rank : na, "Return rank", color = color.teal)
hline(90, "Upper reference", color = color.gray)
hline(50, "Midpoint", color = color.new(color.gray, 60))
hline(10, "Lower reference", color = color.gray)Paste the complete script into TradingView's Pine Editor, save it and add it to the chart. Enable "Show the three components" to inspect their contributions. The 10 and 90 lines are reference levels, not orders; the script is an indicator and places no trades.
Flat prices, missing history and extreme readings
- A flat close resets the raw streak, but streak RSI retains its smoothing history. After a negative streak, a reset toward zero is a positive change in the streak series even though price did not rise.
- With N = 100, the rank needs the current return and 100 earlier returns, requiring 102 consecutive valid closes. Both RSI components must also be available. The example returns na until all three are defined; it never substitutes zero for missing components.
- A missing or zero previous close makes the percentage return undefined here. Any missing return in the required prior window keeps rank unavailable. The RSI calls retain Pine's own initialization and missing-value behavior; a flat or gapped startup should be inspected before using signals.
- A current return below every prior return ranks at 0; one above every prior return ranks at 100. If every return equals the current return, strict rank is 0. This does not mean price is falling, and a flat-history CRSI should not be read as ordinary oversold evidence.
- Each normalized component contributes one third. A raw streak of +8 is never averaged directly with RSI. An extreme return rank of 100 can coexist with price RSI 30 and streak RSI 20, giving CRSI 50.
- Use the same symbol feed, adjusted-price settings, timeframe and session when comparing values. The original research team's data-mismatch explanation specifically distinguishes split-only from split-and-dividend-adjusted prices.
The open bar can change all three inputs. Read confirmed closes when evaluating closed-bar rules. This is consistent with TradingView's explanation of historical and realtime calculations; confirmation does not eliminate later data revisions.
Turn a Connors RSI strategy idea into a test
One reproducible research specification is: on standard daily candles, while flat, require a confirmed close above SMA(200) and CRSI below 10. Enter at the next bar's open. Exit at the next open after either a confirmed CRSI above 50 or the fifth held bar closes. Allow one position, no pyramiding, and use a fixed position-size rule. This is an illustrative test, not the published Connors Research strategy or a performance claim.
Define commissions, slippage, starting capital and the maximum acceptable loss before running it. The time exit does not cap losses, and the next open can gap. Keep the rule unchanged across a development period and a later untouched period; record trades, drawdown and costs alongside returns.
| Change one input | Mechanism to inspect | Do not assume |
|---|---|---|
| Price RSI 3 → 5 | Less weight on the latest price change. | Higher profitability. |
| Streak RSI 2 → 3 | Slower adjustment after a streak reset. | A fixed reduction in false signals. |
| Rank 100 → 50 | Smaller comparison sample; rank steps grow from 1 to 2 points. | A guaranteed increase in trades. |
Repeated price declines can keep CRSI low while losses grow. Intraday bars change the elapsed time represented by each length; a 100-bar window on a five-minute chart is not 100 trading days. Validate that use separately.
Educational information, not investment advice. Neither an indicator threshold nor a successful historical test guarantees future returns.
Build and inspect the rule in Pineify
Give Pine Script AI Coding Agent the three formulas, strict tie rule, missing-history policy and the entry/exit specification above. Ask it to expose the components before converting the indicator into a strategy. Check the generated code and compare several bars by hand.
Once the strategy exposes its input parameters, Strategy Optimizer can support parameter comparisons in TradingView. Keep the test period and trading costs fixed. Parameter search does not itself establish a trading edge or replace an untouched validation period.
Explore Pine Script AI Coding AgentConnors RSI questions
Sources and related indicators
Sources checked October 17, 2026. The guidebook supplies the formula convention; the numeric fixtures and test specification on this page are educational examples.