Ver en GitHub

Estrategia Color 3rdGen XMA

Esta estrategia opera basándose en la dirección de una media móvil de tercera generación. El indicador es una combinación de dos medias móviles exponenciales y se vuelve azul cuando sube y rosa cuando baja. Se registra una señal de compra cuando la media gira hacia arriba, y una señal de venta cuando gira hacia abajo.

Las órdenes se colocan solo en un horario especificado por el usuario después de que aparece una señal. Las posiciones también pueden cerrarse cuando se detecta la señal opuesta o cuando vence un período de tenencia predefinido. Los niveles opcionales de stop-loss y take-profit se miden en puntos.

Parámetros

  • Length – período de suavizado de la media de tercera generación.
  • StartHour – hora en que se pueden abrir nuevas posiciones.
  • StartMinute – minuto dentro de la hora en que se permiten aperturas.
  • HoldMinutes – tiempo máximo para mantener una posición abierta.
  • Volume – volumen de orden utilizado para las entradas.
  • StopLoss – distancia de stop-loss en puntos. 0 deshabilita el stop.
  • TakeProfit – distancia de take-profit en puntos. 0 deshabilita el objetivo.
  • UseLongEntries – habilitar entradas largas.
  • UseShortEntries – habilitar entradas cortas.
  • CloseLongBySignal – cerrar posiciones largas cuando aparece una señal de venta.
  • CloseShortBySignal – cerrar posiciones cortas cuando aparece una señal de compra.
  • CandleType – marco temporal de las velas usadas para cálculos.

Lógica

  1. Suscribirse a velas del marco temporal seleccionado.
  2. Calcular la media móvil de tercera generación para cada vela.
  3. Detectar cuándo la media sube o baja entre velas consecutivas.
  4. Almacenar una señal de compra o venta basada en el cambio de dirección.
  5. En el horario de apertura especificado, entrar en la dirección de la señal almacenada.
  6. Cerrar posiciones en señales opuestas, cuando transcurre el tiempo de tenencia, o cuando se alcanzan los niveles de stop-loss/take-profit.
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>
/// Color 3rd Generation XMA strategy.
/// Uses two EMAs of different periods to approximate 3rd generation moving average.
/// Opens long when fast EMA crosses above slow EMA, short when crosses below.
/// </summary>
public class Color3RdGenXmaStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<decimal> _minSpread;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _isFirst = true;

	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public decimal MinSpread { get => _minSpread.Value; set => _minSpread.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public Color3RdGenXmaStrategy()
	{
		_fastLength = Param(nameof(FastLength), 20)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "General");

		_slowLength = Param(nameof(SlowLength), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "General");
		_minSpread = Param(nameof(MinSpread), 20m)
			.SetGreaterThanZero()
			.SetDisplay("Min Spread", "Minimum EMA spread in price steps", "General");

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

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

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

		_prevFast = 0m;
		_prevSlow = 0m;
		_isFirst = true;
	}

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

		_prevFast = 0m;
		_prevSlow = 0m;
		_isFirst = true;

		var fastEma = new ExponentialMovingAverage { Length = FastLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, ProcessCandle)
			.Start();

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

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

		if (_isFirst)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_isFirst = false;
			return;
		}

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

		var step = Security.PriceStep ?? 1m;
		var spread = Math.Abs(fast - slow);
		if (spread < MinSpread * step)
		{
			_prevFast = fast;
			_prevSlow = slow;
			return;
		}

		var prevAbove = _prevFast > _prevSlow;
		var curAbove = fast > slow;

		if (!prevAbove && curAbove && Position <= 0)
			BuyMarket();
		else if (prevAbove && !curAbove && Position >= 0)
			SellMarket();

		_prevFast = fast;
		_prevSlow = slow;
	}
}