Открыть на GitHub

Стратегия Deep Drawdown MA

Обзор

Deep Drawdown MA — это портирована версия советника MetaTrader 5 «Deep Drawdown MA (barabashkakvn's edition)», реализованная на высокоуровневом API StockSharp. Алгоритм торгует пересечением скользящих средних и одновременно защищает сделки, уходящие в просадку, переводом их в безубыток. В стратегии сохранены все ключевые параметры исходного робота: настройки двух скользящих средних, ограничение на число набираемых позиций и выбор, закрывать ли убыточные сделки сразу при смене сигнала.

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

  • Индикаторы: две скользящие средние с отдельными периодами, типами цены и смещением по истории. Метод сглаживания (SMA, EMA, SMMA или LWMA) общий для обеих средних.
  • Входы:
    • Покупка — когда смещённая быстрая средняя пересекает сверху смещённую медленную. Стратегия докупает заданный объём и при необходимости закрывает шорты, если предыдущее открытие было не на покупку и лимит позиций не превышен.
    • Продажа — когда смещённая быстрая средняя уходит ниже смещённой медленной. Открывается короткая позиция (с учётом покрытия лонгов), если последняя сделка не была продажей и сохранён запас по лимиту.
  • Выходы:
    • Из лонга — при обратном пересечении (fast < slow) позиция либо закрывается сразу (CloseLosses = true), либо переводится в режим ожидания безубытка. В режиме безубытка стратегия ждёт, пока закрытие свечи вернётся к средней цене входа, и только потом фиксирует позицию.
    • Из шорта — зеркальная логика: при развороте (fast > slow) позиция закрывается мгновенно или ставится в очередь на безубыток до возврата цены к средней цене входа.
  • Учёт позиции: средняя цена входа и направление последней сделки пересчитываются по собственным сделкам, что позволяет повторить поведение MT5 без прямого доступа к позициям.

Параметры

Название Описание Значение по умолчанию
OrderVolume Объём заявки при каждом рыночном входе. 0.1
MaxPositions Максимальный суммарный объём по направлению (нетто-позиция). 5
CloseLosses Закрывать ли убыточные позиции сразу при смене сигнала. false
FastMaPeriod / SlowMaPeriod Периоды быстрой и медленной скользящих. 10 / 30
FastMaShift / SlowMaShift Смещение индикатора по истории (аналог параметра shift в MT5). 3 / 0
FastPriceType / SlowPriceType Тип цены для расчёта (Close, Open, High, Low, Median, Typical, Weighted). Close
MaMethod Тип сглаживания для обеих средних (SMA, EMA, SMMA, LWMA). SMA
CandleType Тип свечей, по которым ведутся расчёты. 15-минутные свечи

Особенности конверсии

  • В MT5 советник мог одновременно держать встречные позиции (hedging). StockSharp работает с нетто-позицией, поэтому в портированной версии ограничение по количеству сделок применяется к суммарному объёму по направлению.
  • Защита от глубокой просадки реализована через внутренние флаги без модификации заявок. Стратегия отслеживает закрытия свечей и закрывает позицию по восстановленной средней цене входа.
  • Параметр смещения скользящей средней реализован через короткую очередь последних значений индикатора, что повторяет поведение MT5 без обращения к буферам индикаторов.

Как использовать

  1. Подключите стратегию к нужному инструменту, задайте OrderVolume, тип свечей и параметры скользящих средних под ваш таймфрейм.
  2. Запустите стратегию и убедитесь, что подписка на свечи активна и разрешена торговля.
  3. Следите за логом: при срабатывании режима безубытка позиция будет закрыта автоматически при возврате цены к средней.

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

  • Включите CloseLosses = true, если требуется немедленно закрывать убыточные позиции при смене тренда.
  • Подберите MaxPositions, чтобы ограничить наращивание позиции после последовательных разворотных сигналов.
  • Используйте встроенную защиту StartProtection и другие средства Risk Management StockSharp для дополнительного контроля.

Состав папки

  • CS/DeepDrawdownMaStrategy.cs — реализация стратегии на C#.
  • README.md, README_ru.md, README_zh.md — подробная документация на трёх языках.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Deep drawdown MA crossover strategy (simplified).
/// Uses fast/slow EMA crossover with position management.
/// </summary>
public class DeepDrawdownMaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	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 DeepDrawdownMaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");

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

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

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

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

		decimal prevFast = 0, prevSlow = 0;
		bool hasPrev = false;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, (ICandleMessage candle, decimal fastValue, decimal slowValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!hasPrev)
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					hasPrev = true;
					return;
				}

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					return;
				}

				if (prevFast <= prevSlow && fastValue > slowValue && Position <= 0)
					BuyMarket();
				else if (prevFast >= prevSlow && fastValue < slowValue && Position >= 0)
					SellMarket();

				prevFast = fastValue;
				prevSlow = slowValue;
			})
			.Start();

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