Ver no GitHub

Estratégia de Cronex RSI

A Estratégia de Cronex RSI recria o consultor especialista Exp_CronexRSI.mq5 na API de alto nível do StockSharp. A pilha de indicadores combina um Índice de Força Relativa (RSI) clássico com duas médias móveis sequenciais para reduzir o ruído. As decisões de trading são baseadas em cruzamentos entre as curvas RSI suavizadas rápida e lenta, com permissões de entrada/saída configuráveis que correspondem aos parâmetros MQL5 originais.

Lógica de trading

  1. Construir o RSI a partir do preço aplicado e do período de retrocesso selecionados.
  2. Suavizar o valor RSI com uma média móvel rápida, depois suavizar o resultado com uma média móvel lenta.
  3. Avaliar cruzamentos com um deslocamento de confirmação configurável:
    • Quando a curva rápida estava acima da curva lenta uma barra antes e cai abaixo na barra confirmada, a estratégia fecha posições vendidas e, se habilitado, abre uma posição comprada.
    • Quando a curva rápida estava abaixo da curva lenta e cruza acima na barra confirmada, a estratégia fecha compradas e pode entrar em operações vendidas.
  4. Os volumes são simétricos em ambas as direções. Quando um novo sinal reverte a posição, a estratégia primeiro cobre a exposição existente e depois abre o novo lado usando o volume base configurado.

Por padrão a estratégia aguarda uma vela completamente fechada antes de agir sobre um sinal, reproduzindo o comportamento SignalBar = 1 do Exp_CronexRSI. Definir o deslocamento para zero processa o cruzamento imediatamente na barra de fechamento.

Parâmetros

Nome Descrição
RsiPeriod Período de retrocesso RSI.
FastPeriod Comprimento da média móvel de suavização rápida.
SlowPeriod Comprimento da segunda média móvel de suavização.
SignalShift Número de barras concluídas usadas para confirmação (0 reage instantaneamente).
SmoothingMethod Tipo de média móvel aplicado durante ambos os estágios de suavização (simples, exponencial, suavizada, ponderada linear, ponderada por volume).
AppliedPrice Componente de preço passado ao RSI (fechamento, abertura, máximo, mínimo, mediana, típico, ponderado).
CandleType Série de velas processada pela estratégia.
TradeVolume Tamanho de ordem base usado para novas entradas.
EnableLongEntry / EnableShortEntry Permitir abertura de posições compradas/vendidas.
EnableLongExit / EnableShortExit Permitir fechamento de posições em resposta a sinais opostos.

Notas de implementação

  • O método de suavização usa classes de média móvel do StockSharp. A opção VolumeWeighted também cobre os estilos VIDYA/AMA do MQL5 aplicando um substituto pragmático ponderado por volume.
  • A seleção de preço aplicado corresponde às entradas do indicador Cronex e reflete o auxiliar usado dentro do consultor especialista original.
  • Todos os valores de indicadores são processados através de instâncias DecimalIndicatorValue para permanecer compatíveis com o pipeline de indicadores do StockSharp enquanto evita polling direto de valores.
  • A estratégia redimensiona automaticamente seu histórico interno quando o deslocamento de confirmação muda, garantindo que a lógica de cruzamento mantenha a estrutura exata de retrocesso da versão MQL5.

Uso

  1. Anexar a estratégia a uma carteira e ativo no designer do StockSharp ou via código.
  2. Configurar o período de velas, estilo de suavização e permissões de trading para corresponder à configuração preferida do Cronex RSI.
  3. Lançar a estratégia. Ela subscreverá a série de velas selecionada, atualizará a combinação RSI/MA e enviará ordens a mercado em cruzamentos confirmados.
  4. Usar os auxiliares de gráfico integrados para visualizar as curvas de indicadores e operações executadas para validação adicional.
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 CronexRsiStrategy : 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 CronexRsiStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).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;
	}
}