Открыть на GitHub

Стратегия Stochastic Accelerator

Обзор

Стратегия Stochastic Accelerator — это конверсия эксперта MetaTrader 5 #2 stoch mt5. Оригинальный советник анализирует три осциллятора Stochastic совместно с осциллятором Accelerator Билла Уильямса и Awesome Oscillator. Длинная позиция открывается только тогда, когда все стохастические фильтры указывают на бычью инерцию, а Accelerator Oscillator пробивает вверх заданный порог. Короткие позиции используют симметричные условия. После входа контроль импульса передаётся Awesome Oscillator — при обратном пересечении заданного уровня позиция закрывается. Портирование на StockSharp повторяет эту логику, применяя высокоуровневые подписки на свечи и привязку индикаторов через API.

Стратегия сохраняет структуру управления капиталом оригинала. Входы выполняются фиксированным лотом, а стоп-лосс и тейк-профит заданы в метатрейдеровских пунктах. В реализации StockSharp используется StartProtection, поэтому защитные уровни прикрепляются к каждой новой позиции автоматически. Размер шага цены преобразуется в пункты MetaTrader, что обеспечивает одинаковые защитные расстояния у разных брокеров.

Логика торговли

  1. Подписаться на свечи типа CandleType и обрабатывать только закрытые бары, как делает эксперт на MetaTrader.
  2. Питать три экземпляра StochasticOscillator:
    • Сигнальный стохастик проверяет, находится ли %K выше или ниже %D.
    • Стохастик входа убеждается, что бычьи сигналы находятся выше EntryLevel (для продаж используется 100 - EntryLevel).
    • Стохастик фильтра ограничивает бычьи сигналы, требуя, чтобы %K оставался ниже FilterLevel (для продаж — выше 100 - FilterLevel).
  3. Отслеживать Accelerator Oscillator и требовать пересечения уровня AcceleratorLevel вверх для покупок и вниз через -AcceleratorLevel для продаж.
  4. Закрывать открытую позицию, когда Awesome Oscillator пересекает уровень AwesomeLevel в противоположном направлении.
  5. После выхода открывать новую позицию только в том случае, если условия выполнены ровно по одной стороне. Объём корректируется под шаг лота инструмента, чтобы заявки принимались реальным брокером.
  6. Применять стоп-лосс и тейк-профит через StartProtection, сохраняя пунктовую систему рисков MetaTrader.

Параметры

Имя Тип Значение по умолчанию Описание
CandleType DataType Таймфрейм 4 часа Основные свечи, которые обрабатывает стратегия.
TradeVolume decimal 0.01 Объём входа в лотах.
StopLossPips decimal 40 Дистанция стоп-лосса в пунктах MetaTrader.
TakeProfitPips decimal 70 Дистанция тейк-профита в пунктах MetaTrader.
SignalKPeriod int 40 Период %K сигнального стохастика.
SignalDPeriod int 10 Сглаживание %D сигнального стохастика.
SignalSlowing int 10 Дополнительное сглаживание сигнального стохастика.
EntryKPeriod int 40 Период %K стохастика входа.
EntryDPeriod int 10 Сглаживание %D стохастика входа.
EntrySlowing int 10 Дополнительное сглаживание стохастика входа.
EntryLevel decimal 20 Нижний уровень подтверждения покупок (для продаж используется 100 - EntryLevel).
FilterKPeriod int 40 Период %K фильтрующего стохастика.
FilterDPeriod int 10 Сглаживание %D фильтрующего стохастика.
FilterSlowing int 10 Дополнительное сглаживание фильтрующего стохастика.
FilterLevel decimal 75 Верхний уровень ограничения покупок (для продаж используется 100 - FilterLevel).
AcceleratorLevel decimal 0.0002 Минимальная амплитуда Accelerator Oscillator для входа.
AwesomeLevel decimal 0.0013 Порог Awesome Oscillator, при котором позиция закрывается.

Отличия от оригинального эксперта MetaTrader

  • Вместо многократных вызовов CopyBuffer используются свечные подписки и привязка индикаторов StockSharp.
  • Управление позициями ведётся в неттинговом режиме: при необходимости разворота текущая позиция сначала закрывается, затем отправляется рыночная заявка в противоположную сторону.
  • Стоп-лосс и тейк-профит подключаются через StartProtection, при этом расстояния вычисляются в пунктах на основе шага цены инструмента — это избавляет от ручной модификации ордеров и сохраняет эквивалентность метатрейдеровским настройкам.
  • Запрашиваемый объём нормализуется по VolumeStep, MinVolume и MaxVolume, чтобы код можно было сразу использовать в реальной торговле.

Рекомендации по использованию

  • Перед запуском настройте TradeVolume под минимальный шаг лота инструмента.
  • Совместно подбирайте уровни стохастиков (EntryLevel, FilterLevel) и пороги осцилляторов, чтобы добиться нужной строгости фильтров на вашем рынке.
  • При возможности включайте отображение на графике, чтобы видеть три стохастика, Accelerator Oscillator, Awesome Oscillator и совершённые сделки.
  • Так как расчёт ведётся на закрытых свечах, сигналы появляются в момент закрытия бара. Используйте тестер с тем же таймфреймом для сопоставимых результатов.

Индикаторы

  • Три экземпляра StochasticOscillator с независимыми параметрами сглаживания и уровнями.
  • AcceleratorOscillator для подтверждения входа.
  • AwesomeOscillator для фиксации момента выхода.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Stochastic Accelerator strategy: Rate of Change crossover.
/// Buys when ROC crosses above zero, sells when ROC crosses below zero.
/// </summary>
public class StochasticAcceleratorStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _period;
	private readonly StrategyParam<decimal> _rocLevel;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _prevRoc;
	private int _candlesSinceTrade;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int Period { get => _period.Value; set => _period.Value = value; }
	public decimal RocLevel { get => _rocLevel.Value; set => _rocLevel.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public StochasticAcceleratorStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_period = Param(nameof(Period), 12)
			.SetGreaterThanZero()
			.SetDisplay("Period", "ROC period", "Indicators");
		_rocLevel = Param(nameof(RocLevel), 0.2m)
			.SetDisplay("ROC Level", "ROC threshold for crossover", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevRoc = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevRoc = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
		var roc = new RateOfChange { Length = Period };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(roc, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (_hasPrev)
		{
			if (_prevRoc <= -RocLevel && rocValue > -RocLevel && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (_prevRoc >= RocLevel && rocValue < RocLevel && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevRoc = rocValue;
		_hasPrev = true;
	}
}