Ver en GitHub

Estrategia de Vela XDPO

Esta estrategia es una conversión del experto MQL5 original Exp_XDPOCandle. Construye velas sintéticas aplicando dos medias móviles exponenciales consecutivas a los precios de apertura y cierre. El color de la vela resultante (alcista, bajista o neutral) impulsa las decisiones de trading.

Lógica de la estrategia

  1. Cada vela de mercado entrante se suaviza dos veces:
    • El primer suavizado utiliza una EMA de longitud FastLength.
    • El segundo suavizado aplica otra EMA de longitud SlowLength al resultado del primero.
  2. Si el cierre suavizado está por encima de la apertura suavizada, la vela se considera alcista.
  3. Si el cierre suavizado está por debajo de la apertura suavizada, la vela se considera bajista.
  4. La estrategia abre una posición larga cuando aparece una vela alcista tras una no alcista. Abre una posición corta cuando aparece una vela bajista tras una no bajista.
  5. Las posiciones opuestas existentes se cierran automáticamente revirtiendo mediante órdenes de mercado.

Parámetros

Nombre Descripción
FastLength Longitud de la primera EMA aplicada a los precios.
SlowLength Longitud de la segunda EMA aplicada al resultado de la primera EMA.
CandleType El marco temporal y tipo de velas utilizadas para el cálculo.

Uso

  1. Adjunte la estrategia a un instrumento dentro del entorno StockSharp.
  2. Configure los parámetros si es necesario. Los valores predeterminados están ajustados para coincidir con la configuración del experto original.
  3. Inicie la estrategia. Se suscribirá al tipo de vela especificado y operará en los cambios de color de las velas suavizadas.

Notas

  • La gestión de riesgos se maneja mediante StartProtection() con configuración predeterminada. Ajuste Volume y los parámetros de protección externamente según sea necesario.
  • Este repositorio actualmente solo contiene la versión en C#; el port en Python no está disponible.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;



/// <summary>
/// XDPO candle strategy that trades on color changes of double smoothed candles.
/// </summary>
public class XdpoCandleStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _emaOpen1;
	private decimal? _emaOpen2;
	private decimal? _emaClose1;
	private decimal? _emaClose2;
	private int? _previousColor;

	/// <summary>
	/// Length of the first exponential moving average.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	/// <summary>
	/// Length of the second exponential moving average.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	/// <summary>
	/// Candle type used for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of <see cref="XdpoCandleStrategy"/>.
	/// </summary>
	public XdpoCandleStrategy()
	{
		_fastLength = Param(nameof(FastLength), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Length", "Length of the first EMA", "Parameters")
			;

		_slowLength = Param(nameof(SlowLength), 5)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Length of the second EMA", "Parameters")
			;

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

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

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

		_emaOpen1 = _emaOpen2 = _emaClose1 = _emaClose2 = null;
		_previousColor = null;
	}

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

		var warmup = new StockSharp.Algo.Indicators.ExponentialMovingAverage { Length = FastLength };
		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(warmup, ProcessCandle)
			.Start();

	}

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

		var open1 = CalcEma(candle.OpenPrice, ref _emaOpen1, FastLength);
		var open2 = CalcEma(open1, ref _emaOpen2, SlowLength);
		var close1 = CalcEma(candle.ClosePrice, ref _emaClose1, FastLength);
		var close2 = CalcEma(close1, ref _emaClose2, SlowLength);

		var color = open2 < close2 ? 2 : open2 > close2 ? 0 : 1;
		var goLong = color == 2 && _previousColor != 2;
		var goShort = color == 0 && _previousColor != 0;

		if (IsFormedAndOnlineAndAllowTrading())
		{
			if (goLong && Position <= 0)
				BuyMarket();
			else if (goShort && Position >= 0)
				SellMarket();
		}

		_previousColor = color;
	}

	private static decimal CalcEma(decimal price, ref decimal? prev, int length)
	{
		var k = 2m / (length + 1m);
		var result = prev.HasValue ? price * k + prev.Value * (1m - k) : price;
		prev = result;
		return result;
	}
}