Открыть на GitHub

Стратегия Blockbuster Bollinger Breakout

Стратегия Blockbuster Bollinger Breakout — это перенос эксперт-советника MetaTrader 4 «BLOCKBUSTER EA» в инфраструктуру StockSharp. Оригинальная версия искала агрессивные развороты после рывка цены за пределы полос Боллинджера с дополнительным отступом. Переписанная стратегия сохраняет ключевые параметры и правила сопровождения сделок, но использует высокоуровневый API StockSharp.

Концепция

  1. Построить полосы Боллинджера с заданным периодом и множителем отклонения.
  2. Отслеживать, когда цена закрытия пересекает верхнюю/нижнюю полосу с учётом дополнительного отступа в пунктах.
  3. Открывать короткую позицию, если закрытие ушло выше верхней полосы + отступ. Открывать длинную позицию, если закрытие ушло ниже нижней полосы – отступ.
  4. Закрывать позицию по профиту или стоп-лоссу, выраженным в пунктах так же, как в MQL.

Отступ, стоп и цель задаются в пунктах инструмента и автоматически переводятся в цену через PriceStep. Значение 3 означает три минимальных шага цены независимо от тикера.

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

  • Индикатор

    • Полосы Боллинджера рассчитываются по ценам закрытия (в оригинале использовались цены открытия; в StockSharp такой вариант обеспечивает стабильность при работе с подписками на свечи).
    • Параметры: BollingerPeriod и BollingerDeviation.
    • Дополнительный параметр DistancePoints задаёт величину отступа.
  • Условия входа

    • Лонг: Close < LowerBand - Distance и позиция не длиннее нуля.
    • Шорт: Close > UpperBand + Distance и позиция не короче нуля.
    • При смене направления стратегия отправляет рыночный ордер объёмом TradeVolume + |Position|, что полностью повторяет механику «Only one order» из MT4.
  • Управление позицией

    • На каждой завершённой свече вычисляется нереализованный результат в пунктах относительно цены входа.
    • Тейк-профит: если прибыль >= ProfitTargetPoints.
    • Стоп-лосс: если убыток >= LossLimitPoints.
    • Оба ограничения можно отключить, установив 0.
    • Проверка тейка выполняется раньше стопа — как и в исходном коде.
  • Учёт состояния

    • Цена входа сохраняется при формировании сигнала и используется до закрытия позиции.
    • После выхода переменные состояния сбрасываются автоматически.

Параметры

Параметр Значение по умолчанию Описание
BollingerPeriod 20 Количество свечей в расчёте полос Боллинджера.
BollingerDeviation 2.0 Множитель стандартного отклонения.
DistancePoints 3 Дополнительное превышение за пределами полосы (в пунктах инструмента).
ProfitTargetPoints 3 Тейк-профит в пунктах. 0 — отключено.
LossLimitPoints 20 Стоп-лосс в пунктах. 0 — отключено.
TradeVolume 1 Базовый объём входа (аналог Lots в MT4).
CandleType Таймфрейм 1 минута Тип свечей для расчёта.

Практические рекомендации

  • Лучше всего стратегия показывает себя на инструментах с чётким PriceStep: валютные пары, индексы, ликвидные фьючерсы.
  • Из-за использования цен закрытия рекомендуется протестировать выбранный таймфрейм, чтобы убедиться в сопоставимости результатов с MT4.
  • В коде задействованы визуализации DrawCandles, DrawIndicator и DrawOwnTrades, поэтому при наличии графика сразу видны полосы и сделки.
  • Логика работает только на завершённых свечах, что делает поведение устойчивым в тестах и реальной торговле.

Теги

  • Категория: Контртрендовые пробои
  • Направление: Лонг и шорт
  • Индикаторы: Bollinger Bands
  • Стопы: Да (настраиваемые)
  • Таймфрейм: Краткосрочный (по умолчанию 1 минута)
  • Сложность: Простая
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>
/// Blockbuster Bollinger breakout strategy.
/// Buys when price closes below lower Bollinger band (mean reversion).
/// Sells when price closes above upper Bollinger band.
/// Exits at middle band.
/// </summary>
public class BlockbusterBollingerStrategy : Strategy
{
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerWidth;
	private readonly StrategyParam<DataType> _candleType;

	public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
	public decimal BollingerWidth { get => _bollingerWidth.Value; set => _bollingerWidth.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BlockbusterBollingerStrategy()
	{
		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetDisplay("BB Period", "Bollinger bands period", "Indicators");

		_bollingerWidth = Param(nameof(BollingerWidth), 1m)
			.SetDisplay("BB Width", "Bollinger bands deviation", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); }

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

		var bb = new BollingerBands { Length = BollingerPeriod, Width = BollingerWidth };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(bb, ProcessCandle)
			.Start();
	}

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

		if (!value.IsFinal || value.IsEmpty)
			return;

		var bbVal = value as BollingerBandsValue;
		if (bbVal == null)
			return;

		var upper = bbVal.UpBand;
		var lower = bbVal.LowBand;
		var middle = bbVal.MovingAverage;

		if (upper == null || lower == null || middle == null)
			return;

		var close = candle.ClosePrice;

		// Breakout above upper band - momentum buy
		if (close > upper.Value && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Breakout below lower band - momentum sell
		else if (close < lower.Value && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Exit long at middle
		else if (Position > 0 && close < middle.Value)
		{
			SellMarket();
		}
		// Exit short at middle
		else if (Position < 0 && close > middle.Value)
		{
			BuyMarket();
		}
	}
}