Ver no GitHub

Estratégia Exp X2MA Candle MM Recovery

Visão geral

Esta estratégia é uma conversão em C# do expert do MetaTrader Exp_X2MACandle_MMRec. Ela observa a cor de um candle duplamente suavizado, produzido pelo indicador personalizado X2MA original, para decidir quando abrir ou fechar posições. A versão StockSharp recria o pipeline de suavização dupla e mantém uma camada leve de gestão de dinheiro que reduz o volume de trading após um número configurável de perdas recentes.

O algoritmo processa apenas candles completados. Ele assina um período configurável, aplica duas médias móveis encadeadas aos valores OHLC do candle, deriva uma cor sintética de candle (verde, cinza ou vermelho) e usa transições de cor com um deslocamento de barra selecionável pelo usuário para acionar ações. Operações compradas são abertas quando a cor muda de altista para qualquer outra coisa. Operações vendidas seguem a condição simétrica. As saídas de posição estão alinhadas com as mesmas verificações de cor e podem ser habilitadas ou desabilitadas separadamente para cada lado.

Lógica do indicador

  1. Cada candle é suavizado duas vezes. Ambas as etapas podem usar diferentes métodos e comprimentos.
  2. As opções de suavização mapeiam para indicadores do StockSharp:
    • SimpleSimpleMovingAverage
    • ExponentialExponentialMovingAverage
    • SmoothedSmoothedMovingAverage (RMA)
    • WeightedWeightedMovingAverage
    • JurikJurikMovingAverage (o parâmetro Phase é respeitado quando disponível).
  3. O corpo do candle sintético é achatado quando a diferença absoluta abertura/fechamento está abaixo de GapPoints * Security.StepPrice.
  4. As cores são atribuídas da seguinte forma: abertura < fechamento → 2 (altista), abertura > fechamento → 0 (baixista), caso contrário → 1 (neutro).
  5. Os sinais são avaliados na barra SignalBar + 1 (duas barras atrás com a configuração padrão) para que as ordens sejam enviadas apenas após um candle completo confirmar a mudança de cor.

Gestão de dinheiro

  • O expert original reduzia dinamicamente o tamanho da posição após uma série de perdas usando estatísticas históricas de negociações. O StockSharp não expõe o histórico exato do MetaTrader, então o port mantém uma fila interna de negociações fechadas recentes.
  • O comprimento da fila é controlado por HistoryDepth e o volume cai para ReducedVolume uma vez que LossTrigger ou mais perdas sejam detectadas dentro da janela.
  • A estratégia registra os resultados das negociações usando preços de fechamento de candles quando uma saída manual é acionada. As ordens stop-loss/take-profit da versão MetaTrader não são recriadas. Você pode adicionar suas próprias regras de proteção através dos gestores de risco do StockSharp se necessário.

Parâmetros

Nome Descrição
CandleType Período dos candles usados para suavização e trading.
FirstMethod, FirstLength, FirstPhase Método de suavização primário, comprimento e fase Jurik.
SecondMethod, SecondLength, SecondPhase Método de suavização secundário, comprimento e fase Jurik.
GapPoints Limiar de achatamento do corpo em passos de preço.
SignalBar Deslocamento (0 = último candle terminado) ao ler os buffers de cor.
AllowLongEntry / AllowShortEntry Habilitar abertura de posições compradas ou vendidas.
AllowLongExit / AllowShortExit Habilitar fechamento de posições compradas ou vendidas.
NormalVolume Tamanho de ordem padrão (lotes, ações, contratos).
ReducedVolume Tamanho de ordem usado após o número configurado de perdas.
HistoryDepth Número de negociações recentes inspecionadas para perdas (0 desativa o rastreamento do histórico).
LossTrigger Contagem de perdas que ativa o volume reduzido (0 desativa o interruptor).

Notas de uso

  • A estratégia opera em um único instrumento retornado por GetWorkingSecurities().
  • Sinais e saídas são processados uma vez por candle terminado para evitar ordens duplicadas.
  • Definir ReducedVolume igual a NormalVolume se quiser desativar a redução de volume mantendo as estatísticas do histórico.
  • Como o port depende de preços de fechamento de candles para classificar as negociações, o contador de perdas pode diferir ligeiramente do MetaTrader quando ocorrem deslizamentos ou execuções parciais. A documentação deve ajudá-lo a ajustar os parâmetros para obter comportamento similar.
  • Stops e take-profits da versão MQL não são recriados automaticamente. Usar gestores de risco do StockSharp (StartProtection) se precisar de proteção a nível de plataforma.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

public class ExpX2MaCandleMmRecStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private decimal? _prevFast, _prevSlow;

	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 ExpX2MaCandleMmRecStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 8).SetGreaterThanZero().SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 25).SetGreaterThanZero().SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = null;
		_prevSlow = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = null; _prevSlow = null;
		var fast = new WeightedMovingAverage { Length = FastPeriod };
		var slow = new WeightedMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
		if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
		var prevAbove = _prevFast.Value > _prevSlow.Value;
		var currAbove = fast > slow;
		_prevFast = fast; _prevSlow = slow;
		if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
	}
}