Открыть на GitHub

Стратегия Slow Stochastic Mode

Slow Stochastic Mode Strategy — это перенос эксперта MetaTrader Exp_Slow-Stoch.mq5 на высокоуровневый API StockSharp. Система работает по закрытию сформированных свечей и использует сглаженный стохастический осциллятор для поиска смены режима. Трейдер может выбрать один из трёх алгоритмов сигналов: пробой уровня, разворот импульса или пересечение линий.

Основная идея

Стратегия анализирует линии %K и %D стохастика, дополнительно сглажённые параметром Slowing. В зависимости от выбранного режима сигнала (Mode) алгоритм оценивает значения индикатора на одной или нескольких прошедших свечах (SignalBar) и при выполнении условий открывает позицию либо закрывает противоположную. Все заявки отправляются рыночными приказами.

Режимы сигналов

  • Breakdown — отслеживает пробой уровня 50 линией %K. Пересечение снизу вверх открывает длинную позицию и закрывает короткую. Пересечение сверху вниз открывает короткую позицию и закрывает длинную.
  • Twist — реагирует на изменение направления %K. Если два бара назад осциллятор снижался, а на анализируемой свече развернулся вверх, стратегия входит или переворачивается в лонг. Обратная ситуация формирует сигнал на шорт.
  • CloudTwist — контролирует смену цвета «облака» стохастика через пересечение %K и %D. Бычье пересечение (%K выше %D) открывает и защищает длинные позиции, медвежье (%K ниже %D) делает противоположное.

Все режимы учитывают четыре флага разрешений: входы и выходы для лонгов и шортов можно включать или выключать независимо.

Параметры

Параметр По умолчанию Описание
CandleType Таймфрейм H4 Тип свечей для расчётов.
KPeriod 5 Длина периода для линии %K.
DPeriod 3 Период усреднения %D.
Slowing 3 Дополнительное сглаживание %K.
SignalBar 1 Сколько закрытых баров назад анализируется сигнал.
StopLossPoints 1000 Размер стоп-лосса в шагах цены (0 — отключить).
TakeProfitPoints 2000 Размер тейк-профита в шагах цены (0 — отключить).
EnableLongEntries true Разрешение открывать длинные позиции.
EnableShortEntries true Разрешение открывать короткие позиции.
EnableLongExits true Разрешение закрывать лонги по сигналу.
EnableShortExits true Разрешение закрывать шорты по сигналу.
Mode Twist Выбранный режим сигналов.

Используется встроенный индикатор StockSharp StochasticOscillator. Параметр SignalBar позволяет повторить поведение MetaTrader: по умолчанию анализируется предыдущая свеча (значение 1), а при нуле стратегия реагирует на последнюю завершённую свечу.

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

  • Приказы выставляются методами BuyMarket и SellMarket. При перевороте объём увеличивается на абсолютное значение текущей позиции, чтобы закрыть старую и открыть новую.
  • Защитные стоп-лосс и тейк-профит подключаются через StartProtection. Значения трактуются как количество тиков и автоматически переводятся в абсолютное расстояние с учётом шага цены инструмента.
  • Трейлинг не используется: уровни защиты остаются неизменными до их срабатывания или принудительного выхода.

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

  • В режиме Breakdown тот же пробой уровня, который открывает позицию в одном направлении, закрывает противоположную.
  • В режиме Twist фиксация разворота импульса сначала закрывает текущую позицию, затем открывает новую в обратную сторону.
  • В режиме CloudTwist пересечение линий одновременно даёт сигнал на вход и закрывает позицию противоположного типа.

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

Особенности реализации

  • Значения стохастика сохраняются во внутренних буферах, что позволяет обращаться к нужным смещениям по барам, как в оригинальном советнике.
  • Расчёты выполняются только на полностью сформированных свечах (candle.State == Finished).
  • При наличии графической подсистемы выводятся свечи, стохастик и сделки стратегии.

Конверсия сохраняет логику MQL5-версии и использует преимущества 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;

/// <summary>
/// Slow Stochastic Mode strategy. Uses EMA crossover for trend following.
/// </summary>
public class SlowStochasticModeStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal? _prevFast;
	private decimal? _prevSlow;

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public SlowStochasticModeStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 5)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
	}

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

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

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

		_prevFast = null;
		_prevSlow = null;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

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

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		if (_prevFast == null || _prevSlow == null)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		var prevAbove = _prevFast.Value > _prevSlow.Value;
		var currAbove = fastVal > slowVal;

		_prevFast = fastVal;
		_prevSlow = slowVal;

		if (!prevAbove && currAbove && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (prevAbove && !currAbove && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}