Ver no GitHub

Estratégia RAVIiAO (StockSharp)

Visão geral

A Estratégia RAVIiAO reproduz o MetaTrader 4 consultor especialista "RAVIiAO" dentro do StockSharp API de alto nível. O sistema espera o fechamento de uma nova vela, avalia a inclinação do oscilador RAVI junto com a aceleração/desaceleração (AC) de Bill Williams oscilador e abre uma posição imediatamente no mercado quando ambos os indicadores concordam com a direção da tendência. O porto mantém o conjunto de parâmetros original – períodos de média móvel, limite, distâncias de stop-loss/take-profit e volume de pedidos – permitindo aos traders para replicar o comportamento legado sem ajustes manuais.

Fluxo de trabalho principal

  1. Assinatura de velas – a estratégia assina um período de tempo configurável (velas de 30 minutos por padrão).
  2. Atualizações do indicador – em cada vela finalizada ele atualiza duas médias móveis simples para construir o oscilador RAVI e feeds a mesma vela em um par Awesome Oscillator + suavização de 5 períodos para obter o valor AC.
  3. Preparação do sinal – a última vela finalizada é armazenada como "barra 1" enquanto o valor anterior se torna "barra 2", correspondendo ao Chamadas iCustom(...,1) e iCustom(...,2) de MetaTrader.
  4. Decisão de entrada – uma posição longa é aberta quando AC e RAVI aumentam acima de seus valores anteriores e confirmam uma ambiente otimista (AC[1] > AC[2] > 0 e RAVI[1] > RAVI[2] > Threshold). As negociações curtas usam as condições espelhadas.
  5. Gerenciamento de risco – assim que uma ordem é executada, a estratégia registra níveis estáticos de stop-loss e take-profit expressos em pontos do instrumento (ou seja, StopLossPoints * PriceStep). As velas são monitoradas quanto a violações intrabar usando seus preços altos/baixos.
  6. Redefinição de estado – quando um nível de proteção é atingido, a posição é fechada com uma ordem de mercado e os buffers internos são redefinidos para a próxima oportunidade.

Regras de negociação

  • Entradas longas
    • Valor AC anterior acima do valor AC anterior e ambos maiores que zero.
    • Leitura anterior de RAVI acima do limite e do valor RAVI anterior.
    • Nenhuma posição ativa no momento do sinal.
  • Entradas curtas
    • Valor AC anterior abaixo do valor AC anterior e ambos abaixo de zero.
    • Leitura anterior do RAVI abaixo do limite negativo e abaixo do valor anterior do RAVI.
    • Nenhuma posição ativa quando o sinal dispara.
  • Saídas de posição
    • Os níveis estáticos de stop-loss e take-profit são expressos em pontos brutos, convertidos em compensações de preço por meio do instrumento PriceStep.
    • As violações são detectadas com extremos de vela (baixo para paradas longas, alto para paradas curtas, etc.) e fechadas imediatamente via mercado ordens para emular as ordens de proteção de MetaTrader.

Parâmetros

Nome Descrição
CandleType Período usado para assinatura de velas (padrão 30 minutos).
FastLength Comprimento médio móvel rápido usado no oscilador RAVI.
SlowLength Comprimento médio de movimento lento usado no oscilador RAVI.
Threshold Porcentagem absoluta mínima de RAVI para validar uma continuação de tendência.
StopLossPoints Distância de stop-loss em pontos do instrumento (multiplicada por PriceStep).
TakeProfitPoints Distância de lucro em pontos de instrumento.
TradeVolume Volume de ordens de mercado para cada entrada.

Notas de conversão

  • A porta StockSharp armazena os dois valores mais recentes do indicador para que a decisão na vela n reutilize o AC[1] e RAVI[1] valores de MetaTrader (ou seja, resultados da barra anterior), preservando o estilo de execução "nova barra" de EA.
  • AC é reconstruído através da diferença entre o Awesome Oscillator e sua média móvel simples de 5 períodos, correspondendo ao MT4 cadeia de cálculo.
  • Stops e metas são avaliados em relação aos extremos das velas, em vez de colocar ordens de proteção pendentes; isso reflete o efeito do tratamento SL/TP integrado de MetaTrader, mantendo a implementação idiomática para StockSharp.

Dicas de uso

  • Certifique-se de que o instrumento selecionado exponha um PriceStep correto; caso contrário, as distâncias de proteção não corresponderão à versão MT4.
  • Otimize os parâmetros Threshold, FastLength e SlowLength ao adaptar a estratégia a mercados com diferentes características de volatilidade.
  • Combine a estratégia com proteções em nível de portfólio ou conector StockSharp para segurança adicional durante negociações ao vivo.
using System;
using System.Linq;
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;

/// <summary>
/// Port of the MetaTrader 4 expert advisor "RAVIiAO" that combines the RAVI oscillator and the Acceleration/Deceleration oscillator.
/// </summary>
public class RaviIaoStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<decimal> _threshold;
	private readonly StrategyParam<decimal> _stopLossPoints;
	private readonly StrategyParam<decimal> _takeProfitPoints;

	private SMA _aoAverage;

	private decimal? _prevRavi;
	private decimal? _prevPrevRavi;
	private decimal? _prevAc;
	private decimal? _prevPrevAc;

	/// <summary>
	/// Type of candles used for indicator calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Fast moving average length for the RAVI oscillator.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	/// <summary>
	/// Slow moving average length for the RAVI oscillator.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	/// <summary>
	/// Threshold for bullish or bearish confirmation of the RAVI oscillator (percentage value).
	/// </summary>
	public decimal Threshold
	{
		get => _threshold.Value;
		set => _threshold.Value = value;
	}

	/// <summary>
	/// Stop-loss distance in absolute price units.
	/// </summary>
	public decimal StopLossPoints
	{
		get => _stopLossPoints.Value;
		set => _stopLossPoints.Value = value;
	}

	/// <summary>
	/// Take-profit distance in absolute price units.
	/// </summary>
	public decimal TakeProfitPoints
	{
		get => _takeProfitPoints.Value;
		set => _takeProfitPoints.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of <see cref="RaviIaoStrategy"/>.
	/// </summary>
	public RaviIaoStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(10).TimeFrame())
			.SetDisplay("Candle Type", "Time-frame for analysis", "General");

		_fastLength = Param(nameof(FastLength), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Length", "Fast SMA period inside RAVI", "RAVI");

		_slowLength = Param(nameof(SlowLength), 72)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow SMA period inside RAVI", "RAVI");

		_threshold = Param(nameof(Threshold), 0.3m)
			.SetDisplay("RAVI Threshold", "Minimum absolute RAVI value to confirm the trend", "Signals");

		_stopLossPoints = Param(nameof(StopLossPoints), 500m)
			.SetNotNegative()
			.SetDisplay("Stop Loss", "Stop-loss distance in price units", "Risk");

		_takeProfitPoints = Param(nameof(TakeProfitPoints), 500m)
			.SetNotNegative()
			.SetDisplay("Take Profit", "Take-profit distance in price units", "Risk");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return new[] { (Security, CandleType) };
	}

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

		_prevRavi = null;
		_prevPrevRavi = null;
		_prevAc = null;
		_prevPrevAc = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		var fastMa = new SMA { Length = FastLength };
		var slowMa = new SMA { Length = SlowLength };
		var ao = new AwesomeOscillator();
		_aoAverage = new SMA { Length = 5 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(new IIndicator[] { fastMa, slowMa, ao }, ProcessCandle)
			.Start();

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

		// Use StartProtection for SL/TP
		var tp = TakeProfitPoints > 0 ? new Unit(TakeProfitPoints, UnitTypes.Absolute) : null;
		var sl = StopLossPoints > 0 ? new Unit(StopLossPoints, UnitTypes.Absolute) : null;
		StartProtection(tp, sl);

		base.OnStarted2(time);
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue[] values)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var fastVal = values[0];
		var slowVal = values[1];
		var aoVal = values[2];

		if (fastVal.IsEmpty || slowVal.IsEmpty || aoVal.IsEmpty)
			return;

		var fastValue = fastVal.ToDecimal();
		var slowValue = slowVal.ToDecimal();
		var aoValue = aoVal.ToDecimal();

		// Compute AC = AO - SMA(AO)
		var aoAvgResult = _aoAverage.Process(aoVal);
		if (aoAvgResult.IsEmpty)
			return;

		var aoAvgValue = aoAvgResult.ToDecimal();
		var ac = aoValue - aoAvgValue;

		if (slowValue == 0m)
		{
			UpdateHistory(null, ac);
			return;
		}

		var ravi = 100m * (fastValue - slowValue) / slowValue;

		if (_prevRavi is decimal prevRavi &&
			_prevPrevRavi is decimal prevPrevRavi &&
			_prevAc is decimal prevAc &&
			_prevPrevAc is decimal prevPrevAc &&
			Position == 0 &&
			IsFormedAndOnlineAndAllowTrading())
		{
			var bullish = prevAc > prevPrevAc && prevPrevAc > 0m && prevRavi > prevPrevRavi && prevRavi > Threshold;
			var bearish = prevAc < prevPrevAc && prevPrevAc < 0m && prevRavi < prevPrevRavi && prevRavi < -Threshold;

			if (bullish)
			{
				BuyMarket(Volume);
			}
			else if (bearish)
			{
				SellMarket(Volume);
			}
		}

		UpdateHistory(ravi, ac);
	}

	private void UpdateHistory(decimal? ravi, decimal ac)
	{
		_prevPrevRavi = _prevRavi;
		_prevRavi = ravi;
		_prevPrevAc = _prevAc;
		_prevAc = ac;
	}
}