Ver en GitHub

Bollinger Estrategia de paradas pendientes de banda

Descripción general

Este ejemplo convierte el asesor experto MQL "Bb_0_1" original en la API de alto nivel de StockSharp. La estrategia escucha una suscripción de vela y utiliza Bollinger bandas para agrupar el precio actual. Cuando el mercado se sitúa entre las bandas superior e inferior, el algoritmo coloca tres órdenes stop de compra en capas por encima del precio y tres órdenes stop de venta en capas por debajo del precio. Cada capa está configurada con distancias de toma de ganancias individuales mientras comparte la misma referencia de parada tomada de la banda opuesta.

Lógica comercial

  • Suscríbete al timeframe configurado y calcula Bollinger Bandas con el período y desviación solicitados.
  • Dentro de la ventana de negociación (StartHour < hora < EndHour) y mientras el precio permanezca entre las bandas, coloque órdenes pendientes:
    • Tres paradas de compra en el nivel actual de la banda superior con toma de ganancias desplazadas por FirstTakeProfit, SecondTakeProfit y ThirdTakeProfit pasos de precio por encima de la entrada.
    • Tres paradas de venta en el nivel actual de la banda inferior con tomas de ganancias reflejadas debajo de la entrada.
    • Todas las entradas heredan la banda opuesta como parada protectora inicial.
  • Las órdenes pendientes se vuelven a registrar automáticamente cada vez que las bandas se acercan al precio, de modo que las órdenes sigan los sobres del indicador.
  • Una vez que se ejecuta una orden de parada, la estrategia registra órdenes explícitas de parada de pérdidas y toma de ganancias para el volumen completado.
  • La protección de seguimiento es opcional: UseBandTrailingStop selecciona la banda opuesta para el seguimiento; de lo contrario, se utiliza la banda media (EMA). Las paradas solo siguen cuando el cierre supera el precio de entrada y el valor del indicador proporciona un mejor nivel.

Parámetros

Nombre Descripción
CandleType Marco de tiempo utilizado para los cálculos de la banda Bollinger.
BandPeriod Número de velas utilizadas por las bandas.
BandDeviation Multiplicador de desviación estándar para las bandas.
Volume Volumen de cada capa pendiente.
StartHour / EndHour Ventana de negociación horaria (límites exclusivos).
FirstTakeProfit, SecondTakeProfit, ThirdTakeProfit Distancias de obtención de beneficios expresadas en incrementos de precios para cada capa.
UseBandTrailingStop Seleccione la referencia final: banda opuesta (true) o Bollinger línea media (false).

Notas de implementación

  • El volumen de pedidos refleja el asesor experto original utilizando un tamaño estático (Volume). El tamaño de posición basado en el riesgo del código MQL no se implementa porque el entorno de muestra StockSharp no proporciona el historial de la cuenta.
  • Los parámetros de cambio de indicador del script MQL no están expuestos porque el nivel alto API ya ofrece valores alineados para la vela actual.
  • Las órdenes de protección son órdenes stop y límite normales que se actualizan cada vez que las condiciones de seguimiento basadas en bandas mejoran el nivel de stop.
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 Band breakout strategy.
/// Buys when price closes above upper band, sells when price closes below lower band.
/// Exits at middle band.
/// </summary>
public class BollingerBandPendingStopsStrategy : Strategy
{
	private readonly StrategyParam<int> _bandPeriod;
	private readonly StrategyParam<decimal> _bandWidth;
	private readonly StrategyParam<DataType> _candleType;

	public int BandPeriod { get => _bandPeriod.Value; set => _bandPeriod.Value = value; }
	public decimal BandWidth { get => _bandWidth.Value; set => _bandWidth.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BollingerBandPendingStopsStrategy()
	{
		_bandPeriod = Param(nameof(BandPeriod), 20)
			.SetDisplay("Band Period", "Bollinger bands period", "Indicators");

		_bandWidth = Param(nameof(BandWidth), 1m)
			.SetDisplay("Band 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 = BandPeriod, Width = BandWidth };

		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.IsEmpty ? null : 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 - buy
		if (close > upper.Value && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Breakout below lower band - sell
		else if (close < lower.Value && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Exit at middle band
		else if (Position > 0 && close < middle.Value)
		{
			SellMarket();
		}
		else if (Position < 0 && close > middle.Value)
		{
			BuyMarket();
		}
	}
}