Ver en GitHub

Estrategia Color Zerolag JCCX

Estrategia inspirada en el indicador ColorZerolagJCCX de MetaTrader. Aproxima el oscilador original utilizando dos medias móviles simples. La estrategia va largo cuando la media rápida cruza por debajo de la media lenta y va corto cuando la media rápida cruza por encima de la media lenta.

Detalles

  • Criterios de entrada:
    • Largo: La MA rápida cruza por debajo de la MA lenta
    • Corto: La MA rápida cruza por encima de la MA lenta
  • Largo/Corto: Ambos
  • Criterios de salida: Señal opuesta
  • Stops: StartProtection()
  • Valores predeterminados:
    • FastPeriod = 8
    • SlowPeriod = 21
    • CandleType = velas de 4 horas
  • Filtros:
    • Categoría: Seguimiento de tendencia
    • Dirección: Ambos
    • Indicadores: Media móvil
    • Stops: Opcional
    • Complejidad: Básico
    • Marco temporal: Swing
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Simple crossover strategy inspired by ColorZerolagJCCX indicator.
/// Uses two moving averages and trades on crossovers.
/// </summary>
public class ColorZerolagJccxStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private bool _initialized;
	private decimal _prevFast;
	private decimal _prevSlow;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public ColorZerolagJccxStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 8)
			.SetGreaterThanZero()
			.SetDisplay("Fast MA", "Fast moving average period", "Moving Average");

		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow MA", "Slow moving average period", "Moving Average");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for calculation", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_initialized = false;
		_prevFast = default;
		_prevSlow = default;
	}

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

		var fastMa = new ExponentialMovingAverage { Length = FastPeriod };
		var slowMa = new ExponentialMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastMa, slowMa, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fastMa);
			DrawIndicator(area, slowMa);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_initialized)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_initialized = true;
			return;
		}

		var wasFastAbove = _prevFast > _prevSlow;
		var isFastAbove = fast > slow;

		if (!wasFastAbove && isFastAbove && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (wasFastAbove && !isFastAbove && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}