Открыть на GitHub

Стратегия RSI Trader

Краткое описание

Стратегия является портом советника «RSI trader» для MetaTrader. Она использует двойную фильтрацию тренда: скользящие средние цены и сглаженные средние RSI. Сделки открываются, когда оба фильтра показывают одно направление, и закрываются при расхождении сигналов (режим флэта). По умолчанию применяются часовые свечи, но можно выбрать любые доступные данные.

Алгоритм работы

  1. Рассчитывается RSI с периодом RSI Period (по умолчанию 14).
  2. Поток значений RSI сглаживается двумя простыми скользящими: Short RSI MA и Long RSI MA.
  3. Цена закрытия сглаживается простой (Short Price MA) и линейно-взвешенной (Long Price MA) средними.
  4. После завершения свечи формируется сигнал:
    • Покупка – обе короткие средние находятся выше своих длинных.
    • Продажа – обе короткие средние находятся ниже своих длинных.
    • Флэт – средние указывают противоположные направления, текущая позиция закрывается.
  5. При смене направления противоположная позиция сначала закрывается рыночным приказом, затем стратегия ожидает подтверждения для входа в новый тренд.

Параметры

Название Описание Значение по умолчанию Оптимизация
RSI Period Период расчёта RSI. 14 Да (7…28, шаг 1)
Short Price MA Период короткой простой средней цены. 9 Да (5…20, шаг 1)
Long Price MA Период длинной линейно-взвешенной средней цены. 45 Да (30…90, шаг 5)
Short RSI MA Период короткой сглаживающей средней RSI. 9 Да (5…20, шаг 1)
Long RSI MA Период длинной сглаживающей средней RSI. 45 Да (30…90, шаг 5)
Candle Type Тип свечей для анализа, по умолчанию 1H. H1 Нет

Дополнительно

  • Сделки совершаются только после формирования всех индикаторов.
  • Размер заявки берётся из свойства Volume. Управление проскальзыванием выполняется на уровне торгового адаптера.
  • Фиксированные стопы и тейк-профиты не заданы; выход осуществляется по сигналу флэта. При необходимости добавьте внешние ограничения риска.
  • При доступном сервисе графиков отображаются скользящие средние цены и RSI, что облегчает визуальный контроль сигналов.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RSI Trader strategy combining price SMA crossover with RSI trend confirmation.
/// Buy when short SMA crosses above long SMA with RSI above 50.
/// Sell when short SMA crosses below long SMA with RSI below 50.
/// </summary>
public class RsiTraderAlignedAveragesStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _shortMaPeriod;
	private readonly StrategyParam<int> _longMaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevShort;
	private decimal _prevLong;
	private bool _hasPrev;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int ShortMaPeriod { get => _shortMaPeriod.Value; set => _shortMaPeriod.Value = value; }
	public int LongMaPeriod { get => _longMaPeriod.Value; set => _longMaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public RsiTraderAlignedAveragesStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI calculation period", "Indicators");

		_shortMaPeriod = Param(nameof(ShortMaPeriod), 9)
			.SetDisplay("Short MA", "Short moving average period", "Indicators");

		_longMaPeriod = Param(nameof(LongMaPeriod), 26)
			.SetDisplay("Long MA", "Long moving average period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevShort = 0m;
		_prevLong = 0m;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_hasPrev = false;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var shortMa = new SimpleMovingAverage { Length = ShortMaPeriod };
		var longMa = new SimpleMovingAverage { Length = LongMaPeriod };

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

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

		if (!_hasPrev)
		{
			_prevShort = shortMa;
			_prevLong = longMa;
			_hasPrev = true;
			return;
		}

		var bullCross = _prevShort <= _prevLong && shortMa > longMa;
		var bearCross = _prevShort >= _prevLong && shortMa < longMa;

		if (Position <= 0 && bullCross && rsiValue > 50)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (Position >= 0 && bearCross && rsiValue < 50)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevShort = shortMa;
		_prevLong = longMa;
	}
}