Открыть на GitHub

Стратегия RSI Sign

Данная стратегия является конвертацией советника iRSISign из MQL5 в высокоуровневый API StockSharp. Она использует комбинацию индикаторов RSI и ATR для генерации торговых сигналов.

Система обрабатывает только завершённые свечи выбранного таймфрейма. Когда значение RSI пересекает снизу вверх нижний уровень, открывается длинная позиция или закрывается короткая. Если RSI опускается ниже верхнего уровня, стратегия открывает короткую позицию или закрывает текущую длинную. ATR рассчитывается лишь для контекста, имитируя оригинальный индикатор, который смещал стрелки сигналов на величину ATR.

Подробности

  • Условия входа:
    • Покупка: предыдущее значение RSI было ниже DownLevel, текущее пересекло его сверху вниз.
    • Продажа: предыдущее значение RSI было выше UpLevel, текущее опустилось ниже него.
  • Направления: длинные и короткие позиции могут быть включены отдельно.
  • Условия выхода:
    • Противоположный сигнал закрывает позицию, если соответствующий флаг закрытия активирован.
  • Стопы: не реализованы. Управление рисками может быть добавлено отдельно.
  • Параметры по умолчанию:
    • RsiPeriod = 14
    • AtrPeriod = 14
    • UpLevel = 70
    • DownLevel = 30
    • CandleType = часовые свечи
  • Фильтры:
    • Категория: импульсная
    • Направление: оба
    • Индикаторы: RSI, ATR
    • Стопы: нет
    • Сложность: базовая
    • Таймфрейм: гибкий
    • Сезонность: нет
    • Нейросети: нет
    • Дивергенция: нет
    • Уровень риска: средний

Параметры

Имя Описание
RsiPeriod Период RSI.
AtrPeriod Период ATR.
UpLevel Верхний порог RSI для сигналов продажи.
DownLevel Нижний порог RSI для сигналов покупки.
CandleType Таймфрейм свечей для расчётов.
BuyOpen Разрешить открытие длинных позиций.
SellOpen Разрешить открытие коротких позиций.
BuyClose Разрешить закрытие длинных позиций противоположным сигналом.
SellClose Разрешить закрытие коротких позиций противоположным сигналом.

Стратегия предназначена в качестве учебного примера, демонстрирующего перенос логики MQL5 в стратегию StockSharp.

using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RSI based signal strategy.
/// Opens long when RSI crosses above the down level.
/// Opens short when RSI crosses below the up level.
/// </summary>
public class RsiSignStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _upLevel;
	private readonly StrategyParam<decimal> _downLevel;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _previousRsi;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal UpLevel { get => _upLevel.Value; set => _upLevel.Value = value; }
	public decimal DownLevel { get => _downLevel.Value; set => _downLevel.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public RsiSignStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "Length of RSI indicator", "Indicator");

		_upLevel = Param(nameof(UpLevel), 70m)
			.SetDisplay("RSI Upper Level", "Sell when RSI falls below this value", "Indicator");

		_downLevel = Param(nameof(DownLevel), 30m)
			.SetDisplay("RSI Lower Level", "Buy when RSI rises above this value", "Indicator");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe used for indicator calculations", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_previousRsi = null;
	}

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

		_previousRsi = null;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

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

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var prevRsi = _previousRsi;
		_previousRsi = rsiValue;

		if (prevRsi is null)
			return;

		// RSI crosses above lower level -> buy signal
		if (prevRsi <= DownLevel && rsiValue > DownLevel && Position <= 0)
			BuyMarket();
		// RSI crosses below upper level -> sell signal
		else if (prevRsi >= UpLevel && rsiValue < UpLevel && Position >= 0)
			SellMarket();
	}
}