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).
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();
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import BollingerBands
from StockSharp.Algo.Strategies import Strategy
class bollinger_band_pending_stops_strategy(Strategy):
def __init__(self):
super(bollinger_band_pending_stops_strategy, self).__init__()
self._band_period = self.Param("BandPeriod", 20) \
.SetDisplay("Band Period", "Bollinger bands period", "Indicators")
self._band_width = self.Param("BandWidth", 1.0) \
.SetDisplay("Band Width", "Bollinger bands deviation", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
@property
def band_period(self):
return self._band_period.Value
@property
def band_width(self):
return self._band_width.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(bollinger_band_pending_stops_strategy, self).OnReseted()
def OnStarted2(self, time):
super(bollinger_band_pending_stops_strategy, self).OnStarted2(time)
bb = BollingerBands()
bb.Length = self.band_period
bb.Width = self.band_width
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(bb, self.process_candle).Start()
def process_candle(self, candle, bb_value):
if candle.State != CandleStates.Finished:
return
if not bb_value.IsFinal or bb_value.IsEmpty:
return
if bb_value.UpBand is None or bb_value.LowBand is None or bb_value.MovingAverage is None:
return
upper = float(bb_value.UpBand)
lower = float(bb_value.LowBand)
middle = float(bb_value.MovingAverage)
close = float(candle.ClosePrice)
if close > upper and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif close < lower and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
elif self.Position > 0 and close < middle:
self.SellMarket()
elif self.Position < 0 and close > middle:
self.BuyMarket()
def CreateClone(self):
return bollinger_band_pending_stops_strategy()