Открыть на GitHub

Стратегия Color JJRSX Trend

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

Стратегия представляет собой перенос советника MetaTrader Exp_ColorJJRSX на высокоуровневый API StockSharp. В оригинале применяется осциллятор ColorJJRSX, сочетающий сглаживания Jurik для выявления переломов тренда. В версии для StockSharp осциллятор реализован через стандартный Relative Strength Index (RSI) с периодом JurxPeriod, дополнительно сглаженным Jurik Moving Average (JmaPeriod). Наклон полученной кривой анализируется на нескольких прошедших барах (определяется SignalBar), что позволяет повторить логику сигналов исходного робота.

Торговля ведётся на настраиваемом таймфрейме свечей (по умолчанию 4 часа). Флаги EnableBuy и EnableSell управляют разрешением длинных и коротких входов отдельно. Параметры AllowBuyClose и AllowSellClose активируют выходы при смене направления наклона, а StopLossPoints и TakeProfitPoints добавляют точечные стопы и тейк-профиты в духе исходной MQL-реализации.

Построение индикатора

  1. RSI как замена JurX. Период JurxPeriod задаёт длину RSI, которая заменяет проприетарный JurX и сохраняет диапазон значений 0–100.
  2. Jurik Moving Average. Полученный RSI сглаживается JMA с длиной JmaPeriod, благодаря чему линия быстро реагирует на изменения импульса и остаётся плавной.
  3. Историческое окно. В памяти хранится SignalBar + 3 последних значений JMA. Индексы SignalBar, SignalBar + 1 и SignalBar + 2 полностью повторяют набор данных, который использовался через CopyBuffer в MetaTrader.

Логика входов и выходов

  • Сигнал на покупку
    • JMA[SignalBar + 1] < JMA[SignalBar + 2] — восходящий разворот на предпредыдущем баре.
    • JMA[SignalBar] > JMA[SignalBar + 1] — подтверждение роста на текущем закрывшемся баре.
    • При включённом EnableBuy и отсутствии длинной позиции совершается покупка объёмом OrderVolume. При открытом шорте происходит реверс.
  • Сигнал на продажу
    • JMA[SignalBar + 1] > JMA[SignalBar + 2] — нисходящий разворот.
    • JMA[SignalBar] < JMA[SignalBar + 1] — подтверждение снижения.
    • При активном EnableSell открывается короткая позиция, существующая длинная позиция закрывается и переворачивается.
  • Выходы
    • При смене наклона против позиции и активных флагах AllowBuyClose / AllowSellClose стратегия закрывает сделку по рынку.
    • Для каждой новой позиции рассчитываются уровни стоп-лосса и тейк-профита. При достижении ценой уровня позиция немедленно закрывается.

Управление рисками

  • StopLossPoints и TakeProfitPoints переводятся в цену через шаг цены инструмента. Нулевое значение отключает соответствующий уровень.
  • OrderVolume позволяет задать торговый объём независимо от системного Volume. При перевороте к объёму добавляется модуль текущей позиции.

Параметры

Параметр Описание
JurxPeriod Период RSI, используемого вместо JurX. Соответствует одноимённому параметру в MQL.
JmaPeriod Длина Jurik Moving Average для дополнительного сглаживания.
SignalBar Смещение бара, по которому оценивается сигнал (1 = предыдущий закрытый бар).
EnableBuy / EnableSell Включение длинных и коротких входов.
AllowBuyClose / AllowSellClose Разрешение выходов при смене направления наклона осциллятора.
OrderVolume Объём новой позиции. При развороте добавляется к абсолютной величине текущей позиции.
TakeProfitPoints / StopLossPoints Расстояние тейк-профита и стоп-лосса в пунктах.
CandleType Таймфрейм свечей для вычислений (по умолчанию 4 часа).

Отличия от оригинала

  • JurX заменён на RSI + JMA из стандартной библиотеки StockSharp. Названия параметров сохранены для удобства переноса настроек.
  • MQL-параметры MM, MMMode и Deviation_ не используются. Управление размером позиции выполняется через OrderVolume или дополнительные модули StockSharp.
  • Регистрация сделок производится рыночными ордерами BuyMarket/SellMarket. Стопы и тейки реализованы как проверки диапазона завершившейся свечи.

Рекомендации по применению

  1. Выберите инструмент и задайте нужный CandleType, чтобы соответствовать графику из MetaTrader.
  2. Настройте JurxPeriod и JmaPeriod под конкретный рынок: увеличение значений сглаживает сигналы и уменьшает их количество.
  3. Изменяйте SignalBar, если требуется более консервативное подтверждение.
  4. Определите OrderVolume, StopLossPoints и TakeProfitPoints в соответствии с управлением рисками. Ноль отключает соответствующий уровень.
  5. Воспользуйтесь встроенными графическими элементами StockSharp (стратегия уже добавляет свечи и индикатор RSI), чтобы наблюдать за поведением осциллятора в реальном времени.

Стратегия остаётся верной идее ColorJJRSX и одновременно использует удобство высокоуровневого API StockSharp для тестирования и дальнейшего развития.

using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

public class ColorJjrsxTrendStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private decimal? _prevRsi;

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

	public ColorJjrsxTrendStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_rsiPeriod = Param(nameof(RsiPeriod), 14).SetGreaterThanZero().SetDisplay("RSI Period", "RSI lookback", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevRsi = 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); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevRsi = rsiVal; return; }
		if (_prevRsi == null) { _prevRsi = rsiVal; return; }
		if (_prevRsi.Value < 45m && rsiVal >= 55m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (_prevRsi.Value > 55m && rsiVal <= 45m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevRsi = rsiVal;
	}
}