Ver en GitHub

Estrategia de Operación Automática con Bollinger Bands

Esta estrategia utiliza Bollinger Bands, RSI y el oscilador estocástico para abrir operaciones automáticamente durante una ventana de tiempo GMT especificada. Se abre una posición corta cuando la vela anterior cierra por encima de la banda superior de Bollinger Bands con el RSI por encima de 75 y el %K del estocástico por encima de 85. Se abre una posición larga cuando la vela cierra por debajo de la banda inferior con el RSI por debajo de 25 y el %K del estocástico por debajo de 155. Solo se permite una posición por dirección. Un trailing stop en puntos protege las posiciones abiertas.

Parámetros

  • OpenBuy – habilitar la apertura de posiciones largas.
  • OpenSell – habilitar la apertura de posiciones cortas.
  • GmtTradeStart – hora de inicio de trading en GMT (exclusiva).
  • GmtTradeStop – hora de fin de trading en GMT (exclusiva).
  • BbPeriod – período para Bollinger Bands.
  • RsiPeriod – período para el indicador RSI.
  • StochKPeriod – período %K para el oscilador estocástico.
  • StochDPeriod – período %D para el oscilador estocástico.
  • StochSlowing – factor de suavizado para el oscilador estocástico.
  • TrailingStop – distancia del trailing stop en puntos.
  • CandleType – marco temporal de velas utilizado para los cálculos.
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 Bands auto trade strategy with RSI confirmation.
/// Sells when price touches upper band and RSI is overbought.
/// Buys when price touches lower band and RSI is oversold.
/// </summary>
public class AutoTradeWithBollingerBandsStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _bbPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiOverbought;
	private readonly StrategyParam<decimal> _rsiOversold;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int BbPeriod
	{
		get => _bbPeriod.Value;
		set => _bbPeriod.Value = value;
	}

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public decimal RsiOverbought
	{
		get => _rsiOverbought.Value;
		set => _rsiOverbought.Value = value;
	}

	public decimal RsiOversold
	{
		get => _rsiOversold.Value;
		set => _rsiOversold.Value = value;
	}

	public AutoTradeWithBollingerBandsStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_bbPeriod = Param(nameof(BbPeriod), 20)
			.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 6)
			.SetDisplay("RSI Period", "RSI period", "Indicators");

		_rsiOverbought = Param(nameof(RsiOverbought), 70m)
			.SetDisplay("RSI Overbought", "RSI overbought level", "Indicators");

		_rsiOversold = Param(nameof(RsiOversold), 30m)
			.SetDisplay("RSI Oversold", "RSI oversold level", "Indicators");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var bollinger = new BollingerBands { Length = BbPeriod, Width = 2m };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(bollinger, rsi, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, bollinger);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue bbValue, IIndicatorValue rsiValue)
	{
		if (candle.State != CandleStates.Finished)
			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 rsi = rsiValue.ToDecimal();
		var price = candle.ClosePrice;

		// Sell when price above upper band and RSI overbought
		if (price > upper && rsi > RsiOverbought && Position >= 0)
		{
			SellMarket();
		}
		// Buy when price below lower band and RSI oversold
		else if (price < lower && rsi < RsiOversold && Position <= 0)
		{
			BuyMarket();
		}
		// Exit long when price returns to middle
		else if (Position > 0 && price >= middle)
		{
			SellMarket();
		}
		// Exit short when price returns to middle
		else if (Position < 0 && price <= middle)
		{
			BuyMarket();
		}
	}
}