Открыть на GitHub

Стратегия BBStrategy

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

BBStrategy — это портированная из MetaTrader экспертная система «BBStrategy», основанная на расширениях полос Боллинджера. Алгоритм отслеживает две пары полос с одинаковым периодом, но разными коэффициентами отклонения. После прорыва внешней полосы стратегия переходит в режим ожидания сделки и открывает позицию только тогда, когда цена возвращается внутрь внутренней полосы, подтверждая продолжение импульса без чрезмерного перекупленности/перепроданности.

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

  1. Подписка на свечи и расчёт двух индикаторов Bollinger Bands:
    • Внешняя полоса использует настраиваемое отклонение (по умолчанию 3.0).
    • Внутренняя полоса рассчитывается с меньшим отклонением (по умолчанию 2.0).
  2. Фиксация закрытия свечи за пределами внешней полосы:
    • Закрытие выше верхней внешней полосы активирует режим ожидания покупки.
    • Закрытие ниже нижней внешней полосы активирует режим ожидания продажи.
  3. Вход осуществляется только если следующая завершённая свеча закрывается внутри внутренней полосы в сторону сигнала. Пока цена не вернулась в диапазон, стратегия остаётся в режиме ожидания для соответствующего направления.
  4. При выполнении условий отправляется одна рыночная заявка, если нет открытых позиций и активных заявок. Противоположная позиция закрывается увеличенным объёмом рыночной заявки.
  5. Опциональные стоп-лосс и тейк-профит задаются в пунктах и автоматически переводятся в абсолютные цены через встроенный модуль защиты.

Параметры

Название Описание
Order Volume Объём каждой сделки.
Bollinger Period Количество свечей в расчёте полос Боллинджера.
Inner Deviation Множитель отклонения для внутренней полосы.
Outer Deviation Множитель отклонения для внешней полосы.
Stop-Loss Points Дистанция стоп-лосса в пунктах (0 отключает защиту).
Take-Profit Points Дистанция тейк-профита в пунктах (0 отключает цель).
Candle Type Таймфрейм свечей для расчётов.

Дополнительные заметки

  • Стратегия работает только с одной позицией и игнорирует новые сигналы при наличии активных заявок.
  • Перевод пунктов MetaTrader в реальные изменения цены выполняется исходя из шага цены инструмента.
  • Для визуального контроля на график выводятся свечи, обе полосы Боллинджера и собственные сделки стратегии.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Bollinger Bands breakout strategy.
/// When price breaks above outer band, waits for re-entry into inner band then goes long.
/// When price breaks below outer band, waits for re-entry into inner band then goes short.
/// </summary>
public class BBStrategy : Strategy
{
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _innerDeviation;
	private readonly StrategyParam<decimal> _outerDeviation;
	private readonly StrategyParam<DataType> _candleType;

	public int BollingerPeriod
	{
		get => _bollingerPeriod.Value;
		set => _bollingerPeriod.Value = value;
	}

	public decimal InnerDeviation
	{
		get => _innerDeviation.Value;
		set => _innerDeviation.Value = value;
	}

	public decimal OuterDeviation
	{
		get => _outerDeviation.Value;
		set => _outerDeviation.Value = value;
	}

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

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

		_innerDeviation = Param(nameof(InnerDeviation), 2m)
			.SetDisplay("Inner Dev", "Inner band deviations", "Indicators");

		_outerDeviation = Param(nameof(OuterDeviation), 3m)
			.SetDisplay("Outer Dev", "Outer band deviations", "Indicators");

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

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

		var innerBand = new BollingerBands
		{
			Length = BollingerPeriod,
			Width = InnerDeviation
		};

		var outerBand = new BollingerBands
		{
			Length = BollingerPeriod,
			Width = OuterDeviation
		};

		var waitDirection = 0;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(innerBand, outerBand, (candle, innerVal, outerVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!innerBand.IsFormed || !outerBand.IsFormed)
					return;

				if (innerVal.IsEmpty || outerVal.IsEmpty)
					return;

				var innerBb = innerVal as IBollingerBandsValue;
				var outerBb = outerVal as IBollingerBandsValue;

				if (innerBb == null || outerBb == null)
					return;

				var innerUpper = innerBb.UpBand ?? 0;
				var innerLower = innerBb.LowBand ?? 0;
				var outerUpper = outerBb.UpBand ?? 0;
				var outerLower = outerBb.LowBand ?? 0;

				if (innerUpper == 0 || innerLower == 0 || outerUpper == 0 || outerLower == 0)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var price = candle.ClosePrice;
				var signal = 0;

				// Detect outer band breakout
				if (price > outerUpper)
					waitDirection = 1;
				else if (price < outerLower)
					waitDirection = -1;

				// Check re-entry into inner band
				if (waitDirection > 0 && price < innerUpper && price > innerLower)
				{
					signal = 1;
					waitDirection = 0;
				}
				else if (waitDirection < 0 && price > innerLower && price < innerUpper)
				{
					signal = -1;
					waitDirection = 0;
				}

				if (signal == 1 && Position <= 0)
					BuyMarket();
				else if (signal == -1 && Position >= 0)
					SellMarket();
			})
			.Start();

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