Ver no GitHub

Estratégia de Vela XDPO

Esta estratégia é uma conversão do expert MQL5 original Exp_XDPOCandle. Ela constrói velas sintéticas aplicando duas médias móveis exponenciais consecutivas aos preços de abertura e fechamento. A cor da vela resultante (altista, baixista ou neutra) orienta as decisões de trading.

Lógica da estratégia

  1. Cada vela de mercado recebida é suavizada duas vezes:
    • O primeiro suavizamento usa uma EMA de comprimento FastLength.
    • O segundo suavizamento aplica outra EMA de comprimento SlowLength ao resultado do primeiro.
  2. Se o fechamento suavizado está acima da abertura suavizada, a vela é considerada altista.
  3. Se o fechamento suavizado está abaixo da abertura suavizada, a vela é considerada baixista.
  4. A estratégia abre uma posição comprada quando uma vela altista aparece após uma não altista. Abre uma posição vendida quando uma vela baixista aparece após uma não baixista.
  5. Posições opostas existentes são fechadas automaticamente revertendo através de ordens de mercado.

Parâmetros

Nome Descrição
FastLength Comprimento da primeira EMA aplicada aos preços.
SlowLength Comprimento da segunda EMA aplicada ao resultado da primeira EMA.
CandleType O período e tipo de velas usadas para o cálculo.

Uso

  1. Anexe a estratégia a um instrumento dentro do ambiente StockSharp.
  2. Configure os parâmetros se necessário. Os valores padrão estão ajustados para corresponder às configurações originais do expert.
  3. Inicie a estratégia. Ela irá se inscrever no tipo de vela especificado e operar nas mudanças de cor das velas suavizadas.

Notas

  • O gerenciamento de risco é tratado por StartProtection() com configurações padrão. Ajuste Volume e parâmetros de proteção externamente conforme necessário.
  • Este repositório atualmente contém apenas a versão em C#; o port em Python não está disponível.
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;
	}
}