Открыть на GitHub

Стратегия BollTrade Bollinger Reversion

Обзор

BollTrade Bollinger Reversion Strategy — это конвертация оригинального эксперта BollTrade из MetaTrader в высокоуровневую стратегию StockSharp. Стратегия торгует одним инструментом по сигналам индикатора полос Боллинджера и ожидает, когда цена выйдет за границы полосы на величину дополнительного буфера в пунктах. Если свеча закрывается выше верхней полосы, стратегия открывает короткую позицию, а если закрывается ниже нижней полосы — длинную позицию. Расчёты выполняются только по завершённым свечам, чтобы избежать реакции на незавершённые данные.

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

  1. Подписаться на выбранный тип свечей и рассчитать Bollinger Bands с заданным периодом и отклонением.
  2. Вычислить дополнительное смещение в пунктах, чтобы повторить буфер, использовавшийся в оригинальном советнике.
  3. При закрытии свечи ниже нижней полосы минус смещение открыть длинную позицию. При закрытии выше верхней полосы плюс смещение открыть короткую позицию.
  4. Для каждой позиции сохранить уровни стоп-лосса и тейк-профита, заданные в пунктах. Это имитирует закрытие сделок при достижении заданной прибыли или убытка в версии MetaTrader.
  5. Закрывать позицию, если диапазон свечи пересекает уровни стоп-лосса или тейк-профита. Дополнительного наращивания позиции не выполняется.

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

  • Параметр Lots задаёт базовый объём сделки.
  • При включенном LotIncrease объём увеличивается пропорционально росту стоимости портфеля относительно значения на момент запуска стратегии, но не более 500 лотов. Это повторяет логику масштабирования из MetaTrader.

Параметры

Параметр Описание
Take Profit (pips) Расстояние в пунктах для расчёта тейк-профита от цены входа. Ноль отключает тейк-профит.
Stop Loss (pips) Расстояние в пунктах для расчёта стоп-лосса от цены входа. Ноль отключает стоп-лосс.
Band Offset Дополнительное расстояние в пунктах сверх полос Боллинджера перед открытием сделки.
Bollinger Period Количество свечей в расчёте среднего Bollinger Bands.
Bollinger Deviation Множитель стандартного отклонения для ширины полос.
Base Volume Базовый торговый объём в лотах.
Scale Volume При включении увеличивает объём заявок при росте стоимости портфеля.
Candle Type Тип свечей (таймфрейм), по которым формируются сигналы.

Примечания

  • Стратегия работает только по завершённым свечам, поэтому ей необходима историческая подкачка данных для прогрева.
  • Проверка стоп-лоссов и тейк-профитов выполняется по диапазону свечей, что приблизительно повторяет тиковую логику оригинала при использовании высокоуровневого API.
  • Защитный механизм StartProtection активирован для предотвращения нежелательных позиций при остановке стратегии.
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>
/// Bollinger Bands reversion strategy.
/// Buys when price closes below lower band, sells when above upper band.
/// Uses middle band as exit target.
/// </summary>
public class BollTradeBollingerReversionStrategy : 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 BollTradeBollingerReversionStrategy()
	{
		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");

		_bollingerWidth = Param(nameof(BollingerWidth), 0.5m)
			.SetDisplay("BB Width", "Bollinger Bands width", "Indicators");

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

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	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 bbValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!bbValue.IsFinal)
			return;

		var bb = (BollingerBandsValue)bbValue;
		var upper = bb.UpBand;
		var lower = bb.LowBand;
		var middle = bb.MovingAverage;

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

		var close = candle.ClosePrice;
		var upperVal = upper.Value;
		var lowerVal = lower.Value;
		var midVal = middle.Value;

		// Buy when close below lower band (oversold)
		if (close < lowerVal && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Sell when close above upper band (overbought)
		else if (close > upperVal && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}