Ver no GitHub

Estratégia Two MA One RSI

Esta estratégia porta o especialista MetaTrader 5 "Two MA one RSI" para o StockSharp. Combina um cruzamento de médias móveis rápida e lenta com uma confirmação RSI avaliada na vela fechada anterior. Interruptores flexíveis permitem converter cada comparação em uma regra "maior que" ou "menor que", para que a configuração possa ser invertida sem tocar no código.

Detalhes

  • Critérios de entrada:
    • Sinais comprados requerem que a MA rápida esteja abaixo da MA lenta há duas barras, que a MA rápida esteja acima da MA lenta na barra fechada mais recente, e que o RSI da barra anterior esteja acima do limiar superior. Cada comparação pode ser invertida por parâmetros booleanos.
    • Sinais vendidos espelham a lógica e verificam as relações de MA opostas junto com o RSI caindo abaixo do limiar inferior.
    • Ambas as MAs usam o mesmo tipo de média; o período lento é sempre FastMaPeriod * SlowPeriodMultiplier. Deslocamentos horizontais opcionais reproduzem o comportamento do MT5 onde os valores do indicador são lidos várias velas atrás.
  • Comprado/Vendido: A estratégia pode abrir posições em ambas as direções. CloseOppositePositions controla se um novo sinal força o lado oposto a fechar antes de entrar.
  • Critérios de saída:
    • Stop-loss e take-profit configuráveis em pips.
    • Trailing stop opcional que só se move depois que o preço avança pelo menos TrailingStopPips + TrailingStepPips além da entrada.
    • ProfitClose monitora P&L flutuante (usando o preço de passo do instrumento) e fecha todas as posições quando o valor alvo em moeda é atingido.
  • Stops: Quando StopLossPips é zero, a estratégia depende puramente do módulo de trailing stop (se habilitado). TrailingStopPips requer um TrailingStepPips positivo, correspondendo à validação do especialista original.
  • Valores padrão:
    • FastMaPeriod = 10, SlowPeriodMultiplier = 2.
    • FastMaShift = 3, SlowMaShift = 0.
    • RsiPeriod = 10, RsiUpperLevel = 70, RsiLowerLevel = 30.
    • StopLossPips = 50, TakeProfitPips = 150, TrailingStopPips = 15, TrailingStepPips = 5.
    • MaxPositions = 10, ProfitClose = 100, TradeVolume = 1.
  • Filtros: Seis interruptores booleanos (BuyPreviousFastBelowSlow, BuyCurrentFastAboveSlow, BuyRequiresRsiAboveUpper, SellPreviousFastAboveSlow, SellCurrentFastBelowSlow, SellRequiresRsiBelowLower) permitem ao usuário alterar instantaneamente o sentido de cada comparação.

Parâmetros

Nome Descrição
CandleType Período (ou outro tipo de vela) usado para análise.
MaType Família de médias móveis (simples, exponencial, suavizada, ponderada, ponderada por volume).
FastMaPeriod Período da MA rápida.
SlowPeriodMultiplier Multiplicador de período da MA lenta (lenta = rápida * multiplicador).
FastMaShift, SlowMaShift Deslocamentos horizontais em velas aplicados ao avaliar valores de MA.
RsiPeriod Comprimento do RSI (usa a vela finalizada anterior).
RsiUpperLevel, RsiLowerLevel Limiares RSI para confirmações compradas e vendidas.
BuyPreviousFastBelowSlow, BuyCurrentFastAboveSlow, BuyRequiresRsiAboveUpper Ativar/desativar comparações para sinais comprados.
SellPreviousFastAboveSlow, SellCurrentFastBelowSlow, SellRequiresRsiBelowLower Ativar/desativar comparações para sinais vendidos.
StopLossPips, TakeProfitPips Stop protetor e alvo medido em pips (tamanho do pip derivado do passo de preço do instrumento).
TrailingStopPips, TrailingStepPips Distância do trailing stop e melhoria mínima.
MaxPositions Número máximo de entradas simultâneas por direção (0 = ilimitado).
ProfitClose Meta de lucro em moeda que fecha todas as posições ao ser atingida.
CloseOppositePositions Se deve fechar o lado oposto antes de abrir uma nova operação.
TradeVolume Tamanho base da ordem; também se sincroniza com a propriedade Volume da estratégia.

Notas de implementação

  • Todas as decisões usam apenas velas finalizadas, igualando a lógica de "nova barra" do especialista MT5.
  • O tamanho do pip é igual ao passo de preço do instrumento. Se seu mercado usa preços de pip fracionários, ajuste as configurações do instrumento adequadamente para que a tradução do pip corresponda à lógica digits_adjust do especialista original.
  • Os trailing stops só começam depois que o preço avançou TrailingStopPips + TrailingStepPips; o stop é então ancorado TrailingStopPips distante do fechamento e só se move quando melhora pelo menos TrailingStepPips.
  • ProfitClose calcula lucro flutuante usando PriceStep e StepPrice do instrumento. Certifique-se de que esses campos estejam configurados para resultados de moeda corretos.
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;

/// <summary>
/// Two MA one RSI strategy (simplified).
/// EMA crossover filtered by RSI levels.
/// </summary>
public class TwoMaOneRsiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rsiPeriod;

	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;
	}

	public TwoMaOneRsiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");

		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI length", "Indicators");
	}

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		decimal prevFast = 0, prevSlow = 0;
		bool hasPrev = false;

		var subscription = SubscribeCandles(CandleType);
		// Use Bind with fast, slow - RSI computed separately via cross-feed
		subscription
			.Bind(fast, slow, (ICandleMessage candle, decimal fastValue, decimal slowValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!hasPrev)
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					hasPrev = true;
					return;
				}

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					return;
				}

				// Golden cross + RSI not overbought
				if (prevFast <= prevSlow && fastValue > slowValue && Position <= 0)
				{
					BuyMarket();
				}
				// Death cross + RSI not oversold
				else if (prevFast >= prevSlow && fastValue < slowValue && Position >= 0)
				{
					SellMarket();
				}

				prevFast = fastValue;
				prevSlow = slowValue;
			})
			.Start();

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