Ver no GitHub

Robô ADX + 2 Estratégia MA

Visão geral

A estratégia Robot ADX + 2 MA é uma versão StockSharp do MetaTrader especialista Robot_ADX+2MA. O sistema combina um rápido e um lento média móvel exponencial com os componentes +DI/-DI do Índice Direcional Médio (ADX). Os pedidos só são abertos quando o a vela anterior mostra uma separação EMA suficientemente ampla e a vela atual confirma o impulso através do índice direcional. O conversão mantém o comportamento original de abrir no máximo uma posição de mercado por vez e delegar saídas para stop-loss e proteções de lucro.

Lógica de negociação

  1. Assine a série de velas primárias configurada por meio de CandleType e processe apenas velas concluídas.
  2. Alimente duas médias móveis exponenciais (períodos 5 e 12) com os preços de fechamento das velas. Seus valores da vela anterior emular o lookback shift = 1 usado em MetaTrader.
  3. Alimente um indicador AverageDirectionalIndex (período 6) com as mesmas velas. Armazene o +DI/-DI atual e o anterior leituras para replicar os filtros EA.
  4. Calcule a distância absoluta EMA da vela anterior e compare-a com DifferenceThreshold convertida de pontos em unidades de preço (Point em MetaTrader é igual a Security.PriceStep em StockSharp).
  5. Entrada de alta: permitida somente se nenhuma posição estiver aberta e as seguintes condições forem atendidas:
    • O rápido anterior EMA está abaixo do lento anterior EMA.
    • O +DI anterior está abaixo de 5, o +DI atual está acima de 10 e o +DI é mais forte que o -DI.
    • A distância EMA está acima do limite configurado.
  6. Entrada de baixa: simétrica às regras longas, exigindo o rápido anterior EMA acima do EMA lenta, os filtros -DI devem ser satisfeito e -DI para dominar +DI.
  7. Quando uma negociação for aberta, conte com o módulo de risco iniciado por StartProtection para sair por meio de take-profit ou stop loss. Sem manual regras de saída são adicionadas, correspondendo ao especialista original.

Parâmetros

Nome Tipo Padrão Descrição
CandleType DataType Período de 1 minuto Série de velas primárias processadas pela estratégia.
TakeProfitPoints int 4700 Distância da meta de lucro expressa em etapas de preço. Defina como zero para desativar.
StopLossPoints int 2400 Distância da meta de stop-loss em etapas de preço. Defina como zero para desativar.
TradeVolume decimal 0.1 Volume líquido utilizado para cada ordem de mercado.
DifferenceThreshold int 10 Distância mínima de EMA (em etapas de preço) necessária antes que um sinal seja aceito.

Gestão de risco

  • A versão StockSharp chama StartProtection com UnitTypes.Step, portanto, as distâncias de stop-loss e take-profit configuradas são convertido automaticamente para a etapa de preço da corretora.
  • As ordens de proteção são geradas como saídas de mercado (useMarketOrders = true), replicando o comportamento de fechamento imediato do MQL função auxiliar.

Detalhes de implementação

  • As vinculações de indicadores usam SubscribeCandles(...).Bind(...).BindEx(...) API de alto nível, portanto, nenhum loop manual de dados é necessário.
  • Os valores EMA da vela anterior são armazenados em cache para reproduzir as chamadas iMA(..., shift = 1) no EA original.
  • Os dados de ADX são consumidos por meio de AverageDirectionalIndexValue, dando acesso direto aos componentes +DI e -DI sem chamar ajudantes GetValue proibidos.
  • Uma proteção por vela (_lastProcessedTime) garante que os sinais sejam avaliados apenas uma vez, mesmo que as ligações EMA e ADX sejam acionadas retornos de chamada para a mesma vela.

Diferenças do especialista MetaTrader

  • A chamada direta redundante OrderSend presente na ramificação de venda do código MQL é removida; ambas as direções usam um único Ajudante BuyMarket/SellMarket.
  • MetaTrader verifica a margem livre antes de enviar pedidos. A porta StockSharp delega controles de risco ao ambiente de hospedagem e assume equilíbrio suficiente.
  • A lógica de proteção é implementada por meio do gerenciador de risco do StockSharp em vez de loops personalizados que chamam OrderSend repetidamente.

Dicas de uso

  • Ajuste TradeVolume para respeitar a etapa do lote do título selecionado antes de iniciar a negociação ao vivo.
  • Se o mercado usar uma escala de preços diferente, ajuste DifferenceThreshold junto com as distâncias de stop/alvo para que o EMA a separação é comparável à configuração MetaTrader.
  • O período padrão é de um minuto, mas o parâmetro CandleType permite alternar para qualquer outra série suportada pelos dados fonte.

Indicadores

  • ExponentialMovingAverage(5) calculado sobre preços de fechamento.
  • ExponentialMovingAverage(12) calculado sobre preços de fechamento.
  • AverageDirectionalIndex(6) fornecendo filtros de força +DI/-DI e ADX.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RobotADX2MA: Dual EMA crossover with RSI confirmation and ATR stops.
/// </summary>
public class RobotAdxTwoMaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastEmaLength;
	private readonly StrategyParam<int> _slowEmaLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;

	public RobotAdxTwoMaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_fastEmaLength = Param(nameof(FastEmaLength), 5)
			.SetDisplay("Fast EMA Length", "Fast EMA period.", "Indicators");
		_slowEmaLength = Param(nameof(SlowEmaLength), 12)
			.SetDisplay("Slow EMA Length", "Slow EMA period.", "Indicators");
		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastEmaLength { get => _fastEmaLength.Value; set => _fastEmaLength.Value = value; }
	public int SlowEmaLength { get => _slowEmaLength.Value; set => _slowEmaLength.Value = value; }
	public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

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

		_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
		var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fastEma, slowEma, rsi, atr, 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 fastVal, decimal slowVal, decimal rsiVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0) { _prevFast = fastVal; _prevSlow = slowVal; return; }
		var close = candle.ClosePrice;

		if (Position > 0)
		{
			if ((fastVal < slowVal && _prevFast >= _prevSlow) || close <= _entryPrice - atrVal * 2m) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if ((fastVal > slowVal && _prevFast <= _prevSlow) || close >= _entryPrice + atrVal * 2m) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (fastVal > slowVal && _prevFast <= _prevSlow && rsiVal > 50) { _entryPrice = close; BuyMarket(); }
			else if (fastVal < slowVal && _prevFast >= _prevSlow && rsiVal < 50) { _entryPrice = close; SellMarket(); }
		}
		_prevFast = fastVal; _prevSlow = slowVal;
	}
}