Открыть на GitHub

Стратегия Rollback System

Стратегия представляет собой порт MetaTrader 5 эксперта «Rollback system» на платформу StockSharp. Как и оригинал, она анализирует последние 24 часовые свечи в момент начала нового торгового дня и ищет чрезмерные движения, способные дать обратный откат.

Логика работы

  1. Используется таймфрейм CandleType (по умолчанию 1 час).
  2. Проверка сигналов выполняется один раз в сутки – в промежутке с 00:00 до 00:03. В понедельник и пятницу сделки не открываются.
  3. Перед входом стратегия убеждается, что активных позиций нет.
  4. На основании 24 последних завершённых свечей рассчитываются величины:
    • Open_24_minus_Close_1 – разница между ценой открытия 24 бара назад и последним закрытием.
    • Close_1_minus_Open_24 – обратная разница, показывающая дневное изменение.
    • Close_1_minus_Lowest – удалённость закрытия от минимальной цены дня.
    • Highest_minus_Close_1 – удалённость закрытия от максимума дня.
  5. Сигналы (все пороги переводятся из пунктов в цену):
    • Покупка №1 – предыдущий день снизился (Open_24_minus_Close_1 выше ChannelOpenClosePips), а закрытие осталось возле минимума (Close_1_minus_Lowest меньше RollbackPips - ChannelRollbackPips).
    • Покупка №2 – предыдущий день вырос (Close_1_minus_Open_24 выше порога), но закрылся значительно ниже максимума (Highest_minus_Close_1 больше RollbackPips + ChannelRollbackPips).
    • Продажа №1 – предыдущий день вырос и закрылся возле максимума (Highest_minus_Close_1 меньше RollbackPips - ChannelRollbackPips).
    • Продажа №2 – предыдущий день упал, но закрытие сильно восстановилось (Close_1_minus_Lowest больше RollbackPips + ChannelRollbackPips).
  6. Вход осуществляется рыночными ордерами BuyMarket/SellMarket с объёмом TradeVolume. Значения StopLossPips и TakeProfitPips задают расстояние до защитных уровней (нулевые значения отключают их).
  7. После открытия позиции стратегия на каждом завершённом баре контролирует срабатывание уровней. При пробое стопа или тейка внутри бара позиция закрывается маркет-заявкой, что воспроизводит механику MT5-советника с жёсткими ордерами.

Конвертация пунктов

В MT5 для инструментов с 3 и 5 знаками после запятой пункт автоматически умножается на 10. Порт сохраняет это поведение: используется PriceStep инструмента, а при количестве знаков 3 или 5 применяется десятикратный множитель. Благодаря этому все пороговые значения и защитные уровни совпадают с исходной реализацией.

Параметры

Параметр Описание
TradeVolume Объём, с которым размещаются рыночные ордера.
StopLossPips Стоп-лосс в пунктах (0 – отключён).
TakeProfitPips Тейк-профит в пунктах (0 – отключён).
RollbackPips Базовое требование к величине отката.
ChannelOpenClosePips Минимальная разница между открытием и закрытием предыдущего дня.
ChannelRollbackPips Допуск, добавляемый к условию отката.
CandleType Рабочий таймфрейм, по умолчанию часовые свечи.

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

  • В MT5-версии рисовались прямоугольники на графике; в портированной версии оставлена только торговая логика.
  • Управление рисками реализовано внутри стратегии, а не через реальные стоп-заявки, что соответствует высокоуровневому 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 RollbackSystemStrategy : 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 RollbackSystemStrategy()
	{
		_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 < 30m && rsiVal >= 30m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (_prevRsi.Value > 70m && rsiVal <= 70m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevRsi = rsiVal;
	}
}