Ver en GitHub

Estrategia CyberiaTrader

Esta estrategia es un port simplificado de StockSharp del sistema original CyberiaTrader.mq5. Combina varios indicadores técnicos clásicos para evaluar la dirección del mercado y abrir operaciones cuando la mayoría de los filtros coinciden.

Indicadores

  • MACD – Detecta cambios de momentum usando EMAs rápidas/lentas y una línea de señal.
  • Media Móvil Simple – Determina la tendencia predominante.
  • Commodity Channel Index – Filtra condiciones de sobrecompra/sobreventa.
  • Average Directional Index – Confirma la fuerza direccional mediante los componentes +DI y -DI.

Parámetros

Nombre Descripción
MacdFast Período de EMA rápida para MACD.
MacdSlow Período de EMA lenta para MACD.
MacdSignal Período de la línea de señal para MACD.
MaPeriod Longitud del filtro de tendencia de media móvil.
CciPeriod Período del Commodity Channel Index.
AdxPeriod Período del Average Directional Index.
EnableMacd Activar/desactivar el filtro MACD.
EnableMa Activar/desactivar el filtro de media móvil.
EnableCci Activar/desactivar el filtro CCI.
EnableAdx Activar/desactivar el filtro ADX.
CandleType Marco temporal de las velas de entrada.

Lógica de trading

  1. Los valores de todos los indicadores activados se calculan en cada vela completada.
  2. Los filtros pueden bloquear compras o ventas según sus respectivas reglas:
    • MACD por encima de su señal bloquea entradas cortas; por debajo bloquea largas.
    • Precio por encima de la media móvil bloquea cortos; por debajo bloquea largos.
    • CCI por encima de +100 bloquea largos; por debajo de -100 bloquea cortos.
    • +DI mayor que -DI bloquea cortos; -DI mayor que +DI bloquea largos.
  3. Una operación se abre solo si un lado está permitido y el opuesto está bloqueado.
  4. La protección básica de posición utiliza un take-profit del 2% y un stop-loss del 1%.

Notas

Esta traducción se centra en los filtros direccionales principales del algoritmo original. El extenso análisis de probabilidad y los módulos auxiliares de la versión MQL5 se omiten intencionalmente para mayor claridad.

using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

using StockSharp.Algo;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Simplified conversion of the CyberiaTrader MQL5 strategy.
/// Combines MACD, MA, CCI, and ADX filters to determine market direction.
/// </summary>
public class CyberiaTraderStrategy : Strategy
{
	private readonly StrategyParam<int> _macdFast;
	private readonly StrategyParam<int> _macdSlow;
	private readonly StrategyParam<int> _macdSignal;
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<int> _adxPeriod;
	private readonly StrategyParam<bool> _enableMacd;
	private readonly StrategyParam<bool> _enableMa;
	private readonly StrategyParam<bool> _enableCci;
	private readonly StrategyParam<bool> _enableAdx;
	private readonly StrategyParam<DataType> _candleType;
	
	private MovingAverageConvergenceDivergenceSignal _macd;
	private SimpleMovingAverage _ma;
	private CommodityChannelIndex _cci;
	private AverageDirectionalIndex _adx;
	private int _lastDirection;
	
	/// <summary>
	/// MACD fast EMA period.
	/// </summary>
	public int MacdFast { get => _macdFast.Value; set => _macdFast.Value = value; }
	
	/// <summary>
	/// MACD slow EMA period.
	/// </summary>
	public int MacdSlow { get => _macdSlow.Value; set => _macdSlow.Value = value; }
	
	/// <summary>
	/// MACD signal line period.
	/// </summary>
	public int MacdSignal { get => _macdSignal.Value; set => _macdSignal.Value = value; }
	
	/// <summary>
	/// Moving average length.
	/// </summary>
	public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
	
	/// <summary>
	/// Commodity Channel Index length.
	/// </summary>
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	
	/// <summary>
	/// ADX calculation length.
	/// </summary>
	public int AdxPeriod { get => _adxPeriod.Value; set => _adxPeriod.Value = value; }
	
	/// <summary>
	/// Enable MACD filter.
	/// </summary>
	public bool EnableMacd { get => _enableMacd.Value; set => _enableMacd.Value = value; }
	
	/// <summary>
	/// Enable moving average filter.
	/// </summary>
	public bool EnableMa { get => _enableMa.Value; set => _enableMa.Value = value; }
	
	/// <summary>
	/// Enable CCI filter.
	/// </summary>
	public bool EnableCci { get => _enableCci.Value; set => _enableCci.Value = value; }
	
	/// <summary>
	/// Enable ADX filter.
	/// </summary>
	public bool EnableAdx { get => _enableAdx.Value; set => _enableAdx.Value = value; }
	
	/// <summary>
	/// Candle type used by the strategy.
	/// </summary>
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	
	/// <summary>
	/// Initializes a new instance of <see cref="CyberiaTraderStrategy"/>.
	/// </summary>
	public CyberiaTraderStrategy()
	{
		_macdFast = Param(nameof(MacdFast), 12)
		.SetGreaterThanZero()
		.SetDisplay("MACD Fast Period", "Fast EMA period for MACD", "Indicators");
		
		_macdSlow = Param(nameof(MacdSlow), 26)
		.SetGreaterThanZero()
		.SetDisplay("MACD Slow Period", "Slow EMA period for MACD", "Indicators");
		
		_macdSignal = Param(nameof(MacdSignal), 9)
		.SetGreaterThanZero()
		.SetDisplay("MACD Signal Period", "Signal MA period for MACD", "Indicators");
		
		_maPeriod = Param(nameof(MaPeriod), 20)
		.SetGreaterThanZero()
		.SetDisplay("MA Period", "Length of moving average", "Indicators");
		
		_cciPeriod = Param(nameof(CciPeriod), 14)
		.SetGreaterThanZero()
		.SetDisplay("CCI Period", "Length of CCI", "Indicators");
		
		_adxPeriod = Param(nameof(AdxPeriod), 14)
		.SetGreaterThanZero()
		.SetDisplay("ADX Period", "Length of ADX", "Indicators");
		
		_enableMacd = Param(nameof(EnableMacd), true)
		.SetDisplay("Enable MACD", "Use MACD direction filter", "Logic");
		
		_enableMa = Param(nameof(EnableMa), true)
		.SetDisplay("Enable MA", "Use moving average trend filter", "Logic");
		
		_enableCci = Param(nameof(EnableCci), true)
		.SetDisplay("Enable CCI", "Use CCI overbought/oversold filter", "Logic");
		
		_enableAdx = Param(nameof(EnableAdx), true)
		.SetDisplay("Enable ADX", "Use ADX directional filter", "Logic");
		
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
		.SetDisplay("Candle Type", "Timeframe for strategy", "General");
		
		Volume = 1;
	}
	
	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_lastDirection = 0;
	}
	
	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_lastDirection = 0;
		
		_macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = MacdFast },
				LongMa = { Length = MacdSlow },
			},
			SignalMa = { Length = MacdSignal }
		};
		
		_ma = new SMA { Length = MaPeriod };
		_cci = new CommodityChannelIndex { Length = CciPeriod };
		_adx = new AverageDirectionalIndex { Length = AdxPeriod };
		
		var subscription = SubscribeCandles(CandleType);
		subscription
		.BindEx(_macd, _ma, _cci, _adx, ProcessCandle)
		.Start();
		
		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, _ma);
			DrawOwnTrades(area);
			
			var indicatorArea = CreateChartArea();
			if (indicatorArea != null)
			{
				DrawIndicator(indicatorArea, _macd);
				DrawIndicator(indicatorArea, _cci);
				DrawIndicator(indicatorArea, _adx);
			}
		}
		
		StartProtection(new Unit(2m, UnitTypes.Percent), new Unit(1m, UnitTypes.Percent));
	}
	
	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdVal, IIndicatorValue maVal, IIndicatorValue cciVal, IIndicatorValue adxVal)
	{
		if (candle.State != CandleStates.Finished)
		return;
		
		if (!IsFormedAndOnlineAndAllowTrading())
		return;
		
		var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
		var adxTyped = (AverageDirectionalIndexValue)adxVal;
		
		var disableBuy = false;
		var disableSell = false;
		
		if (EnableMacd)
		{
			var macd = macdTyped.Macd ?? 0m;
			var signal = macdTyped.Signal ?? 0m;
			if (macd > signal)
			disableSell = true;
			else if (macd < signal)
			disableBuy = true;
		}
		
		if (EnableMa)
		{
			var ma = maVal.ToDecimal();
			if (candle.ClosePrice > ma)
			disableSell = true;
			else if (candle.ClosePrice < ma)
			disableBuy = true;
		}
		
		if (EnableCci)
		{
			var cci = cciVal.ToDecimal();
			if (cci > 100m)
			disableBuy = true;
			else if (cci < -100m)
			disableSell = true;
		}
		
		if (EnableAdx)
		{
			var plus = adxTyped.Dx.Plus ?? 0m;
			var minus = adxTyped.Dx.Minus ?? 0m;
			if (plus > minus)
			disableSell = true;
			else if (minus > plus)
			disableBuy = true;
		}

		var direction = !disableBuy && disableSell ? 1 : !disableSell && disableBuy ? -1 : 0;

		if (direction == 1 && _lastDirection != 1 && Position <= 0)
		{
			BuyMarket();
		}
		else if (direction == -1 && _lastDirection != -1 && Position >= 0)
		{
			SellMarket();
		}

		_lastDirection = direction;
	}
}