Ver no GitHub

Estratégia Sidus EMA RSI

Esta estratégia é uma versão StockSharp do consultor especialista MetaTrader 4 Exp_Sidus.mq4. Reproduz a lógica original de que combina um cruzamento rápido/EMA lenta com um filtro RSI de 50 níveis. Os sinais são avaliados apenas em velas concluídas e cada vela pode gerar no máximo um pedido, correspondendo à disciplina de tempo do robô de origem.

Lógica de negociação

  • Pilha de indicadores
    • Média móvel exponencial rápida (período padrão 5)
    • Média móvel exponencial lenta (período padrão 12)
    • Índice de Força Relativa (período padrão 21)
  • Configuração de alta
    1. O EMA rápido estava abaixo ou igual ao EMA lento na vela de sinal anterior.
    2. O EMA rápido está acima do EMA lento na vela de sinal atual.
    3. RSI na mesma vela é estritamente maior que 50.
  • Configuração de baixa
    1. O EMA rápido estava acima ou igual ao EMA lento na vela de sinal anterior.
    2. O EMA rápido está abaixo do EMA lento na vela de sinal atual.
    3. RSI na mesma vela é estritamente menor que 50.
  • Signal shift — o parâmetro SignalShift (padrão 1) define qual vela fechada é considerada a barra de sinal "atual". Um valor de 1 usa a última vela fechada, 0 usa a vela recém-fechada, 2 olha duas barras atrás e assim por diante. O anterior vela para detecção de cruzamento é calculada automaticamente como SignalShift + 1.
  • Proteção duplicada — a estratégia armazena o tempo de abertura da vela sinalizadora e nunca abre outra posição vinculada ao mesma barra, imitando fielmente a verificação LastTime no EA original.

Gerenciamento de posição

  • Existe apenas uma posição por vez.
  • Quando um sinal oposto aparece enquanto uma posição está aberta, a estratégia primeiro fecha a posição existente e depois espera pela próxima passagem de processamento para abrir uma negociação na nova direção, exatamente como a versão MQL faz.
  • StartProtection anexa colchetes opcionais de take-profit e stop-loss expressos em faixas de preço (etapas de preço). As distâncias são derivado das entradas do EA original: pontos de take-profit padrão 80 e pontos de stop-loss 20.

Parâmetros

Nome Descrição Padrão Notas
TakeProfitPoints Distância de lucro em etapas de preço. 80 Defina 0 para desativar o alvo.
StopLossPoints Distância de stop-loss em etapas de preço. 20 Defina 0 para desativar a proteção.
TradeVolume Volume de pedidos (lotes/contratos). 0.1 Atribuído à propriedade base Volume no início.
FastPeriod Comprimento EMA rápido. 5 Otimizável.
SlowPeriod Comprimento EMA lento. 12 Otimizável.
RsiPeriod RSI comprimento. 21 Otimizável.
SignalShift Número de velas fechadas usadas para cálculos de sinal. 1 Espelha a entrada shif do MT4 EA.
CandleType Fonte de vela para a assinatura. 1h período de tempo Pode ser definido como qualquer DataType compatível com o ambiente.

Notas de implementação

  • Os dados da vela são inscritos via SubscribeCandles(CandleType) e processados dentro de ProcessCandle somente depois que a vela atinge o estado Finished.
  • Os valores dos indicadores são armazenados em cache em uma fila curta para que a estratégia possa acessar as barras atuais e anteriores especificadas por SignalShift sem chamar métodos indicadores como GetValue, obedecendo às diretrizes do repositório.
  • A execução da negociação usa BuyMarket/SellMarket quando a estratégia é plana; quando existe uma posição na direção oposta, ClosePosition é emitido primeiro, mantendo o fluxo de pedidos idêntico ao do robô original.
  • Todos os logs de tempo de execução são escritos em inglês para manter uma trilha de auditoria clara.

Notas de conversão

  • As distâncias take-profit e stop-loss multiplicam o instrumento PriceStep, replicando o comportamento MetaTrader Point.
  • O volume padrão é 0.1, o mesmo que a entrada Lots na fonte MQL.
  • Os limites de RSI são codificados em 50 para espelhar a implementação original.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Sidus EMA + RSI strategy: fast EMA crosses slow EMA confirmed by RSI above/below 50.
/// </summary>
public class SidusEmaRsiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rsiPeriod;

	private decimal _prevFast;
	private decimal _prevSlow;

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

		_fastPeriod = Param(nameof(FastPeriod), 5)
			.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 12)
			.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 21)
			.SetDisplay("RSI Period", "RSI period.", "Indicators");
	}

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

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

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

		_prevFast = 0;
		_prevSlow = 0;
	}

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

		var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, rsi, 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 fastValue, decimal slowValue, decimal rsiValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

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

		var bullishCross = _prevFast <= _prevSlow && fastValue > slowValue;
		var bearishCross = _prevFast >= _prevSlow && fastValue < slowValue;

		// Exit existing positions on opposite cross
		if (Position > 0 && bearishCross)
		{
			SellMarket();
		}
		else if (Position < 0 && bullishCross)
		{
			BuyMarket();
		}

		// Entry on crossover confirmed by RSI
		if (Position == 0)
		{
			if (bullishCross && rsiValue > 50)
			{
				BuyMarket();
			}
			else if (bearishCross && rsiValue < 50)
			{
				SellMarket();
			}
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}
}