Ver no GitHub

Estratégia de exaustão de envelope Firebird MA

A estratégia replica o especialista em reversão de envelope Firebird v0.60. Ele mede uma média móvel simples e a compensa em uma porcentagem para formar os envelopes superior e inferior. Quando o preço ultrapassa a faixa superior a estratégia vende, e quando a faixa inferior rompe ela compra. As posições adicionais são calculadas em média apenas se o preço se mover pelo menos um passo configurável de pip além da entrada anterior. O stop loss total é compartilhado entre todas as entradas, evitando que tendências descontroladas entrem repetidamente na mesma direção.

Detalhes

  • Critérios de entrada:
    • Calcule um SMA na abertura da vela ou no ponto médio alto/baixo.
    • Envelope superior = SMA × (1 + Porcentagem/100); envelope inferior = SMA × (1 − Porcentagem/100).
    • Entre em posição curta em um fechamento acima da banda superior (a menos que uma parada recente bloqueie as posições vendidas), entre em posição comprada em um fechamento abaixo da banda inferior (a menos que as posições compradas estejam bloqueadas).
    • As negociações de média são permitidas quando o preço se move PipStep pips (opcionalmente escalonado por potência) além do preenchimento mais recente.
  • Longo/Curto: Longo e curto.
  • Critérios de saída:
    • Take Profit compartilhado ao preço médio de entrada ± TakeProfit pips.
    • Stop loss compartilhado ao preço médio de entrada ∓ StopLoss / position count pips.
    • A bandeira de bloqueio impede a reentrada na mesma direção até que um sinal oposto seja acionado após uma parada.
  • Stops: Sim, stop loss e takeprofit agregados.
  • Valores padrão:
    • MaLength = 10
    • Percent = 0,3
    • TradeOnFriday = verdadeiro
    • UseHighLow = falso (use aberturas)
    • PipStep = 30
    • IncreasementPower = 0
    • TakeProfit = 30
    • StopLoss = 200
    • TradeVolume = 1
  • Filtros:
    • Categoria: Reversão à média
    • Direção: Ambos
    • Indicadores: SMA envelopes
    • Paradas: Sim
    • Complexidade: Média
    • Prazo: Qualquer
    • Sazonalidade: filtro opcional de sexta-feira
    • Redes neurais: Não
    • Divergência: Não
    • Nível de risco: Alto devido à média
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>
/// Firebird MA Envelope Exhaustion strategy - Bollinger Bands mean reversion.
/// Buys when close drops below lower band (exhaustion).
/// Sells when close rises above upper band (exhaustion).
/// Exits at the middle band.
/// </summary>
public class FirebirdMaEnvelopeExhaustionStrategy : Strategy
{
	private readonly StrategyParam<int> _bbPeriod;
	private readonly StrategyParam<decimal> _bbWidth;
	private readonly StrategyParam<DataType> _candleType;

	public int BbPeriod { get => _bbPeriod.Value; set => _bbPeriod.Value = value; }
	public decimal BbWidth { get => _bbWidth.Value; set => _bbWidth.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public FirebirdMaEnvelopeExhaustionStrategy()
	{
		_bbPeriod = Param(nameof(BbPeriod), 10)
			.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");

		_bbWidth = Param(nameof(BbWidth), 2m)
			.SetDisplay("BB Width", "Bollinger Bands width", "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 = BbPeriod, Width = BbWidth };

		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 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;

		// Close below lower band = exhaustion, buy
		if (close < lower.Value && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Close above upper band = exhaustion, sell
		else if (close > upper.Value && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}