Ver no GitHub

Divergência + EMA + RSI Fechar somente compra

Visão geral

Esta estratégia transfere o consultor especialista MetaTrader "Divergence + ema + rsi close buy only" para o API de alto nível de StockSharp. Ele atua em velas de 5 minutos enquanto consulta dados horários e diários para confirmar o alinhamento de tendências e condições de sobrevenda. Os pedidos são apenas longos. As entradas exigem uma divergência de alta do histograma MACD que é confirmada por um cruzamento estocástico horário dentro de uma faixa estreita de sobrevenda e por uma estrutura diária crescente EMA. As saídas dependem de um overshoot fixo de RSI combinado com proteção opcional de stop-loss e take-profit gerenciada pela estrutura.

Lógica de negociação

  1. Filtro de tendência de período de tempo mais alto

    • O EMA(9) diário deve estar acima de EMA(20) para garantir uma tendência de alta prevalecente.
    • O último fechamento de 5 minutos deve permanecer abaixo do EMA(9) diário para que entradas longas sejam tentadas a partir de retrocessos.
  2. Confirmação estocástica por hora

    • O valor %K estocástico horário concluído mais recente deve estar entre StochasticLowerBound (padrão 0) e StochasticUpperBound (padrão 40).
    • %K deve ter ultrapassado %D na última barra horária (%K atual > %D enquanto o %K anterior ≤ %D anterior).
  3. MACD gatilho de divergência (5 minutos)

    • O histograma MACD (linha MACD menos linha de sinal) deve melhorar em pelo menos MacdThreshold enquanto o fechamento de 5 minutos define um mínimo mais baixo em comparação com a vela anterior. Isso se aproxima da divergência de alta usada pelo EA original.
  4. Execução de entrada

    • Quando todos os filtros estão alinhados e nenhuma posição comprada está aberta, a estratégia envia uma compra de mercado. Se existir uma posição curta inesperada, o volume solicitado é aumentado para neutralizá-la antes de lançar uma posição longa.
  5. Regras de saída

    • Uma saída protetora RSI fecha o comprimento quando o RSI de 5 minutos cruza acima de RsiExitLevel (padrão 77).
    • StartProtection ativa os níveis de stop-loss e take-profit convertidos de pips em distâncias de preço sempre que os parâmetros correspondentes forem positivos.
  6. Gerenciamento de pedidos

    • Todas as ordens ativas são canceladas antes do envio de uma nova ordem de compra de mercado para evitar preenchimentos duplicados.
    • O volume padrão é o parâmetro TradeVolume e pode ser ajustado para otimização.

Parâmetros

Nome Descrição Padrão
CandleType Prazo principal para MACD, RSI e execução. Velas de 5 minutos
HourTimeFrame Período horário usado pelo filtro estocástico. 1 hora
DayTimeFrame Prazo diário para confirmação da tendência EMA. 1 dia
MacdFastPeriod / MacdSlowPeriod / MacdSignalPeriod Estrutura MACD no período primário. 6/13/5
MacdThreshold Aumento mínimo de MACD no histograma para aceitar uma divergência. 0,0003
DailyFastPeriod / DailySlowPeriod Períodos diários EMA. 20/09
StochasticKPeriod / StochasticDPeriod / StochasticSlowing Configuração estocástica horária. 30/5/9
StochasticUpperBound / StochasticLowerBound Faixa de %K por hora aceita. 40/0
RsiPeriod Duração de RSI no período principal. 7
RsiExitLevel Valor RSI que força saídas longas. 77
TradeVolume Tamanho base do pedido para compras. 0,01
StopLossPips Distância de stop-loss em pips (0 desativa). 100
TakeProfitPips Distância de lucro em pips (0 desabilita). 200

Notas

  • A estratégia assina três fluxos de dados: o período primário configurado, uma série horária e uma série diária. Cada fluxo aciona seu próprio conjunto de indicadores via Bind/BindEx para manter a implementação concisa e orientada a eventos.
  • Os valores dos indicadores são processados apenas em velas finalizadas para espelhar os parâmetros de deslocamento do EA original.
  • A detecção de divergência MACD usa o valor de fechamento e histograma da barra anterior como uma aproximação simples, porém robusta, da lógica gerada pelo construtor a partir do arquivo de origem MQL.
  • Stop-loss e take-profit são gerenciados por StartProtection para permanecerem sincronizados com os preenchimentos do corretor e oferecer suporte a backtesting ou negociação ao vivo sem replicação manual de pedidos.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Simplified from "Divergence EMA RSI Close Buy Only" MetaTrader expert.
/// Long-only strategy: buys when price pulls back below fast EMA with RSI oversold,
/// exits when RSI reaches overbought level.
/// </summary>
public class DivergenceEmaRsiCloseBuyOnlyStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiEntry;
	private readonly StrategyParam<decimal> _rsiExit;

	private ExponentialMovingAverage _ema;
	private RelativeStrengthIndex _rsi;
	private decimal? _prevRsi;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int EmaPeriod
	{
		get => _emaPeriod.Value;
		set => _emaPeriod.Value = value;
	}

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public decimal RsiEntry
	{
		get => _rsiEntry.Value;
		set => _rsiEntry.Value = value;
	}

	public decimal RsiExit
	{
		get => _rsiExit.Value;
		set => _rsiExit.Value = value;
	}

	public DivergenceEmaRsiCloseBuyOnlyStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for signals", "General");

		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period for trend filter", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 7)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period for entry/exit", "Indicators");

		_rsiEntry = Param(nameof(RsiEntry), 35m)
			.SetDisplay("RSI Entry", "RSI level to enter long", "Signals");

		_rsiExit = Param(nameof(RsiExit), 65m)
			.SetDisplay("RSI Exit", "RSI level to exit long", "Signals");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_ema = new ExponentialMovingAverage { Length = EmaPeriod };
		_rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		_prevRsi = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(_ema, _rsi, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, _ema);
			DrawOwnTrades(area);
		}
	}

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

		if (!_ema.IsFormed || !_rsi.IsFormed)
		{
			_prevRsi = rsiValue;
			return;
		}

		if (_prevRsi is null)
		{
			_prevRsi = rsiValue;
			return;
		}

		var volume = Volume;
		if (volume <= 0)
			volume = 1;
		var close = candle.ClosePrice;

		// Exit: RSI crosses above exit level
		if (Position > 0 && _prevRsi.Value < RsiExit && rsiValue >= RsiExit)
		{
			SellMarket(Position);
		}

		// Entry: RSI crosses below entry level and price is near/below EMA (buy the dip)
		if (Position <= 0 && _prevRsi.Value > RsiEntry && rsiValue <= RsiEntry && close <= emaValue * 1.005m)
		{
			if (Position < 0)
				BuyMarket(Math.Abs(Position));

			BuyMarket(volume);
		}

		_prevRsi = rsiValue;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_ema = null;
		_rsi = null;
		_prevRsi = null;

		base.OnReseted();
	}
}