Ver no GitHub

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).
FirstTakeProfit, SecondTakeProfit, ThirdTakeProfit 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();
		}
	}
}