Ver no GitHub

Estratégia de envelopes modelo M5

Convertido do consultor especialista MetaTrader 4 "Template_M5_Envelopes.mq4". A estratégia rastreia um envelope de média móvel ponderada linear (LWMA) em velas de cinco minutos e ordens de stop de rompimento de armas sempre que o preço se afasta o suficiente do canal. As ordens pendentes são reavaliadas dinamicamente para acompanhar o mercado, e as posições preenchidas são protegidas por lógica configurável de stop-loss, take-profit e trailing-stop.

Lógica de negociação

  1. Um LWMA baseado no preço médio da vela é calculado com o EnvelopePeriod configurado. As faixas superior e inferior do envelope são derivadas aplicando-se a porcentagem EnvelopeDeviation.
  2. Cada vela finalizada de cinco minutos armazena seus valores de envelope junto com a máxima e a mínima. Os sinais só são avaliados quando um conjunto completo de valores "anteriores" estiver disponível, correspondendo à implementação MetaTrader que referenciou iEnvelopes(..., shift = 1) e a barra anterior.
  3. Uma configuração de compra aparece quando:
    • A mínima da vela anterior fica pelo menos DistancePoints abaixo do envelope inferior anterior, e
    • O preço de oferta atual permanece pelo menos DistancePoints abaixo do mesmo valor do envelope.
  4. Uma configuração de venda reflete a lógica com a máxima anterior e o envelope superior.
  5. Quando uma configuração está ativa, apenas uma ordem stop é permitida (o EA original também se restringiu a um único mercado ou ordem pendente). O pedido é feito na oferta/oferta atual mais a distância de EntryOffsetPoints.
  6. Enquanto a ordem pendente permanece ativa, a estratégia monitora o mercado. Se a diferença entre o preço da ordem e o preço de compra/venda atual exceder EntryOffsetPoints + SlippagePoints, a ordem é cancelada e imediatamente registrada novamente no novo preço de referência, mantendo o stop-loss e o take-profit anexados alinhados com as compensações desejadas.
  7. Se o spread atual exceder MaxSpreadPoints, todas as entradas pendentes serão canceladas para evitar negociações em condições de liquidez desfavoráveis.

Gerenciamento de pedidos

  • Após a ativação da ordem de entrada, a estratégia registra o preço de execução e registra ordens de proteção stop e take-profit em compensações de StopLossPoints e TakeProfitPoints, respectivamente. Se um dos valores for zero, a proteção correspondente será ignorada.
  • O módulo de trailing stop (habilitado com UseTrailingStop) rastreia o melhor lance/venda. Sempre que o preço se move a favor da posição aberta em mais de TrailingStopPoints, a ordem stop é reavaliada mais perto do mercado usando ReRegisterOrder. As paradas longas apenas seguem para cima, enquanto as paradas curtas apenas seguem para baixo.
  • Quando a posição estiver totalmente fechada, todas as ordens de proteção serão canceladas e o estado interno será redefinido. Nenhuma nova ordem de entrada será considerada até que a posição retorne à estabilidade.

Parâmetros

Parâmetro Descrição
MaxSpreadPoints Spread máximo permitido antes do cancelamento de ordens pendentes.
TakeProfitPoints Distância de take-profit aplicada às posições preenchidas.
StopLossPoints Distância de stop-loss aplicada a posições pendentes e preenchidas.
EntryOffsetPoints Compensação (em pontos) do bid/ask onde as entradas stop são colocadas.
UseTrailingStop Permite o gerenciamento de trailing stop para posições abertas.
TrailingStopPoints Distância (em pontos) mantida pelo trailing stop.
FixedVolume Volume de negociação enviado com cada ordem de entrada.
EnvelopePeriod Comprimento do LWMA usado como base do envelope.
EnvelopeDeviation Largura do envelope em porcentagem.
DistancePoints Diferença mínima entre preço e envelope necessária para um sinal.
SlippagePoints Tolerância extra (em pontos) adicionada ao limite de reprecificação.
CandleType Prazo usado para calcular o envelope LWMA (padrão M5).

Notas

  • A estratégia assina velas e cotações de nível 1. Se os dados de compra/venda não estiverem disponíveis, as condições de entrada não serão acionadas porque os cálculos de spread e trailing stop dependem disso.
  • As ordens protetoras de stop e take-profit são recriadas com o volume mais recente sempre que a lógica móvel ajusta o preço do stop-loss.
  • Todos os comentários dentro do código são escritos em inglês e tabulações são usadas para recuo para corresponder às convenções do projeto.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Template M5 Envelopes strategy: WMA envelope breakout.
/// Buys above upper envelope, sells below lower envelope.
/// </summary>
public class TemplateM5EnvelopesStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _wmaPeriod;
	private readonly StrategyParam<decimal> _deviation;
	private bool _wasAboveUpper;
	private bool _wasBelowLower;
	private bool _hasPrevSignal;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int WmaPeriod { get => _wmaPeriod.Value; set => _wmaPeriod.Value = value; }
	public decimal Deviation { get => _deviation.Value; set => _deviation.Value = value; }

	public TemplateM5EnvelopesStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_wmaPeriod = Param(nameof(WmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("WMA Period", "Weighted MA period", "Indicators");
		_deviation = Param(nameof(Deviation), 0.3m)
			.SetDisplay("Deviation %", "Envelope deviation percent", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_wasAboveUpper = false;
		_wasBelowLower = false;
		_hasPrevSignal = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrevSignal = false;
		var wma = new WeightedMovingAverage { Length = WmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(wma, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal wmaValue)
	{
		if (candle.State != CandleStates.Finished) return;

		var close = candle.ClosePrice;
		var upper = wmaValue * (1 + Deviation / 100m);
		var lower = wmaValue * (1 - Deviation / 100m);
		var aboveUpper = close > upper;
		var belowLower = close < lower;

		if (_hasPrevSignal)
		{
			if (aboveUpper && !_wasAboveUpper && Position <= 0)
				BuyMarket();
			else if (belowLower && !_wasBelowLower && Position >= 0)
				SellMarket();
		}

		_wasAboveUpper = aboveUpper;
		_wasBelowLower = belowLower;
		_hasPrevSignal = true;
	}
}