Код
Торгуем по RSI: как использовать индекс относительной силы
Ты когда-нибудь видел, как цена акции резко падает — и думал: «Вот бы знать, не пора ли покупать?» Или, наоборот, цена взлетела — и хочется понять, не слишком ли поздно входить. Именно для этого трейдеры используют **RSI** — один из самых популярных индикаторов в мире. В этой статье разберём его от А до Я: простым языком, с кодом и реальными примерами на данных MOEX.
---
## Что такое RSI? Термометр перегрева рынка
Представь термометр. Когда температура поднимается выше 38°C — человек перегрелся, пора отдохнуть. Когда опускается ниже 36°C — что-то не так, нужно согреться.
**RSI (Relative Strength Index, Индекс относительной силы)** работает точно так же, только для рынка:
- Когда RSI высокий (выше 70) — рынок «перегрет», цена выросла слишком быстро. Возможно, скоро откат.
- Когда RSI низкий (ниже 30) — рынок «переохладился», цена упала слишком сильно. Возможно, скоро отскок.
RSI — это число от **0 до 100**. Рассчитывается на основе последних N свечей (обычно 14 дней). Именно поэтому его называют «осциллятором» — он колеблется в заданном диапазоне.
---
## Как RSI считается (без страшных формул)
Не бойся — математику мы спрячем за код. Но понять суть важно:
1. Берём последние 14 дней цен закрытия.
2. Считаем **средний рост** в дни, когда цена выросла.
3. Считаем **среднее падение** в дни, когда цена упала.
4. Делим средний рост на среднее падение — получаем **RS** (Relative Strength).
5. Превращаем RS в число от 0 до 100 — это и есть **RSI**.
Грубо говоря: RSI показывает, насколько «бычьи» дни преобладают над «медвежьими» за последние две недели. Чем больше роста — тем выше RSI.
---
## Зоны перекупленности и перепроданности
Вот главные уровни, которые нужно запомнить:
| RSI | Что это значит | Что делать |
|-----|----------------|------------|
| > 70 | Рынок **перекуплен** | Думать о продаже / не покупать |
| 30–70 | Нейтральная зона | Ждать сигнала |
| < 30 | Рынок **перепродан** | Думать о покупке |
**Аналогия:** Если RSI = 80 — акция как резинка, которую сильно растянули. Рано или поздно она вернётся. Если RSI = 20 — резинку сильно сжали. Скоро распрямится.
> ⚠️ Важно: RSI не гарантирует разворот. Иногда перекупленный рынок продолжает расти. Всегда используй RSI вместе с другими инструментами.
---
## Простая стратегия входа и выхода по RSI
Вот базовая логика, с которой начинают большинство алготрейдеров:
- **Покупай**, когда RSI опускается ниже 30 (перепроданность) и затем **снова поднимается выше 30** — это сигнал разворота вверх.
- **Продавай**, когда RSI поднимается выше 70 (перекупленность) и затем **снова опускается ниже 70** — это сигнал разворота вниз.
Такой подход называют «торговля от пробоя уровня RSI». Он помогает избежать входа в самом разгаре движения — ты ждёшь подтверждения разворота.
---
## Код на Python: RSI на данных MOEX
Теперь самое интересное — напишем стратегию на Python. Мы используем структуру загрузки данных из **ALG-3** (`fetch_moex_data.py`) и логику бэктеста из **ALG-4** (`sma_crossover_backtest.py`).
```python
# Пример для обучения. Не является инвестиционной рекомендацией.
#
# RSI-стратегия: покупка при выходе из перепроданности,
# продажа при выходе из перекупленности.
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
# --- Параметры ---
TICKER = "SBER.ME" # Сбербанк на MOEX (из ALG-3)
START = "2023-01-01"
END = "2025-01-01"
RSI_PERIOD = 14 # стандартный период
RSI_UPPER = 70 # уровень перекупленности
RSI_LOWER = 30 # уровень перепроданности
CAPITAL = 100_000 # начальный капитал (руб.)
# --- Загрузка данных (как в ALG-3) ---
df = yf.download(TICKER, start=START, end=END, auto_adjust=True, progress=False)[["Close"]]
df.columns = ["Close"]
# --- Вычисляем RSI через pandas ---
delta = df["Close"].diff()
gain = delta.clip(lower=0) # только положительные изменения
loss = (-delta).clip(lower=0) # только отрицательные (берём по модулю)
avg_gain = gain.ewm(com=RSI_PERIOD - 1, min_periods=RSI_PERIOD).mean()
avg_loss = loss.ewm(com=RSI_PERIOD - 1, min_periods=RSI_PERIOD).mean()
rs = avg_gain / avg_loss
df["RSI"] = 100 - (100 / (1 + rs))
df.dropna(inplace=True)
# --- Сигналы входа и выхода ---
# +1: RSI пробивает уровень 30 снизу вверх (был <30, стал >=30) → покупка
# -1: RSI пробивает уровень 70 сверху вниз (был >70, стал <=70) → продажа
prev_rsi = df["RSI"].shift(1)
df["Signal"] = 0
df.loc[(prev_rsi < RSI_LOWER) & (df["RSI"] >= RSI_LOWER), "Signal"] = 1
df.loc[(prev_rsi > RSI_UPPER) & (df["RSI"] <= RSI_UPPER), "Signal"] = -1
# --- Позиция (как в ALG-4): 1 = в покупке, 0 = вне рынка ---
df["Position"] = 0
position = 0
for i, sig in df["Signal"].items():
if sig == 1:
position = 1
elif sig == -1:
position = 0
df.at[i, "Position"] = position
# --- Бэктест доходности ---
df["Returns"] = df["Close"].pct_change()
df["Strat_returns"] = df["Returns"] * df["Position"].shift(1)
df["Equity"] = CAPITAL * (1 + df["Strat_returns"]).cumprod()
# --- Статистика ---
total_signals = (df["Signal"] != 0).sum()
final_equity = df["Equity"].iloc[-1]
total_return = (final_equity / CAPITAL - 1) * 100
print("===== RSI СТРАТЕГИЯ — РЕЗУЛЬТАТЫ =====")
print(f"Тикер: {TICKER} | {START} — {END}")
print(f"RSI-период: {RSI_PERIOD}, уровни: {RSI_LOWER}/{RSI_UPPER}")
print(f"Кол-во сигналов: {total_signals}")
print(f"Итоговый капитал: {final_equity:,.0f} руб.")
print(f"Общая доходность: {total_return:+.1f}%")
print("=======================================")
# --- График (как в ALG-4) ---
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8), sharex=True)
ax1.plot(df["Close"], color="black", lw=1, label="Цена закрытия")
buys = df[df["Signal"] == 1]
sells = df[df["Signal"] == -1]
ax1.scatter(buys.index, buys["Close"], marker="^", color="green", s=80, zorder=5, label="Покупка (RSI < 30)")
ax1.scatter(sells.index, sells["Close"], marker="v", color="red", s=80, zorder=5, label="Продажа (RSI > 70)")
ax1.set_title(f"RSI-стратегия — {TICKER}")
ax1.legend(); ax1.grid(alpha=0.3)
ax2.plot(df["RSI"], color="purple", lw=1.5, label="RSI")
ax2.axhline(RSI_UPPER, ls="--", color="red", lw=1, label=f"Перекупленность ({RSI_UPPER})")
ax2.axhline(RSI_LOWER, ls="--", color="green", lw=1, label=f"Перепроданность ({RSI_LOWER})")
ax2.axhline(50, ls=":", color="grey", lw=1)
ax2.set_ylim(0, 100); ax2.set_title("RSI")
ax2.legend(); ax2.grid(alpha=0.3)
plt.tight_layout()
plt.savefig("rsi_strategy.png", dpi=150)
plt.show()
```
**Как это работает:**
- Мы загружаем данные Сбербанка с MOEX (как в ALG-3) через `yfinance`.
- Считаем RSI по формуле с экспоненциальным сглаживанием (EWM) — это стандартный подход Уайлдера.
- Генерируем сигналы на пробой уровней 30 и 70.
- Считаем доходность и строим два графика: цену со сделками и сам RSI.
Попробуй изменить `RSI_PERIOD` (например, на 7 или 21) и посмотри, как меняется число сигналов. Меньший период — больше сигналов, больше шума. Больший период — меньше сигналов, но они надёжнее.
---
## Когда RSI обманывает: типичные ловушки
RSI — мощный инструмент, но у него есть слабые стороны. Вот три ситуации, когда он подводит:
### 1. Сильный тренд игнорирует RSI
В сильном восходящем тренде RSI может **долго оставаться выше 70** — и это не значит «продавай». Рынок просто очень сильный. Если ты продашь по первому сигналу RSI > 70, можешь пропустить половину движения вверх.
**Совет:** В трендовом рынке используй RSI иначе — жди откатов RSI к 40–50 как точки входа, а не ждёшь уровня 30.
### 2. Ложные сигналы на боковом рынке
Когда рынок «пилит» — ходит вверх-вниз без чёткого направления — RSI будет постоянно пересекать уровни 30 и 70, генерируя много сигналов. Большинство из них окажутся убыточными.
**Совет:** Добавь фильтр тренда (например, SMA из ALG-4). Торгуй RSI только по направлению тренда.
### 3. Дивергенция RSI — полезная, но сложная
Иногда цена обновляет максимум, а RSI — нет (или наоборот). Это называется **дивергенцией** и часто предвещает разворот. Но трактовать её правильно сложно — и новичкам лучше начать с простых сигналов.
---
## Ключевые выводы
- **RSI** — это осциллятор от 0 до 100, показывающий «перегрев» или «переохлаждение» рынка.
- **RSI > 70** — перекупленность (возможный разворот вниз).
- **RSI < 30** — перепроданность (возможный разворот вверх).
- Простая стратегия: **покупай при выходе RSI из зоны < 30, продавай при выходе из зоны > 70**.
- RSI лучше работает **против тренда** (на откатах), хуже — в сильном тренде.
- Всегда **комбинируй RSI с другими инструментами** (например, с SMA из прошлого урока).
- **Код выше** — рабочая база, которую можно улучшать: добавлять стоп-лоссы, фильтры, несколько тикеров.
---
## Что дальше?
Теперь у тебя есть две стратегии: SMA-кроссовер (из урока 1) и RSI (из этого урока). Попробуй их совместить: входи в покупку только тогда, когда **и** SMA даёт «золотой крест», **и** RSI ниже 50. Это называется «конфлюэнция» — совпадение сигналов нескольких индикаторов.
---
*Попробуйте эту стратегию прямо сейчас на [arenago.ru](https://arenago.ru) — загрузите данные MOEX, запустите RSI-бот в Тренировочной Арене и посмотрите, как он работает в реальных рыночных условиях. Никакого риска — только практика!*
1
22
0
Пока нет комментариев. Будьте первым!