Ver en GitHub

Estrategia de Canal BrakeExp

Esta estrategia opera basándose en el indicador BrakeExp, que construye un canal exponencial alrededor de los movimientos del precio. El indicador alterna entre regímenes largo y corto y genera señales de compra o venta cuando el precio cruza los bordes dinámicos del canal.

Cómo funciona

  • El indicador mantiene una curva exponencial que sigue al precio.
  • Cuando la curva está por debajo del precio (tendencia alcista), la estrategia busca señales de compra.
  • Cuando la curva está por encima del precio (tendencia bajista), la estrategia busca señales de venta.
  • Un cruce de un lado al otro genera una señal de entrada en la nueva dirección y cierra la posición opuesta.

Parámetros

  • Candle Type – período temporal de las velas procesadas.
  • Volume – volumen de la orden para entradas de mercado.
  • A, B – parámetros que definen la forma de la curva BrakeExp.
  • Buy Open / Sell Open – permiso para abrir posiciones largas o cortas.
  • Buy Close / Sell Close – permiso para cerrar posiciones cortas o largas.

Notas

Esta implementación se centra en la lógica principal del indicador BrakeExp y no incluye gestión de stop-loss o take-profit. Se pueden añadir controles de riesgo adicionales si es necesario.

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>
/// Channel breakout strategy using EMA and price crossover.
/// </summary>
public class BrakeExpChannelStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;

	private decimal _prevClose;
	private decimal _prevEma;
	private bool _hasPrev;

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

	public BrakeExpChannelStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period", "Indicators");
	}

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

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

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

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		SubscribeCandles(CandleType)
			.Bind(ema, ProcessCandle)
			.Start();
	}

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevClose = close;
			_prevEma = emaVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevClose <= _prevEma && close > emaVal;
		var crossDown = _prevClose >= _prevEma && close < emaVal;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevClose = close;
		_prevEma = emaVal;
	}
}