Ver no GitHub

Estratégia de ADX MACD Deev

Visão geral

A Estratégia de ADX MACD Deev é um port StockSharp do consultor especialista MetaTrader com o mesmo nome. Combina o sinal de força de tendência do Índice Direcional Médio (ADX) com a confirmação de momentum da Convergência/Divergência de Médias Móveis (MACD). A estratégia opera apenas quando ambos os indicadores concordam na direção do mercado e pode opcionalmente assegurar lucros através de trailing stops e saídas parciais de posição.

Como funciona

  1. Preparação de indicadores
    • ADX é calculado com um período de médio configurável. A estratégia rastreia os valores mais recentes de ADX e requer que se movam consistentemente em uma direção antes de permitir uma negociação.
    • MACD usa EMAs rápidas, lentas e de sinal exponenciais configuráveis. O histograma e a linha de sinal devem mostrar conjuntamente um crescimento sustentado para comprados ou um declínio sustentado para vendidos.
  2. Lógica de entrada
    • Entradas compradas: acionadas quando o histograma MACD excede o limiar MACD Minimum (pips), tanto o histograma MACD quanto a linha de sinal aumentam pelo número selecionado de barras, e ADX permanece acima da força necessária enquanto também sobe.
    • Entradas vendidas: acionadas quando o histograma MACD está abaixo do limiar negativo, tanto o histograma MACD quanto a linha de sinal declinam sobre o intervalo selecionado, e ADX permanece acima do mínimo enquanto decresce.
    • Apenas uma posição pode estar aberta por vez.
  3. Gestão de risco
    • Os níveis iniciais de stop-loss e take-profit são colocados em unidades de preço derivadas do instrumento PriceStep e das distâncias de pip escolhidas.
    • Um trailing stop pode seguir posições rentáveis assim que o preço avança Trailing Stop + Trailing Step pips.
    • Quando Take Half Profit está habilitado, a estratégia fecha metade da posição atual no nível de take-profit e deixa o restante correr com o trailing stop.

Parâmetros

Grupo Nome Descrição
Trading Order Volume Volume de cada nova ordem de mercado.
Risco Stop Loss (pips) Deslocamento inicial do stop-loss desde a entrada.
Risco Take Profit (pips) Deslocamento inicial do take-profit desde a entrada.
Risco Trailing Stop (pips) Distância do trailing stop. Definir como zero para desabilitar o trailing.
Risco Trailing Step (pips) Movimento de preço adicional antes do trailing stop se mover novamente.
Risco Take Half Profit Habilita saída parcial quando o nível de take-profit é atingido.
Indicadores ADX Period Período de médio do ADX.
Indicadores ADX Bars Interval Número de barras ADX recentes que devem seguir uma tendência em uma direção.
Indicadores ADX Minimum Valor mínimo de ADX necessário para entradas.
Indicadores MACD Fast EMA Comprimento da EMA rápida usada pelo MACD.
Indicadores MACD Slow EMA Comprimento da EMA lenta usada pelo MACD.
Indicadores MACD Signal EMA Comprimento da EMA de sinal usada pelo MACD.
Indicadores MACD Bars Interval Número de barras MACD que devem se alinhar na mesma direção.
Indicadores MACD Minimum (pips) Magnitude mínima do MACD convertida para pips.
Geral Candle Type Tipo de vela ou período usado para cálculos.

Notas de uso

  • A estratégia requer instrumentos com um PriceStep válido. Se PriceStep for zero, os limiares baseados em pips revertem para valores brutos de MACD.
  • O arredondamento de volume para saídas parciais segue o VolumeStep do instrumento.
  • Ajustes do trailing stop são avaliados apenas em velas fechadas.
  • A estratégia usa bindings de API de alto nível (SubscribeCandles().BindEx(...)) e não depende de polling manual de valores de indicadores.
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;

public class AdxMacdDeevStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public AdxMacdDeevStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}