Ver no GitHub

Estratégia BBStrategy

Visão geral

BBStrategy é um sistema de breakout de bandas Bollinger convertido do consultor especialista MetaTrader "BBStrategy". A estratégia rastreia dois conjuntos de bandas Bollinger com o mesmo período, mas multiplicadores de desvio diferentes. Quando o preço ultrapassa a banda externa, o algoritmo arma uma negociação, mas a entrada real é adiada até que o preço retorne à banda interna. Este comportamento tenta evitar a compra de rompimentos excessivamente estendidos ou a venda de condições profundamente sobrevendidas, ao mesmo tempo em que captura o movimento de continuação após uma expansão de volatilidade.

Lógica principal

  1. Assine velas e calcule duas Bollinger bandas:
    • A banda externa usa um multiplicador de desvio configurável (padrão 3.0).
    • Banda interna usa um desvio menor (padrão 2,0).
  2. Detecte quando o preço de fechamento termina fora da banda externa:
    • Acima da faixa externa superior arma uma configuração longa.
    • Abaixo dos braços da faixa externa inferior, uma configuração curta.
  3. Insira apenas se a próxima vela concluída fechar dentro da faixa interna na direção do rompimento. Enquanto o preço espera para entrar novamente, a estratégia permanece em estado de “espera” para a direção correspondente.
  4. Envie uma única ordem de mercado quando as condições estiverem alinhadas e não houver posições abertas ou ordens ativas. As posições opostas existentes são fechadas aumentando o volume da ordem de mercado.
  5. As distâncias opcionais de take-profit e stop-loss (expressas em pontos) são convertidas em compensações de preço absoluto e gerenciadas por meio do auxiliar de proteção integrado.

Parâmetros

Nome Descrição
Volume do pedido Tamanho da negociação para cada posição.
Bollinger Período Número de velas usadas para ambos os cálculos de banda Bollinger.
Desvio Interno Multiplicador de desvio para a banda interna que valida retrocessos.
Desvio Externo Multiplicador de desvio para a banda externa que detecta fugas.
Pontos Stop-Loss Distância de parada protetora em pontos (0 desabilita a parada).
Pontos de lucro Distância de take-profit em pontos (0 desativa o alvo).
Tipo de vela Prazo de vela para cálculos.

Notas

  • A estratégia negocia uma única posição de cada vez e ignora novos sinais enquanto as ordens estão ativas.
  • Para gerenciamento de risco, o auxiliar converte MetaTrader "pontos" em incrementos de preço reais com base no tamanho do tick do instrumento.
  • Os desenhos do gráfico incluem velas, bandas Bollinger e as próprias negociações da estratégia para facilitar a depuração visual.
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);
		}
	}
}