Открыть на GitHub

Стратегия Bull & Bear Candle Martingale

Общее описание

Стратегия реагирует на сильные бычьи и медвежьи свечи и открывает позиции по направлению движения. Для длинных и коротких сделок ведутся независимые цепочки мартингейла: убыток по лонгу увеличивает следующий объём через параметр Bull Multiplier, убыток по шорту использует Bear Multiplier. Расстояния стоп-лосса и тейк-профита также задаются отдельно для каждого направления, что полностью повторяет возможности исходного MQL советника.

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

  1. Подписка на выбранный тип свечей (по умолчанию 1 минута) и обработка только закрытых свечей.
  2. При отсутствии позиции:
    • Бычий сигнал: Close > Open и тело свечи превышает фильтр для покупок — выполняется рыночная покупка.
    • Медвежий сигнал: Close < Open и тело больше порога для продаж — выполняется рыночная продажа.
  3. Для каждой сделки выставляются стоп-лосс и тейк-профит, преобразованные из пунктов в цену согласно шагу стоимости инструмента.
  4. После закрытия позиции вычисляется реализованный результат относительно сохранённой базы:
    • Отрицательный результат увеличивает объём следующей сделки в соответствующей цепочке мартингейла.
    • Положительный или нулевой результат возвращает объём к начальному значению.
  5. Пока позиция открыта, новые сигналы игнорируются, что обеспечивает поведение «одна сделка за раз», как в оригинальном роботе.

Управление капиталом

  • Цепочки мартингейла для длинных и коротких сделок не пересекаются, поэтому серия убытков по одной стороне не влияет на другую.
  • Объём автоматически приводится к допустимому шагу VolumeStep, чтобы избежать отклонения заявок.
  • Вызов StartProtection(useMarketOrders: true) активирует встроенную защиту StockSharp для сопроводительных стопов и тейков.

Параметры

Параметр Описание
Initial Volume Стартовый объём для обеих мартингейл-цепочек.
Bull Multiplier Множитель объёма для следующей длинной сделки после убытка.
Bear Multiplier Множитель объёма для следующей короткой сделки после убытка.
Bull Stop Loss Расстояние стоп-лосса в пунктах для лонгов (конвертируется в цену).
Bull Take Profit Расстояние тейк-профита в пунктах для лонгов.
Bear Stop Loss Расстояние стоп-лосса в пунктах для шортов.
Bear Take Profit Расстояние тейк-профита в пунктах для шортов.
Bull Body Filter Минимальный размер тела бычьей свечи в пунктах для открытия лонга.
Bear Body Filter Минимальный размер тела медвежьей свечи в пунктах для открытия шорта.
Candle Type Таймфрейм, на котором формируются сигналы (по умолчанию 1 минута).

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

  • Убедитесь, что инструмент предоставляет корректные PriceStep и VolumeStep. При отсутствии PriceStep стратегия использует значение 0.0001.
  • Логика мартингейла опирается на реализованный PnL, поэтому даже ручное закрытие позиций корректно обновляет цепочки.
  • Для оптимизации имеет смысл подбирать сочетания фильтров по телу свечи и множителей, чтобы найти баланс между частотой входов и глубиной просадки.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Bull/Bear Candle Martingale strategy: Bullish/bearish candle direction + EMA filter.
/// Buys after strong bullish candle when close crosses above EMA.
/// Sells after strong bearish candle when close crosses below EMA.
/// </summary>
public class BullBearCandleMartingaleStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;

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

	public int EmaPeriod
	{
		get => _emaPeriod.Value;
		set => _emaPeriod.Value = value;
	}

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

		_emaPeriod = Param(nameof(EmaPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period", "Indicators");
	}

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

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		decimal? prevClose = null;
		decimal? prevEma = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, (candle, emaVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var close = candle.ClosePrice;
				var bullish = close > candle.OpenPrice;
				var bearish = close < candle.OpenPrice;
				var bodySize = Math.Abs(close - candle.OpenPrice);
				var range = candle.HighPrice - candle.LowPrice;

				// Require strong candle body (>50% of range)
				var strongCandle = range > 0 && bodySize / range > 0.5m;

				if (prevClose.HasValue && prevEma.HasValue && strongCandle)
				{
					var crossUp = prevClose.Value <= prevEma.Value && close > emaVal;
					var crossDown = prevClose.Value >= prevEma.Value && close < emaVal;

					if (bullish && crossUp && Position <= 0)
						BuyMarket();
					else if (bearish && crossDown && Position >= 0)
						SellMarket();
				}

				prevClose = close;
				prevEma = emaVal;
			})
			.Start();

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