Bollinger Estratégia de paradas pendentes de banda
Visão geral
Este exemplo converte o consultor especialista MQL "Bb_0_1" original no StockSharp API de alto nível. A estratégia escuta uma assinatura de vela e usa bandas Bollinger para delimitar o preço atual. Quando o mercado fica entre as bandas superior e inferior, o algoritmo coloca três ordens de stop de compra em camadas acima do preço e três ordens de stop de venda em camadas abaixo do preço. Cada camada é configurada com distâncias de take-profit individuais enquanto compartilha a mesma referência de stop obtida da banda oposta.
Lógica de negociação
Assine o prazo configurado e calcule Bollinger Bandas com período e desvio solicitado.
Dentro da janela de negociação (StartHour < hora < EndHour) e enquanto o preço permanece entre as faixas, coloque ordens pendentes:
Três paradas de compra no nível da banda superior atual com lucros deslocados por FirstTakeProfit, SecondTakeProfit e ThirdTakeProfit etapas de preço acima da entrada.
Três paradas de venda no nível atual da banda inferior com lucros espelhados abaixo da entrada.
Todas as entradas herdam a banda oposta como parada protetora inicial.
As ordens pendentes são automaticamente registradas novamente sempre que as bandas se aproximam do preço, para que as ordens sigam os envelopes do indicador.
Depois que uma ordem stop é executada, a estratégia registra ordens explícitas de stop-loss e take-profit para o volume preenchido.
A proteção de rastreamento é opcional: UseBandTrailingStop seleciona a banda oposta para rastreamento, caso contrário, a banda do meio (EMA) é usada. O stop só termina quando o fechamento ultrapassa o preço de entrada e o valor do indicador fornece um nível melhor.
Parâmetros
Nome
Descrição
CandleType
Período usado para os cálculos da banda Bollinger.
BandPeriod
Quantidade de velas utilizadas pelas bandas.
BandDeviation
Multiplicador de desvio padrão para as bandas.
Volume
Volume de cada camada pendente.
StartHour / EndHour
Janela de negociação por hora (limites exclusivos).
Distâncias de lucro expressas em etapas de preços para cada camada.
UseBandTrailingStop
Selecione a referência final: banda oposta (true) ou Bollinger linha média (false).
Notas de implementação
O volume do pedido reflete o consultor especialista original usando um tamanho estático (Volume). O dimensionamento de posição baseado em risco do código MQL não é implementado porque o ambiente de amostra StockSharp não fornece histórico da conta.
Os parâmetros de mudança do indicador do script MQL não são expostos porque o nível superior API já fornece valores alinhados para a vela atual.
As ordens de proteção são ordens normais de stop e limite que são atualizadas sempre que as condições de trilha baseadas em banda melhoram o nível 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()