Открыть на GitHub

Стратегия Scalper EMA Simple

Обзор

Scalper EMA Simple — это порт MetaTrader-советника ScalperEMAEASimple. Стратегия сочетает быстрые и медленные экспоненциальные средние, осциллятор Стохастик и фильтр Average Directional Index (ADX), чтобы находить краткосрочные откаты внутри текущего тренда. По умолчанию она рассчитана на внутридневной скальпинг ликвидных валютных пар, однако может применяться к любым инструментам, где управление рисками ведётся в пунктах.

Реализация использует высокоуровневый API StockSharp и обрабатывает только закрытые свечи. Все вычисления выполняются последовательно, без повторного прохода по истории, что делает стратегию пригодной для реального времени.

Набор индикаторов

  • Быстрая EMA (FastEmaPeriod) — отслеживает краткосрочный импульс.
  • Медленная EMA (SlowEmaPeriod) — задаёт направление доминирующего тренда.
  • Стохастик (StochasticLength, StochasticKPeriod, StochasticDPeriod) — фиксирует развороты импульса возле зон перепроданности и перекупленности.
  • Average Directional Index — блокирует сделки, когда сила тренда превышает AdxThreshold.

Стохастик подтверждает импульс, когда линия %K возвращается выше уровня перепроданности (для покупок) или ниже уровня перекупленности (для продаж). EMA обеспечивают фильтр по направлению, а ADX ограничивает работу фазами спокойного отката, а не стремительного тренда.

Условия входа

  1. Свеча должна закрыться со стороны тренда относительно медленной EMA, а быстрая EMA обязана поддерживать то же направление (fast > slow для покупок, fast < slow для продаж).
  2. Расстояние от свечи до медленной EMA должно быть меньше диапазона свечи и трёх предыдущих расстояний. Так воспроизводится механизм поиска откатов из исходного MQL-кода.
  3. Тело свечи пересекает быструю EMA или быстрая EMA пересекает медленную. Это служит триггером на пробой.
  4. Стохастик должен подтвердить импульс пересечением из крайней зоны в пределах последних ConditionWindowBars свечей.
  5. ADX остаётся ниже AdxThreshold, чтобы не торговать при резком ускорении волатильности.
  6. Между сигналами одного направления проходит не менее SignalCooldownBars свечей.

При выполнении всех условий стратегия закрывает противоположные позиции и открывает новую сделку по рынку в обнаруженном направлении.

Выход и управление рисками

  • После входа устанавливается первоначальный стоп на расстоянии StopLossPips (пересчитывается в цену через размер пункта инструмента).
  • Когда нереализованная прибыль достигает TrailingActivationPips, активируется трейлинг со ступенью TrailingDistancePips.
  • При появлении противоположного сигнала позиция закрывается, после чего возможно открытие в обратную сторону.

Защитные приказы выставляются через SetStopLoss, поэтому они автоматически синхронизируются с текущим объёмом позиции.

Параметры

Параметр Описание
Volume Базовый торговый объём для сигнала. При наличии встречной позиции добавляется объём для полного разворота.
FastEmaPeriod / SlowEmaPeriod Периоды экспоненциальных средних.
StochasticLength, StochasticKPeriod, StochasticDPeriod Настройки стохастика, соответствующие исходному советнику.
StochasticOversold / StochasticOverbought Границы перепроданности и перекупленности.
AdxThreshold Максимальное значение ADX, допускающее сделку.
SignalCooldownBars Минимальная пауза между сигналами одного направления.
ConditionWindowBars Количество свечей, в течение которых должны одновременно выполняться условия отката, пробоя EMA и подтверждения стохастика.
StopLossPips Дистанция первоначального стоп-лосса в пунктах.
TrailingDistancePips Расстояние, поддерживаемое трейлинг-стопом.
TrailingActivationPips Прибыль в пунктах, необходимая для включения трейлинга.
CandleType Тип свечей, используемый всеми индикаторами (по умолчанию 5 минут).

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

  • Пересчёт пунктов основан на PriceStep. Для инструментов с 3 или 5 знаками после запятой добавляется множитель 10 — аналогично MetaTrader.
  • Стратегия реагирует только на закрытые свечи, поэтому сделки исполняются по цене закрытия бара.
  • Состояние хранит индексы последнего отката, пробоя EMA и подтверждения стохастика, что позволяет имитировать оконные проверки оригинального эксперта без пересмотра всей истории.

Использование

  1. Подключите стратегию к Connector или Trader с заданными инструментом и портфелем.
  2. Убедитесь, что у инструмента корректно задан PriceStep для конвертации пунктов в цену.
  3. Настройте параметры под волатильность рынка. Медленная EMA по умолчанию равна 740, как в оригинальном советнике; для более быстрых рынков её можно уменьшить.
  4. Запустите стратегию. При выполнении условий она автоматически откроет рыночную позицию и выставит защитные ордера.

Предупреждение: стратегия предоставлена в образовательных целях. Перед использованием на реальных счетах необходимы прогон на истории, форвард-тесты и анализ рисков.

using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// EMA scalper strategy combining fast/slow EMA trend with stochastic momentum.
/// Buys when fast EMA > slow EMA and stochastic is oversold.
/// Sells when fast EMA below slow EMA and stochastic is overbought.
/// </summary>
public class ScalperEmaSimpleStrategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaPeriod;
	private readonly StrategyParam<int> _slowEmaPeriod;
	private readonly StrategyParam<decimal> _stochOversold;
	private readonly StrategyParam<decimal> _stochOverbought;
	private readonly StrategyParam<DataType> _candleType;

	public int FastEmaPeriod
	{
		get => _fastEmaPeriod.Value;
		set => _fastEmaPeriod.Value = value;
	}

	public int SlowEmaPeriod
	{
		get => _slowEmaPeriod.Value;
		set => _slowEmaPeriod.Value = value;
	}

	public decimal StochOversold
	{
		get => _stochOversold.Value;
		set => _stochOversold.Value = value;
	}

	public decimal StochOverbought
	{
		get => _stochOverbought.Value;
		set => _stochOverbought.Value = value;
	}

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

	public ScalperEmaSimpleStrategy()
	{
		_fastEmaPeriod = Param(nameof(FastEmaPeriod), 20)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 50)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_stochOversold = Param(nameof(StochOversold), 10m)
			.SetDisplay("Stochastic Oversold", "Oversold level", "Indicators");

		_stochOverbought = Param(nameof(StochOverbought), 90m)
			.SetDisplay("Stochastic Overbought", "Overbought level", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Primary candle series", "General");
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
		var stochK = new StochasticK { Length = 14 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, stochK, ProcessCandle)
			.Start();

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

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

		// Buy: uptrend (fast > slow) + stochastic oversold
		if (fastValue > slowValue && stochK < StochOversold && Position <= 0)
		{
			BuyMarket(Position < 0 ? Math.Abs(Position) + 1 : 1);
		}
		// Sell: downtrend (fast < slow) + stochastic overbought
		else if (fastValue < slowValue && stochK > StochOverbought && Position >= 0)
		{
			SellMarket(Position > 0 ? Math.Abs(Position) + 1 : 1);
		}
	}
}