Открыть на GitHub

Стратегия RSI Dual Cloud

Обзор

RSI Dual Cloud – порт эксперта MetaTrader «RSI Dual Cloud EA» на платформу StockSharp. Стратегия работает на настраиваемой серии свечей и анализирует две линии индикатора RSI – быструю и медленную. Сигналы формируются при входе, нахождении или выходе быстрой линии из заданной зоны перекупленности/перепроданности, а также при пересечении быстрой и медленной линий. Можно включить инверсию сигналов и ограничить торговлю только лонгами или только шортами.

Используются только рыночные заявки. При появлении нового сигнала противоположная позиция закрывается, затем открывается новая. Размер позиции контролируется единственным параметром объёма.

Логика сигналов

  1. Вход в зону – быстрая RSI входит в диапазон порога.
    • Лонг: предыдущее значение выше нижнего уровня, текущее ниже него.
    • Шорт: предыдущее значение ниже верхнего уровня, текущее выше него.
  2. Нахождение в зоне – быстрая RSI остаётся внутри диапазона.
    • Лонг: текущее значение ниже нижнего уровня.
    • Шорт: текущее значение выше верхнего уровня.
  3. Выход из зоны – быстрая RSI покидает диапазон.
    • Лонг: предыдущее значение ниже нижнего уровня, текущее выше него.
    • Шорт: предыдущее значение выше верхнего уровня, текущее ниже него.
  4. Пересечение линий – использование «двойного облака» RSI.
    • Лонг: быстрая RSI пересекает медленную снизу вверх.
    • Шорт: быстрая RSI пересекает медленную сверху вниз.

Можно задействовать любую комбинацию условий, но для входов должен быть активен хотя бы один пункт. При включении параметра Reverse сигналы меняются местами (лонг ↔ шорт).

Параметры

Название Описание
Candle Type Серия свечей для расчётов (по умолчанию 1 час).
Fast RSI / Slow RSI Периоды быстрой и медленной RSI.
Upper Level / Lower Level Уровни перекупленности и перепроданности.
Order Volume Объём рыночных заявок.
Use Entrance / Being / Leaving / Crossing Переключатели условий входа.
Closed Candles При включении сигналы считаются только на закрытых свечах.
Reverse Инверсия направлений сигналов.
Trade Mode Разрешённое направление торговли: лонг, шорт или оба.

Рекомендации по использованию

  • Стратегия подписывается на одну свечную серию и через high-level API подключает два индикатора RSI.
  • Применяются лишь рыночные заявки; обратные позиции закрываются перед открытием новой.
  • Параметры по умолчанию соответствуют оригинальному советнику (RSI 5 и 15, уровни 25/75).
  • Комбинируйте переключатели сигналов, чтобы повторить варианты работы оригинальной версии.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Uses fast and slow RSI crossovers to detect entry signals.
/// Simplified from the "RSI Dual Cloud EA" MetaTrader strategy.
/// </summary>
public class RsiDualCloudStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;

	private RelativeStrengthIndex _fastRsi;
	private RelativeStrengthIndex _slowRsi;
	private decimal? _prevFast;
	private decimal? _prevSlow;

	/// <summary>
	/// Candle type used for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Fast RSI period.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	/// <summary>
	/// Slow RSI period.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	public RsiDualCloudStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for RSI calculations", "General");

		_fastLength = Param(nameof(FastLength), 14)
			.SetGreaterThanZero()
			.SetDisplay("Fast RSI", "Fast RSI period", "Indicators");

		_slowLength = Param(nameof(SlowLength), 42)
			.SetGreaterThanZero()
			.SetDisplay("Slow RSI", "Slow RSI period", "Indicators");
	}

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

		_prevFast = null;
		_prevSlow = null;

		_fastRsi = new RelativeStrengthIndex { Length = FastLength };
		_slowRsi = new RelativeStrengthIndex { Length = SlowLength };

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

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

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

		if (!_fastRsi.IsFormed || !_slowRsi.IsFormed)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		if (_prevFast is null || _prevSlow is null)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		var crossUp = _prevFast < _prevSlow && fastValue > slowValue;
		var crossDown = _prevFast > _prevSlow && fastValue < slowValue;

		var volume = Volume;
		if (volume <= 0)
			volume = 1;

		var minSpread = 5m;

		if (crossUp && Math.Abs(fastValue - slowValue) >= minSpread)
		{
			if (Position <= 0)
				BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
		}
		else if (crossDown && Math.Abs(fastValue - slowValue) >= minSpread)
		{
			if (Position >= 0)
				SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_fastRsi = null;
		_slowRsi = null;
		_prevFast = null;
		_prevSlow = null;

		base.OnReseted();
	}
}