Открыть на GitHub

Стратегия DT RSI EXP1

Порт воспроизводит советник MT4 DT-RSI-EXP1. Алгоритм анализирует колебания RSI на 15-минутных свечах, чтобы найти двойные вершины и впадины около уровней 60/40. Лонг открывается, когда две последовательные вершины RSI удовлетворяют условиям, между ними нет впадин ниже 40, а фильтр тренда на 4-часовом графике направлен вниз. Для шорта условия зеркальные: две впадины, отсутствие вершин выше 60 и восходящий фильтр. К каждой позиции привязывается фиксированный стоп-лосс и тейк-профит, дополнительно можно включить трейлинг-стоп. Как и в оригинале, позиции принудительно закрываются при достижении RSI экстремумов 70/30.

Подробности

  • Вход в рынок:
    • Лонг: две вершины RSI, вторая выше 60, между ними нет впадин ниже 40; EMA на таймфрейме 240 минут (замена RFTL) ниже предыдущего закрытия; RSI(1) пересекает прогнозируемую линию шеи вверх, RSI(2) остаётся ниже, RSI(2) < 50 и RSI(0) < 55.
    • Шорт: две впадины RSI, вторая ниже 40, между ними нет вершин выше 60; EMA на 240-минутном графике выше предыдущего закрытия; RSI(1) пробивает линию шеи вниз, RSI(2) > 50 и RSI(0) > 47.
  • Направление: обе стороны.
  • Выход:
    • Экстремумы RSI (RSI > 70 для лонгов, RSI < 30 для шортов).
    • Срабатывание стоп-лосса или тейк-профита, рассчитанных в шагах цены.
    • Опциональный трейлинг-стоп после прохождения TrailingStopPoints.
  • Стопы: фиксированные стоп-лосс и тейк-профит + трейлинг по желанию.
  • Значения по умолчанию:
    • CandleType = 15 минут.
    • TrendCandleType = 240 минут (EMA-фильтр).
    • RsiPeriod = 47.
    • StopLossPoints = 26.
    • TakeProfitPoints = 76.
    • TrailingStopPoints = 0 (выключен).
  • Фильтры:
    • Категория: трендовые входы по структурам RSI.
    • Направление: обе.
    • Индикаторы: RSI, EMA тренда.
    • Стопы: есть.
    • Сложность: средняя (много условий на свинги).
    • Таймфрейм: внутридневной (M15 + H4).
    • Сезонность: нет.
    • Нейросети: нет.
    • Дивергенция: нет.
    • Риск: средний.

Параметры

Имя Значение Описание Оптимизация
CandleType 15 минут Базовый поток свечей для RSI и сигналов. Да
TrendCandleType 240 минут Старший таймфрейм для EMA (аналог MT4 RFTL). Да
RsiPeriod 47 Период RSI на основном таймфрейме. Да
StopLossPoints 26 Дистанция стоп-лосса в шагах цены. Да
TakeProfitPoints 76 Дистанция тейк-профита в шагах цены. Да
TrailingStopPoints 0 Шаг трейлинг-стопа в шагах цены (0 отключает). Да

Заметки

  • Индикатор MT4 RFTL заменён EMA с периодом 10 на 240-минутном графике. При необходимости измените таймфрейм или период EMA, чтобы ближе воспроизвести оригинал.
  • Убедитесь, что у инструмента корректно настроены PriceStep и StepPrice, иначе значения в пунктах не совпадут с брокером.
  • Трейлинг активируется только после прохождения цены дальше TrailingStopPoints от входа и никогда не расширяет исходный риск.
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>
/// DT RSI EXP1 strategy - RSI overbought/oversold with EMA trend filter.
/// Buys when RSI crosses above oversold level while above EMA trend.
/// Sells when RSI crosses below overbought level while below EMA trend.
/// </summary>
public class DtRsiExp1Strategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<decimal> _oversold;
	private readonly StrategyParam<decimal> _overbought;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevRsi;
	private bool _hasPrev;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
	public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

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

		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");

		_oversold = Param(nameof(Oversold), 30m)
			.SetDisplay("Oversold", "RSI oversold level", "Indicators");

		_overbought = Param(nameof(Overbought), 70m)
			.SetDisplay("Overbought", "RSI overbought level", "Indicators");

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

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevRsi = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

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

		StartProtection(
			takeProfit: new Unit(2, UnitTypes.Percent),
			stopLoss: new Unit(1, UnitTypes.Percent)
		);
	}

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevRsi = rsi;
			_hasPrev = true;
			return;
		}

		// RSI crosses above oversold + bullish trend
		if (_prevRsi <= Oversold && rsi > Oversold && close > ema && Position == 0)
		{
			BuyMarket();
		}
		// RSI crosses below overbought + bearish trend
		else if (_prevRsi >= Overbought && rsi < Overbought && close < ema && Position == 0)
		{
			SellMarket();
		}

		_prevRsi = rsi;
	}
}