Открыть на GitHub

Стратегия «RSI Levels»

Общее описание

RSI Levels — порт советника MetaTrader 5, отслеживающего значения индикатора RSI на выбранном таймфрейме. Стратегия реагирует, когда RSI пробивает заданные уровни перекупленности и перепроданности: вход в лонг выполняется при уходе RSI ниже уровня oversold, вход в шорт — при подъёме выше уровня overbought. Одновременно разрешена только одна позиция; перед открытием новой позиции противоположное направление закрывается.

Логика торговли

  1. Расчёт RSI — индикатор вычисляется по завершённым свечам рабочего таймфрейма, период задаётся параметром.
  2. Сигнал на покупку — текущий RSI закрывается ниже уровня перепроданности, а предыдущее значение находилось выше. При наличии короткой позиции она закрывается, затем открывается покупка.
  3. Сигнал на продажу — текущий RSI закрывается выше уровня перекупленности, а предыдущее значение было ниже. При наличии длинной позиции она закрывается, после чего открывается продажа.
  4. Стоп-лосс — фиксированный, задаётся в пунктах относительно цены входа. Нулевое значение отключает защитный стоп.
  5. Тейк-профит — фиксированный, задаётся в пунктах относительно цены входа. Нулевое значение отключает цель по прибыли.
  6. Управление позицией — после закрытия сделки внутренние переменные обнуляются, что исключает ложные срабатывания при следующем сигнале.

Управление капиталом

Размер позиции рассчитывается от параметра «Процент риска на сделку». Сначала определяется денежный риск (капитал портфеля × процент риска), затем он делится на стоимость стопа (пункты стопа × стоимость шага цены). Получившийся объём округляется вниз до допустимого шага лота и ограничивается минимальными/максимальными значениями инструмента. При отсутствии сведений о PriceStep или StepPrice стратегия делает предупреждение и использует минимальный объём.

Параметры

Параметр Значение по умолчанию Описание
CandleType Таймфрейм 1 час Таймфрейм, по которому подписываемся на свечи и считаем RSI.
RsiPeriod 14 Период сглаживания RSI.
OverboughtLevel 70 Уровень перекупленности.
OversoldLevel 30 Уровень перепроданности.
RiskPercent 2 Доля капитала, рискуемая в одной сделке.
StopLossPoints 500 Размер стоп-лосса в пунктах (0 — отключен).
TakeProfitPoints 1000 Размер тейк-профита в пунктах (0 — отключен).

Практические рекомендации

  • Убедитесь, что у инструмента заданы PriceStep, StepPrice, MinVolume и VolumeStep. Без них расчёт лота будет неточным, и стратегия перейдёт на минимальный объём.
  • Используются методы SubscribeCandles и Bind, поэтому индикатор обновляется автоматически без ручного запроса данных.
  • Стопы и цели проверяются по значениям свечей. Из-за гэпов или проскальзывания фактическая цена исполнения может отличаться от расчётной.
  • Стратегия рассчитана на размеренные таймфреймы (M15, H1, H4). На мелких интервалах рекомендуется добавить фильтры для снижения рыночного шума.

Порядок работы

  1. Привяжите стратегию к нужному инструменту и портфелю.
  2. Настройте уровни RSI, стопы и процент риска под специфику рынка.
  3. Запустите стратегию и следите за предупреждениями в журнале.
  4. По итогам тестов или торговли корректируйте параметры и уровни риск-менеджмента.

Реализация в StockSharp повторяет логику оригинального советника и предоставляет доступ ко всем важным настройкам через параметры стратегии.

using System;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RSI Levels strategy: RSI oversold/overbought mean reversion.
/// Buys when RSI < 35. Sells when RSI > 65.
/// </summary>
public class RsiLevelsStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public RsiLevelsStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsi)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (rsi < 30m && Position <= 0)
		{
			BuyMarket();
		}
		else if (rsi > 70m && Position >= 0)
		{
			SellMarket();
		}
	}
}