Estrategia SMC Trader Camel CCI MACD
Descripción general
Esta estrategia es una versión StockSharp del MetaTrader 4 asesor experto "Steve Cartwright Trader Camel CCI MACD".
Reproduce la lógica comercial original basada en un canal de media móvil exponencial estilo camello,
un filtro de tendencias MACD y umbrales del índice de canales de productos básicos (CCI). Las operaciones se ejecutan al finalizar
velas para garantizar un comportamiento determinista y mantenerse cerca del flujo de trabajo barra por barra de la versión MQL.
Lógica de trading
- Indicadores
- Se aplican dos medias móviles exponenciales (EMA) con el mismo período a los máximos y mínimos de las velas para formar el
canal de camellos. Una ruptura del cierre anterior más allá de estos límites indica fuerza del impulso.
- Se utiliza un indicador MACD estándar (EMA rápido, EMA lento y línea de señal) para confirmar la dirección de la tendencia subyacente.
- Un indicador CCI valida la fuerza del impulso utilizando niveles de sobrecompra/sobreventa en ±100 de forma predeterminada.
- Entradas largas
- El cierre de la vela anterior está por encima del máximo del camello EMA.
- El valor principal anterior MACD está por encima de cero y por encima de la línea de señal.
- El valor CCI anterior está por encima del umbral positivo.
- No hay ninguna posición activa abierta y no se produjo ninguna salida dentro del período de tiempo de la vela actual (evita un reingreso rápido).
- Entradas cortas
- El cierre de la vela anterior está por debajo del mínimo del camello EMA.
- El valor principal anterior MACD está por debajo de cero y por debajo de la línea de señal.
- El valor CCI anterior está por debajo del umbral negativo.
- Mismas condiciones de posición plana y enfriamiento que para configuraciones largas.
- Sale
- Las posiciones largas se cierran cuando el valor principal MACD anterior cruza por debajo de la línea de señal o cuando el valor principal CCI anterior
el valor cae por debajo del umbral positivo.
- Las posiciones cortas se cierran cuando el valor principal MACD anterior cruza por encima de la línea de señal.
- Después de cualquier salida, se aplica un tiempo de reutilización igual a la duración de una vela antes de nuevas entradas.
La estrategia se negocia una vez por barra como máximo porque cada decisión se basa en datos de la vela completada anteriormente.
Parámetros
| Parámetro |
Descripción |
Predeterminado |
CandleType |
Tipo de datos de vela/período de tiempo utilizado para todos los indicadores. |
plazo de 1 hora |
CamelLength |
Longitud del canal alto/bajo EMA. |
34 |
CciPeriod |
Longitud del filtro CCI. |
20 |
MacdFastPeriod |
Longitud rápida de EMA para MACD. |
12 |
MacdSlowPeriod |
Longitud lenta de EMA para MACD. |
26 |
MacdSignalPeriod |
Período de suavizado de señal para MACD. |
9 |
CciThreshold |
Nivel absoluto CCI que debe superarse para las entradas (aplicado simétricamente). |
100 |
Todos los parámetros son optimizables a través del optimizador StockSharp gracias a las llamadas SetOptimize.
Gestión del riesgo
- Las órdenes se envían a través de
BuyMarket y SellMarket, heredando la propiedad de estrategia Volume.
StartProtection() está habilitado para inicializar los asistentes de protección estándar StockSharp.
- En el algoritmo original no se define ningún stop-loss ni take-profit fijo; las salidas dependen únicamente de las señales de los indicadores.
Trazar
La estrategia traza automáticamente los indicadores del canal camel EMA, MACD y CCI, junto con sus propias operaciones.
que replica las señales visuales utilizadas en la implementación de MT4.
Notas
- El temporizador de enfriamiento utiliza la duración de la vela derivada de
CandleType.Arg. Asegúrese de que CandleType contenga un
TimeSpan argumento cuando cambia el período de tiempo.
- Debido a que todas las decisiones se basan en los valores de la barra anterior, el orden de las operaciones refleja
iMACD, iCCI
y iMA (con shift=1) llama en la fuente EA.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Strategy combining CCI and MACD signal crossover with EMA trend filter.
/// Buy when MACD crosses above signal with CCI positive and price above EMA.
/// Sell when MACD crosses below signal with CCI negative and price below EMA.
/// </summary>
public class SmcTraderCamelCciMacd1Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _macdFastPeriod;
private readonly StrategyParam<int> _macdSlowPeriod;
private readonly StrategyParam<int> _macdSignalPeriod;
private readonly StrategyParam<int> _cciPeriod;
private decimal? _prevMacdMain;
private decimal? _prevMacdSignal;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public int MacdFastPeriod { get => _macdFastPeriod.Value; set => _macdFastPeriod.Value = value; }
public int MacdSlowPeriod { get => _macdSlowPeriod.Value; set => _macdSlowPeriod.Value = value; }
public int MacdSignalPeriod { get => _macdSignalPeriod.Value; set => _macdSignalPeriod.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public SmcTraderCamelCciMacd1Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaLength = Param(nameof(EmaLength), 34)
.SetDisplay("EMA Length", "Trend EMA period", "Indicators");
_macdFastPeriod = Param(nameof(MacdFastPeriod), 12)
.SetDisplay("MACD Fast", "Fast EMA for MACD", "Indicators");
_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 26)
.SetDisplay("MACD Slow", "Slow EMA for MACD", "Indicators");
_macdSignalPeriod = Param(nameof(MacdSignalPeriod), 9)
.SetDisplay("MACD Signal", "Signal line period", "Indicators");
_cciPeriod = Param(nameof(CciPeriod), 20)
.SetDisplay("CCI Period", "CCI period", "Indicators");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevMacdMain = null;
_prevMacdSignal = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevMacdMain = null;
_prevMacdSignal = null;
var ema = new ExponentialMovingAverage { Length = EmaLength };
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd =
{
ShortMa = { Length = MacdFastPeriod },
LongMa = { Length = MacdSlowPeriod }
},
SignalMa = { Length = MacdSignalPeriod }
};
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(macd, cci, ema, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue, IIndicatorValue cciValue, IIndicatorValue emaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!macdValue.IsFinal || !cciValue.IsFinal || !emaValue.IsFinal)
return;
if (macdValue is not MovingAverageConvergenceDivergenceSignalValue macdData)
return;
if (macdData.Macd is not decimal macdMain || macdData.Signal is not decimal macdSignal)
return;
var cci = cciValue.ToDecimal();
var emaVal = emaValue.ToDecimal();
if (_prevMacdMain is not decimal prevMain || _prevMacdSignal is not decimal prevSignal)
{
_prevMacdMain = macdMain;
_prevMacdSignal = macdSignal;
return;
}
var macdBullCross = prevMain <= prevSignal && macdMain > macdSignal;
var macdBearCross = prevMain >= prevSignal && macdMain < macdSignal;
// Long: MACD bullish cross + CCI > 0 + price above EMA
if (Position <= 0 && macdBullCross && cci > 0 && candle.ClosePrice > emaVal)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Short: MACD bearish cross + CCI < 0 + price below EMA
else if (Position >= 0 && macdBearCross && cci < 0 && candle.ClosePrice < emaVal)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevMacdMain = macdMain;
_prevMacdSignal = macdSignal;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import (
CommodityChannelIndex,
ExponentialMovingAverage,
MovingAverageConvergenceDivergenceSignal
)
from StockSharp.Algo.Strategies import Strategy
class smc_trader_camel_cci_macd1_strategy(Strategy):
"""Strategy combining CCI and MACD signal crossover with EMA trend filter.
Buy when MACD crosses above signal with CCI positive and price above EMA.
Sell when MACD crosses below signal with CCI negative and price below EMA."""
def __init__(self):
super(smc_trader_camel_cci_macd1_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._ema_length = self.Param("EmaLength", 34) \
.SetDisplay("EMA Length", "Trend EMA period", "Indicators")
self._macd_fast_period = self.Param("MacdFastPeriod", 12) \
.SetDisplay("MACD Fast", "Fast EMA for MACD", "Indicators")
self._macd_slow_period = self.Param("MacdSlowPeriod", 26) \
.SetDisplay("MACD Slow", "Slow EMA for MACD", "Indicators")
self._macd_signal_period = self.Param("MacdSignalPeriod", 9) \
.SetDisplay("MACD Signal", "Signal line period", "Indicators")
self._cci_period = self.Param("CciPeriod", 20) \
.SetDisplay("CCI Period", "CCI period", "Indicators")
self._prev_macd_main = None
self._prev_macd_signal = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def MacdFastPeriod(self):
return self._macd_fast_period.Value
@property
def MacdSlowPeriod(self):
return self._macd_slow_period.Value
@property
def MacdSignalPeriod(self):
return self._macd_signal_period.Value
@property
def CciPeriod(self):
return self._cci_period.Value
def OnReseted(self):
super(smc_trader_camel_cci_macd1_strategy, self).OnReseted()
self._prev_macd_main = None
self._prev_macd_signal = None
def OnStarted2(self, time):
super(smc_trader_camel_cci_macd1_strategy, self).OnStarted2(time)
self._prev_macd_main = None
self._prev_macd_signal = None
ema = ExponentialMovingAverage()
ema.Length = self.EmaLength
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = self.MacdFastPeriod
macd.Macd.LongMa.Length = self.MacdSlowPeriod
macd.SignalMa.Length = self.MacdSignalPeriod
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(macd, cci, ema, self._process_candle).Start()
def _process_candle(self, candle, macd_value, cci_value, ema_value):
if candle.State != CandleStates.Finished:
return
if not macd_value.IsFinal or not cci_value.IsFinal or not ema_value.IsFinal:
return
macd_raw = macd_value.Macd if hasattr(macd_value, 'Macd') else None
signal_raw = macd_value.Signal if hasattr(macd_value, 'Signal') else None
if macd_raw is None or signal_raw is None:
return
macd_main = float(macd_raw)
macd_signal = float(signal_raw)
cci_val = float(cci_value)
ema_val = float(ema_value)
if self._prev_macd_main is None or self._prev_macd_signal is None:
self._prev_macd_main = macd_main
self._prev_macd_signal = macd_signal
return
prev_main = self._prev_macd_main
prev_signal = self._prev_macd_signal
macd_bull_cross = prev_main <= prev_signal and macd_main > macd_signal
macd_bear_cross = prev_main >= prev_signal and macd_main < macd_signal
close = float(candle.ClosePrice)
# Long: MACD bullish cross + CCI > 0 + price above EMA
if self.Position <= 0 and macd_bull_cross and cci_val > 0 and close > ema_val:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Short: MACD bearish cross + CCI < 0 + price below EMA
elif self.Position >= 0 and macd_bear_cross and cci_val < 0 and close < ema_val:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_macd_main = macd_main
self._prev_macd_signal = macd_signal
def CreateClone(self):
return smc_trader_camel_cci_macd1_strategy()