La estrategia MA2CCI incorpora el clásico asesor experto MetaTrader creado en torno a la interacción de dos promedios móviles simples (SMA) y el índice del canal de productos básicos (CCI). Filtra operaciones utilizando la línea cero CCI y aplica paradas protectoras derivadas del rango verdadero promedio (ATR). El sistema está diseñado para entradas que siguen tendencias con una rápida reacción a las reversiones.
La versión StockSharp mantiene la lógica comercial original al tiempo que adapta la gestión de riesgos al entorno .NET. El tamaño de la posición sigue una regla de riesgo por mil con un factor de disminución adicional que reduce el tamaño de la operación después de pérdidas consecutivas. Cada entrada adjunta una parada impulsada por la volatilidad que refleja la distancia ATR utilizada en la implementación MQL.
Lógica de trading
Indicadores
Rápido SMA con longitud predeterminada 4.
Lento SMA con longitud predeterminada 8.
Filtro CCI usando retrospectiva de 4 períodos.
ATR con periodo 4 para colocación de parada.
Condiciones de entrada
Largo: el SMA rápido cruza por encima del SMA lento y la barra terminada anterior muestra CCI subiendo hasta cero (de negativo a positivo).
Corto: el SMA rápido cruza por debajo del SMA lento y la barra anterior muestra el CCI cayendo por cero (de positivo a negativo).
Condiciones de salida
El cruce opuesto SMA cierra posiciones abiertas incluso si no se inicia ninguna nueva operación.
parada ATR: las posiciones largas salen cuando el precio cae a entry - ATR; las posiciones cortas salen cuando el precio sube a entry + ATR.
Gestión del riesgo
El volumen de pedido base es configurable; por defecto 0,1 lotes (o equivalente en intercambio).
El tamaño dinámico opcional escala el volumen a free capital * MaxRiskPerThousand / 1000 cuando los datos de la cartera están disponibles.
Después de más de una pérdida consecutiva, el tamaño de la posición se reduce linealmente en losses / DecreaseFactor del volumen calculado.
Las paradas de volatilidad dependen de la vela terminada más reciente; Los picos intrabar más allá de los niveles de parada desencadenan una salida del mercado en el siguiente tick de la estrategia.
Parámetros
Nombre
Descripción
Predeterminado
CandleType
Plazo de trabajo para todos los indicadores.
velas de 1 hora
OrderVolume
Tamaño mínimo de operación cuando el tamaño basado en el riesgo no está disponible.
0.1
FastMaPeriod
Período del ayuno SMA.
4
SlowMaPeriod
Periodo de la lentitud SMA.
8
CciPeriod
Periodo del filtro CCI.
4
AtrPeriod
ATR longitud para el cálculo de parada.
4
MaxRiskPerThousand
Fracción de capital libre asignada por operación (por 1000 unidades).
0,02
DecreaseFactor
El divisor solía reducir el volumen después de rachas perdedoras.
3
Notas
La estrategia solo procesa velas terminadas, lo que garantiza una decisión por barra similar a la EA original que usaba Volume[0] > 1 como puerta.
Los niveles de parada se simulan internamente en lugar de registrar órdenes de parada de cambio; esto coincide con el comportamiento de la versión MetaTrader que dependía de los cierres del mercado cuando se alcanzaban los umbrales ATR.
Habilite los gráficos dentro de StockSharp Designer para visualizar SMA, CCI y las operaciones ejecutadas utilizando los asistentes de dibujo integrados.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// MA2CCI Classic strategy - dual SMA crossover with CCI zero-line filter.
/// Buys when fast SMA crosses above slow SMA and CCI above zero.
/// Sells when fast SMA crosses below slow SMA and CCI below zero.
/// </summary>
public class Ma2CciClassicStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Ma2CciClassicStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetDisplay("CCI Period", "CCI lookback", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal cci)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_prevFast <= _prevSlow && fast > slow && cci > 0 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (_prevFast >= _prevSlow && fast < slow && cci < 0 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevFast = fast; _prevSlow = slow;
}
}
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 SimpleMovingAverage, CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class ma2_cci_classic_strategy(Strategy):
def __init__(self):
super(ma2_cci_classic_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 12).SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 26).SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._cci_period = self.Param("CciPeriod", 14).SetDisplay("CCI Period", "CCI lookback", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
@property
def fast_period(self): return self._fast_period.Value
@property
def slow_period(self): return self._slow_period.Value
@property
def cci_period(self): return self._cci_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(ma2_cci_classic_strategy, self).OnReseted()
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
def OnStarted2(self, time):
super(ma2_cci_classic_strategy, self).OnStarted2(time)
self._has_prev = False
fast = SimpleMovingAverage(); fast.Length = self.fast_period
slow = SimpleMovingAverage(); slow.Length = self.slow_period
cci = CommodityChannelIndex(); cci.Length = self.cci_period
sub = self.SubscribeCandles(self.candle_type)
sub.Bind(fast, slow, cci, self.process_candle).Start()
def process_candle(self, candle, fast, slow, cci):
if candle.State != CandleStates.Finished: return
f = float(fast); s = float(slow); c = float(cci)
if not self._has_prev: self._prev_fast = f; self._prev_slow = s; self._has_prev = True; return
if self._prev_fast <= self._prev_slow and f > s and c > 0 and self.Position <= 0:
if self.Position < 0: self.BuyMarket()
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and f < s and c < 0 and self.Position >= 0:
if self.Position > 0: self.SellMarket()
self.SellMarket()
self._prev_fast = f; self._prev_slow = s
def CreateClone(self): return ma2_cci_classic_strategy()