Ver no GitHub

Estratégia ADX Smoothed Cross

Resumo

A estratégia opera com base em um Average Directional Index (ADX) de suavização dupla. Compara as linhas +DI e -DI suavizadas para detectar mudanças de tendência. Quando a linha +DI suavizada cruza acima da linha -DI suavizada, a estratégia entra em uma posição comprada. Quando a linha +DI suavizada cruza abaixo da linha -DI suavizada, abre uma posição vendida.

Como Funciona

  • Utiliza um indicador ADX com período configurável.
  • Aplica duas passagens de suavização exponencial controladas pelos parâmetros Alpha1 e Alpha2.
  • Um sinal de compra ocorre quando o +DI suavizado anterior estava abaixo do -DI suavizado e o +DI suavizado atual está acima.
  • Um sinal de venda ocorre no cruzamento oposto.
  • Parâmetros opcionais permitem desabilitar operações compradas ou vendidas e controlar se as posições existentes podem ser fechadas quando um sinal oposto aparece.
  • O gerenciamento de risco integrado define níveis de stop-loss e take-profit em pontos.

Parâmetros

Nome Descrição
AdxPeriod Período para o cálculo do ADX.
Alpha1 Primeiro coeficiente de suavização (0-1).
Alpha2 Segundo coeficiente de suavização (0-1).
StopLoss Stop-loss em pontos.
TakeProfit Take-profit em pontos.
AllowBuy Habilitar entradas compradas.
AllowSell Habilitar entradas vendidas.
AllowCloseBuy Permitir fechar posições compradas em sinais de venda.
AllowCloseSell Permitir fechar posições vendidas em sinais de compra.
CandleType Período utilizado para o indicador.

Notas

  • Apenas velas finalizadas são processadas.
  • A estratégia usa a API de alto nível com vinculação de indicadores.
  • Stop-loss e take-profit são gerenciados via StartProtection.
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>
/// Smoothed EMA crossover strategy (ADX-inspired directional cross concept).
/// Buys when fast EMA crosses above slow EMA, sells when below.
/// </summary>
public class AdxSmoothedCrossStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	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 AdxSmoothedCrossStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicator");

		_slowPeriod = Param(nameof(SlowPeriod), 25)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicator");

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

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

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

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		SubscribeCandles(CandleType)
			.Bind(fast, slow, ProcessCandle)
			.Start();
	}

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

		if (_prevFast is null || _prevSlow is null)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastValue > slowValue;
		var crossDown = _prevFast >= _prevSlow && fastValue < slowValue;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}
}