Convierte el MetaTrader 4 asesor experto "Anubis" al StockSharp alto nivel API.
Utiliza un filtro de índice de canales de productos básicos (CCI) de 4 horas junto con un cruce de MACD de 15 minutos.
Aplica un tamaño de posición adaptable, stop-loss, protección de equilibrio, salidas impulsadas por ATR y una toma de ganancias basada en la desviación estándar.
Lógica estratégica
Datos
Periodo de tiempo principal: velas de 15 minutos (SignalCandleType), utilizadas para los cálculos MACD y ATR.
Plazo superior: velas de 4 horas (TrendCandleType), utilizadas para el filtrado CCI y la medición de la desviación estándar.
Indicadores
CommodityChannelIndex con periodo configurable en la serie 4H.
StandardDeviation (longitud 30) en 4H cierra para estimar la distancia de obtención de beneficios.
MovingAverageConvergenceDivergenceSignal (rápido/lento/señal configurable) en 15 millones de velas.
AverageTrueRange (longitud 12) en velas de 15 millones para salidas basadas en volatilidad.
Inscripciones
Corto: cuando 4H CCI está por encima de CciThreshold, los dos valores anteriores de MACD muestran un cruce bajista (MACD cruza por debajo de su señal), MACD fue positivo, no hay posiciones largas abiertas y el precio se ha movido al menos PriceFilterPoints desde la última entrada corta.
Largo: condición simétrica con CCI debajo de -CciThreshold, MACD cruzando hacia arriba mientras es negativo, sin cortos abiertos y con el filtro de distancia mínima satisfecho.
Gestión de riesgos
El volumen base se define por VolumeValue y se escala según el capital de la cuenta (2× por encima de 14k, 3,2× por encima de 22k) y por LossFactor después de una operación perdedora.
Las operaciones simultáneas máximas por dirección están limitadas por MaxLongTrades y MaxShortTrades.
Stop-loss duro colocado prácticamente a StopLossPoints * PriceStep del precio medio de entrada.
El punto de equilibrio se activa una vez que el precio avanza BreakevenPoints y cierra inmediatamente la posición si el precio vuelve a la entrada.
Sale
La toma de ganancias con desviación estándar cierra la posición una vez que el precio se mueve StdDevMultiplier * StdDev a favor.
Las salidas agresivas se activan cuando el rango de la vela anterior excede CloseAtrMultiplier * ATR.
Las salidas de desaceleración de MACD requieren tanto una ganancia suficiente (ProfitThresholdPoints) como una reversión en la pendiente MACD (} anterior menor o mayor que hace dos barras, dependiendo de la dirección).
El stop de protección cierra la operación si el precio supera la distancia del stop-loss o vuelve a caer hasta la entrada después de la activación del punto de equilibrio.
Parámetros
Nombre
Descripción
VolumeValue
Volumen base de pedidos.
CciThreshold
Umbral absoluto para el filtro 4H CCI.
CciPeriod
Período del indicador 4H CCI.
StopLossPoints
Distancia de stop-loss en puntos.
BreakevenPoints
Ganancia en puntos necesarios para armar el punto de equilibrio.
MacdFastPeriod
Período rápido de EMA para MACD.
MacdSlowPeriod
Período lento de EMA durante MACD.
MacdSignalPeriod
Periodo de señal EMA durante MACD.
LossFactor
Multiplicador de volumen aplicado después de una operación perdedora.
MaxShortTrades
Número máximo de entradas cortas simultáneas.
MaxLongTrades
Número máximo de entradas largas simultáneas.
CloseAtrMultiplier
multiplicador ATR para salidas anticipadas.
ProfitThresholdPoints
Búfer de ganancias adicional (puntos) antes de que salga MACD.
StdDevMultiplier
Multiplicador de desviación estándar para la toma de ganancias.
PriceFilterPoints
Movimiento mínimo del precio entre entradas consecutivas.
SignalCandleType
Periodo de tiempo principal para MACD y ATR.
TrendCandleType
Plazo mayor para CCI y desviación estándar.
Notas
La estrategia se basa en metadatos Security.PriceStep válidos para traducir parámetros basados en puntos en distancias de precios.
La lógica de protección se implementa mediante controles explícitos en lugar de órdenes de límite/detención pendientes, lo que refleja el comportamiento original de EA con paradas virtuales.
La versión de Python se omite intencionalmente según las instrucciones de la tarea.
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>
/// Anubis CCI + MACD strategy.
/// Buys when CCI crosses above 0 and MACD histogram is positive.
/// Sells when CCI crosses below 0 and MACD histogram is negative.
/// </summary>
public class AnubisCciMacdStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevCci;
private bool _hasPrev;
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public AnubisCciMacdStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetDisplay("CCI Period", "CCI lookback period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCci = 0m;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var macd = new MovingAverageConvergenceDivergenceSignal();
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(cci, macd, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue cciValue, IIndicatorValue macdValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!cciValue.IsFinal || !macdValue.IsFinal)
return;
var cci = cciValue.ToDecimal();
var macdVal = (MovingAverageConvergenceDivergenceSignalValue)macdValue;
if (macdVal.Macd is not decimal macd || macdVal.Signal is not decimal signal)
return;
var histogram = macd - signal;
if (!_hasPrev)
{
_prevCci = cci;
_hasPrev = true;
return;
}
// CCI crosses above 0 with bullish MACD
if (_prevCci <= 0 && cci > 0 && histogram > 0 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// CCI crosses below 0 with bearish MACD
else if (_prevCci >= 0 && cci < 0 && histogram < 0 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevCci = cci;
}
}
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, MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
class anubis_cci_macd_strategy(Strategy):
"""Anubis CCI + MACD strategy.
Buys when CCI crosses above 0 and MACD histogram is positive.
Sells when CCI crosses below 0 and MACD histogram is negative."""
def __init__(self):
super(anubis_cci_macd_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 14) \
.SetDisplay("CCI Period", "CCI lookback period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_cci = 0.0
self._has_prev = False
@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
def OnReseted(self):
super(anubis_cci_macd_strategy, self).OnReseted()
self._prev_cci = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(anubis_cci_macd_strategy, self).OnStarted2(time)
self._has_prev = False
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
macd = MovingAverageConvergenceDivergenceSignal()
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(cci, macd, self._process_candle).Start()
def _process_candle(self, candle, cci_value, macd_value):
if candle.State != CandleStates.Finished:
return
if not cci_value.IsFinal or not macd_value.IsFinal:
return
cci = float(cci_value)
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
histogram = float(macd_raw) - float(signal_raw)
if not self._has_prev:
self._prev_cci = cci
self._has_prev = True
return
# CCI crosses above 0 with bullish MACD
if self._prev_cci <= 0 and cci > 0 and histogram > 0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# CCI crosses below 0 with bearish MACD
elif self._prev_cci >= 0 and cci < 0 and histogram < 0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_cci = cci
def CreateClone(self):
return anubis_cci_macd_strategy()