Ver no GitHub

Estratégia de Vela de Mudança Média

Estratégia convertida do especialista MetaTrader Exp_AverageChangeCandle. Recria a lógica original dentro do StockSharp suavizando ratios de velas relativos a uma média móvel de referência dinâmica e reagindo às transições de cor altista/baixista.

Ideia principal

  1. Calcular uma média móvel de referência (MaMethod1, Length1) sobre o preço aplicado selecionado.
  2. Expressar o preço de abertura e fechamento da vela atual como ratios em relação à referência e elevá-los à potência Power.
  3. Suavizar os valores transformados de abertura e fechamento com uma segunda média móvel (MaMethod2, Length2).
  4. Classificar a cor da vela: altista quando o fechamento suavizado > abertura suavizada, baixista quando o fechamento suavizado < abertura suavizada.
  5. Gerar sinais de trading quando a cor muda após o atraso SignalBar configurado.

Apenas velas terminadas são processadas. A estratégia abre posições de mercado na direção da nova cor e opcionalmente fecha o lado oposto.

Parâmetros

Parâmetro Padrão Descrição
OrderVolume 1 Volume usado ao abrir uma nova posição.
MaMethod1 Lwma Suavização aplicada ao ratio de referência (subconjunto de SMA/EMA/SMMA/LWMA/JJMA/AMA). Tipos não suportados usam EMA.
Length1 12 Período da média móvel de referência.
Phase1 15 Parâmetro de fase Jurik para a referência (mantido por compatibilidade).
PriceSource Median Preço aplicado antes de calcular a referência.
MaMethod2 Jjma Suavização aplicada aos ratios transformados.
Length2 5 Período da média móvel de sinal.
Phase2 100 Parâmetro de fase Jurik para a suavização de sinal.
Power 5 Expoente usado ao elevar os ratios de abertura/fechamento.
SignalBar 1 Quantas velas fechadas esperar antes de agir em uma mudança de cor.
BuyOpenEnabled true Permitir abrir posições compradas.
SellOpenEnabled true Permitir abrir posições vendidas.
BuyCloseEnabled true Fechar comprados quando um sinal baixista aparece.
SellCloseEnabled true Fechar vendidos quando um sinal altista aparece.
StopLossPoints 0 Distância absoluta de stop-loss. 0 desativa o stop.
TakeProfitPoints 0 Distância absoluta de take-profit. 0 desativa o alvo.
CandleType Período H4 Série de velas processada pela estratégia.

Regras de trading

  • Transição altista (color muda para 2): fechar vendidos ativos (se permitido) e abrir uma posição comprada quando Position <= 0 e BuyOpenEnabled é verdadeiro.
  • Transição baixista (color muda para 0): fechar comprados ativos (se permitido) e abrir uma posição vendida quando Position >= 0 e SellOpenEnabled é verdadeiro.
  • Cor 1 (neutra) não aciona operações.
  • Os sinais são avaliados usando a barra localizada SignalBar passos atrás da vela terminada mais recente para imitar o timing original do MetaTrader.

Gestão de risco

StopLossPoints e TakeProfitPoints configuram StartProtection com distâncias absolutas. Quando qualquer valor é zero, a proteção respectiva é desativada.

Notas

  • Apenas os métodos de suavização disponíveis no StockSharp são implementados diretamente. JurX, ParMA, T3 e VIDYA do código original são mapeados para EMA como alternativa funcional.
  • Os parâmetros de fase são mantidos por compatibilidade, mas afetam apenas médias baseadas em Jurik/Kaufman.
  • A estratégia usa ordens de mercado assim como o assessor especialista original. O gerenciamento de slippage da versão MQL não é reproduzido porque o StockSharp lida com a execução via conectores.
namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// Average Change Candle strategy (simplified).
/// Compares smoothed open vs close ratios to detect bullish/bearish candle patterns.
/// Uses EMA of open and close to determine trend direction.
/// </summary>
public class AverageChangeCandleStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;

	private decimal _prevSmoothedOpen;
	private decimal _prevSmoothedClose;
	private bool _initialized;

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

	public int EmaPeriod
	{
		get => _emaPeriod.Value;
		set => _emaPeriod.Value = value;
	}

	public AverageChangeCandleStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Source candles", "General");

		_emaPeriod = Param(nameof(EmaPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA smoothing period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevSmoothedOpen = 0m;
		_prevSmoothedClose = 0m;
		_initialized = false;
	}

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

		_prevSmoothedOpen = 0;
		_prevSmoothedClose = 0;
		_initialized = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, (ICandleMessage candle, decimal emaValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				// Simple exponential smoothing of open and close
				var alpha = 2m / (EmaPeriod + 1m);

				if (!_initialized)
				{
					_prevSmoothedOpen = candle.OpenPrice;
					_prevSmoothedClose = candle.ClosePrice;
					_initialized = true;
					return;
				}

				var smoothedOpen = alpha * candle.OpenPrice + (1m - alpha) * _prevSmoothedOpen;
				var smoothedClose = alpha * candle.ClosePrice + (1m - alpha) * _prevSmoothedClose;

				var prevBullish = _prevSmoothedClose > _prevSmoothedOpen;
				var currBullish = smoothedClose > smoothedOpen;

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					_prevSmoothedOpen = smoothedOpen;
					_prevSmoothedClose = smoothedClose;
					return;
				}

				// Buy on transition to bullish smoothed candle
				if (currBullish && !prevBullish && candle.ClosePrice > emaValue && Position <= 0)
				{
					BuyMarket();
				}
				// Sell on transition to bearish smoothed candle
				else if (!currBullish && prevBullish && candle.ClosePrice < emaValue && Position >= 0)
				{
					SellMarket();
				}

				_prevSmoothedOpen = smoothedOpen;
				_prevSmoothedClose = smoothedClose;
			})
			.Start();

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