Esta estrategia StockSharp transfiere el asesor experto MetaTrader 5 Expert_ABE_BE_CCI (carpeta MQL/306). El EA original combina patrones de velas envolventes alcistas/bajistas con un módulo de confirmación del índice de canales de productos básicos (CCI) y gestión de dinero de lote fijo. La implementación de C# mantiene la misma lógica de decisión y al mismo tiempo aprovecha la suscripción de alto nivel y los enlaces de indicadores proporcionados por StockSharp.
El motor observa las velas completadas en el período de tiempo seleccionado, calcula un promedio móvil de cuerpos de velas, un promedio de precios de cierre y un CCI con período configurable. Los patrones envolventes alcistas o bajistas solo se aceptan cuando los cuerpos de las velas exceden el promedio reciente y el punto medio de la vela envuelta está en el lado correcto del promedio móvil, imitando las comprobaciones MQL CCandlePattern. Las operaciones largas requieren una envoltura alcista más CCI por debajo del umbral de sobreventa, mientras que las operaciones cortas requieren la condición de espejo con CCI por encima del umbral de sobrecompra. Las salidas de posición reflejan la lógica de "voto" EA: CCI cruces de ±ExitLevel neutralizan las posiciones abiertas independientemente de la dirección.
Flujo de trabajo
Suscríbete al tipo de vela configurado y calcula:
Promedio del cuerpo de la vela en BodyAveragePeriod barras.
Media móvil de precios de cierre en la misma ventana.
Índice de canales de productos básicos con longitud CciPeriod.
Por cada vela terminada:
Verifique que la vela anterior forme una barra envuelta de colores opuestos.
Comprobar que el cuerpo envolvente sea mayor que el promedio del cuerpo rodante y cierre más allá de la apertura anterior, replicando los filtros MQL.
Confirme el contexto de la tendencia comparando el punto medio de la vela anterior con el promedio móvil del precio de cierre.
Confirme el impulso con CCI frente a EntryOversoldLevel o EntryOverboughtLevel.
Gestionar operaciones:
Si las condiciones alcistas se alinean y no hay ninguna posición larga activa, cierre los cortos y compre el volumen configurado.
Si las condiciones bajistas se alinean y no hay posiciones cortas activas, cierre posiciones largas y venda el volumen configurado.
Supervise CCI para detectar salidas: cualquier cruce por debajo de +ExitLevel o a través de -ExitLevel cierra posiciones largas, mientras que los cruces por encima de -ExitLevel o por debajo de +ExitLevel cierra posiciones cortas, coincidiendo con la lógica de "voto" de 40 puntos de EA.
Parámetros predeterminados
Nombre
Predeterminado
Descripción
CciPeriod
49
Longitud del indicador del índice del canal de productos básicos.
BodyAveragePeriod
11
Ventana para promediar el tamaño del cuerpo de la vela y el precio medio de cierre.
EntryOversoldLevel
-50
CCI umbral que confirma configuraciones envolventes alcistas.
EntryOverboughtLevel
50
CCI umbral que confirma configuraciones envolventes bajistas.
ExitLevel
80
Nivel absoluto CCI que desencadena salidas de posición cuando se cruza.
CandleType
1 hora
Plazo utilizado para la suscripción de velas.
Notas
El manejo de volúmenes refleja las conversiones típicas de StockSharp: Volume define el tamaño base del pedido; Las posiciones opuestas se aplanan antes de invertir.
Los componentes de seguimiento y administración de dinero (TrailingNone, MoneyFixedLot) del paquete MQL no se vuelven a crear; El tamaño del pedido de StockSharp ya cubre el comportamiento de lote fijo.
Todos los comentarios dentro del código están en inglés, las tabulaciones se utilizan para la sangría y no se recuperan valores de indicadores a través de GetValue, siguiendo las pautas del repositorio.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// ABE BE CCI strategy: Engulfing pattern with CCI confirmation.
/// Bullish engulfing + negative CCI for long, bearish engulfing + positive CCI for short.
/// </summary>
public class AbeBeCciStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _entryLevel;
private readonly StrategyParam<int> _signalCooldownCandles;
private readonly List<ICandleMessage> _candles = new();
private decimal _prevCci;
private bool _hasPrevCci;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public decimal EntryLevel { get => _entryLevel.Value; set => _entryLevel.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public AbeBeCciStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
_entryLevel = Param(nameof(EntryLevel), 100m)
.SetDisplay("Entry Level", "CCI threshold for entry", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candles.Clear();
_prevCci = 0m;
_hasPrevCci = false;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candles.Clear();
_hasPrevCci = false;
_candlesSinceTrade = SignalCooldownCandles;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
_candles.Add(candle);
if (_candles.Count > 5)
_candles.RemoveAt(0);
if (_candles.Count >= 2)
{
var curr = _candles[^1];
var prev = _candles[^2];
var bullishEngulfing = prev.OpenPrice > prev.ClosePrice
&& curr.ClosePrice > curr.OpenPrice
&& curr.OpenPrice <= prev.ClosePrice
&& curr.ClosePrice >= prev.OpenPrice;
var bearishEngulfing = prev.ClosePrice > prev.OpenPrice
&& curr.OpenPrice > curr.ClosePrice
&& curr.OpenPrice >= prev.ClosePrice
&& curr.ClosePrice <= prev.OpenPrice;
if (bullishEngulfing && cciValue < -EntryLevel && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (bearishEngulfing && cciValue > EntryLevel && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
if (_hasPrevCci)
{
if (Position > 0 && _prevCci > EntryLevel && cciValue < EntryLevel && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
else if (Position < 0 && _prevCci < -EntryLevel && cciValue > -EntryLevel && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
}
_prevCci = cciValue;
_hasPrevCci = true;
}
}
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 CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class abe_be_cci_strategy(Strategy):
def __init__(self):
super(abe_be_cci_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._cci_period = self.Param("CciPeriod", 14)
self._entry_level = self.Param("EntryLevel", 100.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._candles = []
self._prev_cci = 0.0
self._has_prev_cci = False
self._candles_since_trade = 6
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def CciPeriod(self):
return self._cci_period.Value
@CciPeriod.setter
def CciPeriod(self, value):
self._cci_period.Value = value
@property
def EntryLevel(self):
return self._entry_level.Value
@EntryLevel.setter
def EntryLevel(self, value):
self._entry_level.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(abe_be_cci_strategy, self).OnReseted()
self._candles.clear()
self._prev_cci = 0.0
self._has_prev_cci = False
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(abe_be_cci_strategy, self).OnStarted2(time)
self._candles.clear()
self._has_prev_cci = False
self._candles_since_trade = self.SignalCooldownCandles
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(cci, self._process_candle).Start()
def _process_candle(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
cci_val = float(cci_value)
self._candles.append(candle)
if len(self._candles) > 5:
self._candles.pop(0)
if len(self._candles) >= 2:
curr = self._candles[-1]
prev = self._candles[-2]
bullish_engulfing = (float(prev.OpenPrice) > float(prev.ClosePrice)
and float(curr.ClosePrice) > float(curr.OpenPrice)
and float(curr.OpenPrice) <= float(prev.ClosePrice)
and float(curr.ClosePrice) >= float(prev.OpenPrice))
bearish_engulfing = (float(prev.ClosePrice) > float(prev.OpenPrice)
and float(curr.OpenPrice) > float(curr.ClosePrice)
and float(curr.OpenPrice) >= float(prev.ClosePrice)
and float(curr.ClosePrice) <= float(prev.OpenPrice))
if bullish_engulfing and cci_val < -self.EntryLevel and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif bearish_engulfing and cci_val > self.EntryLevel and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
if self._has_prev_cci:
if self.Position > 0 and self._prev_cci > self.EntryLevel and cci_val < self.EntryLevel and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
elif self.Position < 0 and self._prev_cci < -self.EntryLevel and cci_val > -self.EntryLevel and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
self._prev_cci = cci_val
self._has_prev_cci = True
def CreateClone(self):
return abe_be_cci_strategy()