Ver no GitHub

Estratégia Curta Envelope MA

Visão geral

A Envelope MA Short Strategy é uma versão C# do MetaTrader consultor especialista EnvelopeMA.mq4 (ID 9533). Ele recria a lógica original de rompimento curto em velas de 15 minutos, combinando um envelope de média móvel exponencial com dois EMAs adicionais e um trio de filtros Parabolic SAR. A estratégia observa recuos de preço e o EMA rápida na metade inferior do envelope e, em seguida, arma uma ordem de venda pendente pendente no limite inferior do envelope. Quando a ordem é preenchida, ela gerencia a posição curta com níveis fixos de stop-loss e take-profit, bem como regras de saída baseadas em indicadores.

Indicadores e sinais

  • Base do envelope: Média móvel exponencial dos máximos das velas (EnvelopePeriod, padrão 280). A faixa inferior é o gatilho de entrada e é calculada com uma porcentagem de desvio (EnvelopeDeviation, padrão 0,08%).
  • EMA rápida: Média móvel exponencial dos mínimos das velas (FastMaPeriod, padrão 6) usada para confirmar o impulso antes de armar a entrada curta.
  • EMA lenta (deslocado): Média móvel exponencial dos mínimos das velas com atraso de uma barra (SlowMaPeriod, padrão 18). O valor atrasado reflete o parâmetro de deslocamento iMA de MetaTrader e é usado tanto para confirmação de entrada quanto para decisões de saída.
  • Parabolic SAR trio: Três Parabolic SAR instâncias com diferentes fatores de aceleração (0,03/0,5, 0,015/0,6 e 0,02/0,2) que devem ficar acima do preço atual antes que a estratégia permita uma saída baseada em indicadores.

A estratégia espera pelas velas concluídas. Quando o EMA rápida, o lento deslocado EMA e o fechamento da vela permanecem entre os limites do envelope (acima da banda inferior e abaixo da banda superior), ele envia uma ordem de sell-stop na banda inferior do envelope. As ordens pendentes expiram após aproximadamente cinco intervalos de velas se permanecerem não preenchidas.

Gestão comercial

  • Níveis de proteção: Na entrada, a estratégia coloca metas internas de stop-loss e take-profit derivadas das distâncias de pip configuradas. Os movimentos de preços fora da faixa da vela são aproximados usando os valores máximos e mínimos de cada barra finalizada.
  • Saída do indicador: Uma posição curta é fechada antecipadamente quando ambos os EMAs e o fechamento ficam abaixo do preço de entrada, todos os três valores SAR permanecem acima do preço e o EMA rápida cruza de volta acima do lento atrasado EMA – imitando o comportamento MetaTrader.
  • Ajuste de rastreamento: Após pelo menos quatro barras, se a máxima mais alta da vela desde a entrada tiver se movido pelo menos três etapas de preço abaixo do preço de entrada e o fechamento estiver sendo negociado abaixo da banda inferior do envelope, o stop loss será reduzido para essa banda inferior.

Risk controls

  • Proteção de patrimônio: O parâmetro LiquidityThreshold fecha quaisquer posições vendidas abertas e cancela paradas de venda pendentes se a proporção entre o patrimônio do portfólio e o saldo inicial cair abaixo do valor configurado (padrão 0,58).
  • Expiração do pedido: Pedidos pendentes não atendidos são cancelados automaticamente assim que o tempo de vida de cinco barras expirar para evitar sinais obsoletos.

Parâmetros

Nome Descrição Padrão
CandleType Tipo/prazo de vela processado pela estratégia. Período de 15 minutos
EnvelopePeriod Comprimento EMA usado como base do envelope. 280
EnvelopeDeviation Largura do envelope expressa em porcentagem. 0,08
FastMaPeriod Período EMA rápida calculado em mínimos. 6
SlowMaPeriod Período EMA lento (avaliado com um atraso de uma barra). 18
StopLossPips Distância de stop-loss em pips em relação ao preço de entrada. 25
TakeProfitPips Distância de lucro em pips em relação ao preço de entrada. 25
TradeVolume Volume utilizado para ordens pendentes e de mercado. 1
LiquidityThreshold Relação mínima de capital próprio sobre saldo; shorts são liquidados quando violados. 0,58

Notas de conversão

  • O dimensionamento do lote MetaTrader com base no saldo, margem ou contra-pips foi substituído por um parâmetro TradeVolume direto para se ajustar ao modelo de execução StockSharp.
  • O carimbo de data e hora de expiração para pedidos pendentes é tratado dentro do loop de estratégia porque StockSharp pedidos não expõem o mesmo campo de vencimento que MetaTrader.
  • Os níveis de stop-loss e take-profit são avaliados em relação aos máximos e mínimos das velas para aproximar os gatilhos intra-barra, correspondendo ao comportamento do especialista MQL que monitorou os preços nas barras concluídas.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Envelope MA Short: EMA band reversion with ATR stops.
/// </summary>
public class EnvelopeMaShortStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;
	private readonly StrategyParam<decimal> _bandPercent;

	private decimal _entryPrice;

	public EnvelopeMaShortStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_emaLength = Param(nameof(EmaLength), 20)
			.SetDisplay("EMA Length", "EMA period.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
		_bandPercent = Param(nameof(BandPercent), 1.0m)
			.SetDisplay("Band %", "Band width percent.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
	public decimal BandPercent { get => _bandPercent.Value; set => _bandPercent.Value = value; }

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

		_entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_entryPrice = 0;
		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, atr, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (atrVal <= 0 || emaVal <= 0) return;
		var close = candle.ClosePrice;
		var factor = BandPercent / 100m;
		var upper = emaVal * (1m + factor);
		var lower = emaVal * (1m - factor);

		if (Position > 0)
		{
			if (close >= emaVal || close <= _entryPrice - atrVal * 1.5m) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if (close <= emaVal || close >= _entryPrice + atrVal * 1.5m) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (close < lower) { _entryPrice = close; BuyMarket(); }
			else if (close > upper) { _entryPrice = close; SellMarket(); }
		}
	}
}