Индикатор RSI: формула, настройки и чтение

RSI (Relative Strength Index) сравнивает средний размер закрытий вверх со средним размером закрытий вниз за окно расчёта и выражает их соотношение по шкале от 0 до 100. Senzoukria считает его по закрытиям баров с исходным сглаживанием Уайлдера, период по умолчанию — 14.

Senzoukria · Индикаторы · Updated September 2026


RSI Моментум, в отдельной панели под графиком.

Что измеряет RSI

Значение отражает пропорцию между средним ростом и средним падением внутри сглаженного окна, а не расстояние, пройденное ценой. Ряд инициализируется простым средним первых четырнадцати изменений от закрытия к закрытию, поэтому ничего не рисуется, пока эти четырнадцать изменений не набраны; дальше каждый бар обновляет обе средние по рекурсии Уайлдера, которая сохраняет в памяти все прежние изменения с затухающим весом. Три граничных случая заданы явно: окно из одних ростов даёт 100, окно из одних падений — 0, а полностью плоское окно, где обе средние равны нулю, не даёт никакого значения вместо 100, потому что рынок, который не двигался, не несёт информации о направлении. Расчёт идёт непрерывно и никогда не сбрасывается на границе сессии.

Формула — так, как она реализована

Это не привычное определение из других источников, а то, что вычисляет поставляемый код, задокументированное рядом с реализацией:

Période entière ≥ `min` depuis les params (garde-fou UI). */ function intParam( params: Record<string, unknown>, key: string, fallback: number, min = 1, ): number { return Math.max(min, Math.floor(numParam(params, key, fallback))); } function toPoints( bars: readonly FootprintBar[], values: ReadonlyArray<number | null>, ): SeriesPoint[] { return bars.map((b, i) => ({ time: b.bucketTsNs, value: values[i] ?? null })); } /** SMA N sur série à trous : null dès qu'UNE valeur de la fenêtre est null — moyenner autour d'un trou mentirait sur la période effective. */ function smaNullable( values: ReadonlyArray<number | null>, period: number, ): Array<number | null> { const n = Math.max(1, Math.floor(period)); const out: Array<number | null> = new Array<number | null>(values.length).fill(null); for (let i = n - 1; i < values.length; i++) { let sum = 0; let ok = true; for (let j = i - n + 1; j <= i; j++) { const v = values[j]; if (v === null) { ok = false; break; } sum += v; } if (ok) out[i] = sum / n; } return out; } /** EMA N sur une série dont les valeurs définies forment un SUFFIXE contigu (sortie d'un lissage précédent) : l'EMA tourne sur le suffixe, le préfixe reste null. Série toute-null (ou trou interne — impossible dans nos usages) → tout-null, on ne devine pas. */ function suffixEma( values: ReadonlyArray<number | null>, period: number, ): Array<number | null> { const out: Array<number | null> = new Array<number | null>(values.length).fill(null); const start = values.findIndex((v) => v !== null); if (start < 0) return out; const defined: number[] = []; for (let i = start; i < values.length; i++) { const v = values[i]; if (v === null) return out; // pas un suffixe contigu → dégradation propre defined.push(v); } const ema = emaSeries(defined, period); for (let j = 0; j < ema.length; j++) out[start + j] = ema[j]; return out; } /** Égalités RSI (documentées) : marché PLAT (les deux moyennes nulles) → null — pas d'information directionnelle (déviation assumée du Pine `down==0 → 100`, qui afficherait 100 sur du plat) ; que des gains → 100 ; que des pertes → 0. */ function rsiValue(avgGain: number, avgLoss: number): number | null { if (avgLoss === 0 && avgGain === 0) return null; if (avgLoss === 0) return 100; if (avgGain === 0) return 0; return 100 - 100 / (1 + avgGain / avgLoss); } /** RSI de Wilder sur une série de valeurs (closes ici, série RSI pour le StochRSI). Graine = moyenne SIMPLE des N premières variations, puis lissage Wilder ; premier point à l'indice N (N variations consommées). */ function wilderRsiSeries( values: readonly number[], period: number, ): Array<number | null> { const n = Math.max(1, Math.floor(period)); const out: Array<number | null> = new Array<number | null>(values.length).fill(null); if (values.length < n + 1) return out; let avgGain = 0; let avgLoss = 0; for (let i = 1; i <= n; i++) { const ch = values[i] - values[i - 1]; if (ch > 0) avgGain += ch; else avgLoss -= ch; } avgGain /= n; avgLoss /= n; out[n] = rsiValue(avgGain, avgLoss); for (let i = n + 1; i < values.length; i++) { const ch = values[i] - values[i - 1]; avgGain = (avgGain * (n - 1) + Math.max(0, ch)) / n; avgLoss = (avgLoss * (n - 1) + Math.max(0, -ch)) / n; out[i] = rsiValue(avgGain, avgLoss); } return out; } /** %K brut : 100·(close − LL_N)/(HH_N − LL_N) sur high/low des barres. Fenêtre PLATE (HH == LL) → null : 0/0 = pas d'information (même règle que delta-percent). */ function rawStochK( bars: readonly FootprintBar[], period: number, ): Array<number | null> { const n = Math.max(1, Math.floor(period)); const out: Array<number | null> = new Array<number | null>(bars.length).fill(null); for (let i = n - 1; i < bars.length; i++) { let hh = Number.NEGATIVE_INFINITY; let ll = Number.POSITIVE_INFINITY; for (let j = i - n + 1; j <= i; j++) { if (bars[j].high > hh) hh = bars[j].high; if (bars[j].low < ll) ll = bars[j].low; } const range = hh - ll; out[i] = range > 0 ? (100 * (bars[i].close - ll)) / range : null; } return out; } function typicalPrice(b: FootprintBar): number { return (b.high + b.low + b.close) / 3; } /** True range de la barre i — TR[0] = high − low (pas de close précédent), même définition que `atrSeries` (averages.ts). */ function trueRangeAt(bars: readonly FootprintBar[], i: number): number { const b = bars[i]; if (i === 0) return b.high - b.low; const pc = bars[i - 1].close; return Math.max(b.high - b.low, Math.abs(b.high - pc), Math.abs(b.low - pc)); } // ── Defs ──────────────────────────────────────────────────────────────────── /** RSI (Wilder, 1978) — lissage WILDER : gain = max(0, close − closeₚ) ; loss = max(0, closeₚ − close) graine = moyenne simple des N premiers gains/losses (à l'indice N) ; puis avg = (avg·(N−1) + x)/N ; RSI = 100 − 100/(1 + avgGain/avgLoss) Égalités : cf. `rsiValue` (plat → null, tout-gain → 100, tout-perte → 0). CONTINU — pas de reset session. Défaut N=14 (Wilder).

Как его читать

  • Значение выше 70 означает, что в сглаженном окне преобладали закрытия вверх. В устойчивом тренде RSI может держаться там долго, поэтому читайте его как описание того, что уже произошло, а не как сигнал разворота.
  • Значение ниже 30 описывает зеркальный случай: в окне преобладали закрытия вниз.
  • Уровень 50 разделяет окна, где средний рост больше среднего падения, и окна, где верно обратное. Пересечение меняет этот баланс, но само по себе тренд не устанавливает.
  • Дивергенция, когда цена делает более высокий максимум, а RSI — более низкий, говорит, что второй отрезок движения собран из меньших закрытий вверх, чем первый. Сверьте это с футпринтом обоих отрезков, прежде чем делать вывод.
  • Разрыв линии означает, что окно было плоским и значение не определено. Разрыв — это не ноль.

Параметры и значения по умолчанию

Период по умолчанию — 14, выбор самого Уайлдера, допустимо от 2 до 200. Короткий период сильнее реагирует на каждое новое закрытие и гораздо чаще касается зон 30 и 70; длинный сглаживает кривую и делает экстремумы редкими. Настройка цвета меняет только отрисовку линии в её панели.

RSI — параметры, доступные в приложении, со значениями по умолчанию.
ПараметрТипПо умолчаниюДиапазон
Periodnumber142 – 200

Чего он не показывает

RSI читает закрытия и больше ничего. Был ли отрезок сделан покупателями, забиравшими предложения, или продавцами, которые отошли, — это различие видно в колонках bid × ask бара футпринта, и никакое прочтение этой линии его не восстановит. Поскольку ряд непрерывен между сессиями, ночной гэп входит в расчёт как одно крупное изменение от закрытия к закрытию и затем влияет на средние ещё много баров. Сглаживание Уайлдера по своей конструкции имеет длинную память, поэтому один аномальный бар остаётся заметен в значении ещё долго после того, как он напечатался. Плоские участки дают настоящие разрывы линии, а не значение по умолчанию.

Все индикаторы

Эта страница на других языках

Frequently asked questions

Что означает RSI, равный 70?
RSI 70 означает, что за окно расчёта среднее закрытие вверх было примерно в 2,33 раза больше среднего закрытия вниз. Это описание периода, в котором преобладали закрытия покупателей, а не измерение того, сколько цене ещё осталось пройти; в трендовом рынке значение может оставаться выше 70 много баров подряд.
Совпадает ли этот RSI с RSI на других платформах?
Сглаживание — стандартная рекурсия Уайлдера, инициализированная простым средним первых N изменений, что соответствует обычным реализациям. Один случай отличается намеренно: когда и средний рост, и среднее падение равны нулю, то есть рынок был абсолютно плоским, Senzoukria не возвращает значения, тогда как некоторые версии, производные от Pine, в этой ситуации возвращают 100.
Сбрасывается ли RSI в начале каждой торговой сессии?
Нет. Ряд RSI здесь непрерывен: сглаженные средние переходят из одной сессии в следующую. Поэтому первое изменение новой сессии — это гэп между предыдущим закрытием и новым, и на фьючерсах, торгующихся раздельными сессиями, он может быть большим.

Keep reading