Ver no GitHub

Estratégia Godbot

Esta estratégia opera usando Bandas de Bollinger combinadas com médias móveis para detectar reversões e força de tendência.

Lógica

  • Funciona em um período de velas principal (padrão 30 minutos).
  • Calcula as Bandas de Bollinger e uma EMA neste período.
  • Separadamente, calcula uma DEMA em um período superior (padrão 1 dia) para determinar a tendência global.
  • Fecha posições compradas quando o preço volta a cair abaixo da banda superior de Bollinger.
  • Fecha posições vendidas quando o preço sobe novamente acima da banda inferior de Bollinger.
  • Abre comprado quando o preço cruza acima da banda inferior enquanto tanto DEMA quanto EMA estão subindo.
  • Abre vendido quando o preço cruza abaixo da banda superior enquanto tanto DEMA quanto EMA estão caindo.

Parâmetros

  • Bollinger Period – período das Bandas de Bollinger.
  • Bollinger Deviation – multiplicador de largura para as bandas.
  • EMA Period – período para o filtro de tendência EMA.
  • DEMA Period – período para a DEMA no período superior.
  • Candle Type – período usado para cálculos de Bandas de Bollinger e EMA.
  • DEMA Candle Type – período superior usado para a DEMA.

Notas

  • Apenas uma posição é mantida de cada vez.
  • A estratégia usa ordens de mercado para entradas e saídas.
  • Os dados de DEMA devem se acumular antes que a negociação comece.
using System;
using System.Collections.Generic;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on Bollinger Bands and EMA trend confirmation.
/// Buys when price crosses below lower band with uptrend, sells when above upper band with downtrend.
/// </summary>
public class GodbotStrategy : Strategy
{
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevEma;
	private bool _hasPrevEma;

	public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
	public decimal BollingerDeviation { get => _bollingerDeviation.Value; set => _bollingerDeviation.Value = value; }
	public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public GodbotStrategy()
	{
		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetGreaterThanZero()
			.SetDisplay("BB Deviation", "Bollinger Bands deviation", "Indicators");

		_maPeriod = Param(nameof(MaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period for trend", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevEma = 0;
		_hasPrevEma = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var bb = new BollingerBands
		{
			Length = BollingerPeriod,
			Width = BollingerDeviation
		};
		var ema = new ExponentialMovingAverage { Length = MaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, ProcessEma);
		subscription
			.BindEx(bb, ProcessBB)
			.Start();
	}

	private void ProcessEma(ICandleMessage candle, decimal emaVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		_prevEma = emaVal;
		_hasPrevEma = true;
	}

	private void ProcessBB(ICandleMessage candle, IIndicatorValue bbValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_hasPrevEma)
			return;

		var bb = (BollingerBandsValue)bbValue;
		if (bb.UpBand is not decimal upper || bb.LowBand is not decimal lower || bb.MovingAverage is not decimal middle)
			return;

		var close = candle.ClosePrice;

		// Buy: price below lower band
		if (close < lower && Position <= 0)
			BuyMarket();
		// Sell: price above upper band
		else if (close > upper && Position >= 0)
			SellMarket();
	}
}