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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class brake_exp_channel_strategy(Strategy):
def __init__(self):
super(brake_exp_channel_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "EMA period", "Indicators")
self._prev_close = 0.0
self._prev_ema = 0.0
self._has_prev = False
@property
def candle_type(self):
return self._candle_type.Value
@property
def ema_period(self):
return self._ema_period.Value
def OnReseted(self):
super(brake_exp_channel_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_ema = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(brake_exp_channel_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
self.SubscribeCandles(self.candle_type).Bind(ema, self.process_candle).Start()
def process_candle(self, candle, ema_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
ev = float(ema_val)
if not self._has_prev:
self._prev_close = close
self._prev_ema = ev
self._has_prev = True
return
cross_up = self._prev_close <= self._prev_ema and close > ev
cross_down = self._prev_close >= self._prev_ema and close < ev
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_ema = ev
def CreateClone(self):
return brake_exp_channel_strategy()