Ver en GitHub

Estrategia de Rebote en Canal Bollinger

Convertida del script de TradingView "strategy1". La estrategia opera rebotes en el canal Bollinger. Entra en largo después de que el precio cae por debajo de la banda inferior y luego cierra por encima de ella. Las salidas se activan al cruzar por encima de la banda media, tocar la banda superior o por stop-loss por debajo del canal.

Detalles

  • Criterios de entrada: El precio estaba por debajo de la banda inferior y luego cierra por encima de ella.
  • Largo/Corto: Solo largos.
  • Criterios de salida: Cruce por encima de la banda media, toque de la banda superior o stop-loss por debajo del canal.
  • Stops: Sí, stop fijo por debajo del canal.
  • Valores predeterminados:
    • Length = 20
    • BufferFactor = 0.2
    • CandleType = TimeSpan.FromMinutes(1)
  • Filtros:
    • Categoría: Reversión a la media
    • Dirección: Largo
    • Indicadores: Bollinger Bands
    • Stops: Sí
    • Complejidad: Básico
    • Marco temporal: Variable
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio
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>
/// Bollinger Channel Rebound strategy using EMA crossover.
/// </summary>
public class BollingerChannelReboundStrategy : Strategy
{
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

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

	public BollingerChannelReboundStrategy()
	{
		_slowLength = Param(nameof(SlowLength), 40)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "General");

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

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fast = new ExponentialMovingAverage { Length = 14 };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var prevF = 0m; var prevS = 0m; var init = false;
		var lastSignal = DateTimeOffset.MinValue;
		var cooldown = TimeSpan.FromMinutes(360);
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, (candle, f, s) =>
		{
			if (candle.State != CandleStates.Finished) return;
			if (!fast.IsFormed || !slow.IsFormed) return;
			if (!init) { prevF = f; prevS = s; init = true; return; }
			if (candle.OpenTime - lastSignal >= cooldown)
			{
				if (prevF <= prevS && f > s && Position <= 0) { BuyMarket(); lastSignal = candle.OpenTime; }
				else if (prevF >= prevS && f < s && Position >= 0) { SellMarket(); lastSignal = candle.OpenTime; }
			}
			prevF = f; prevS = s;
		}).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}
}