Ver no GitHub

Estratégia de Rompimento dos Níveis da Vela Anterior

Visão geral

Esta estratégia reproduz o consultor especialista MetaTrader "Previous Candle Breakdown". Ela aguarda o preço romper acima ou abaixo da vela de referência anterior com um recuo configurável medido em passos de preço. A implementação depende das APIs de alto nível do StockSharp com assinaturas de velas para cálculos de níveis e assinaturas de ticks para decisões de execução.

Lógica de negociação

  1. Ao fechamento de cada vela de referência (padrão de 4 horas), a estratégia armazena o máximo e mínimo da vela anterior e os desloca por IndentSteps * Security.PriceStep para construir níveis de rompimento.
  2. Os preços de tick (últimas negociações) são monitorados. Uma entrada comprada é acionada quando o preço atinge o nível superior e uma entrada vendida quando o preço cai pelo nível inferior.
  3. Um filtro de média móvel opcional requer que a MA rápida (com deslocamento opcional para frente) permaneça acima da MA lenta para negociações compradas e abaixo para vendidas. Definir qualquer período de MA como zero desabilita o filtro.
  4. As negociações são permitidas apenas dentro da janela de sessão configurada entre StartTime e EndTime. Sessões que cruzam meia-noite são suportadas.
  5. O lucro flutuante é monitorado continuamente: stops, alvos e regras de trailing fecham posições existentes antes que um sinal de rompimento possa acionar reversões.

Gestão de risco

  • StopLossSteps / TakeProfitSteps — distâncias em passos de preço do preço de entrada. Os passos são convertidos via distance = steps * Security.PriceStep.
  • TrailingStopSteps / TrailingStepSteps — habilita uma saída de trailing depois que a posição se move a favor em pelo menos a distância de trailing. O stop é movido mais somente quando o lucro avança pelo passo de trailing.
  • ProfitClose — fecha todas as posições assim que o lucro não realizado (Position * (último preço - PositionPrice)) excede o limiar. Definir como 0 para desabilitar.
  • MaxNetPosition — limita a posição líquida absoluta para que a estratégia não possa fazer pirâmide além dessa quantidade. O tamanho da posição em si é controlado pela propriedade Volume da estratégia.

Parâmetros

Parâmetro Descrição
CandleType Período de referência usado para calcular os níveis de rompimento.
IndentSteps Deslocamento acima/abaixo do máximo/mínimo da vela anterior expresso em passos de preço.
FastMaPeriod / FastMaShift Comprimento da MA rápida e deslocamento opcional para frente (barras).
SlowMaPeriod / SlowMaShift Comprimento da MA lenta e deslocamento opcional para frente (barras).
StopLossSteps Distância de stop loss em passos de preço.
TakeProfitSteps Distância de take profit em passos de preço.
TrailingStopSteps Distância do trailing stop (0 desabilita o trailing).
TrailingStepSteps Ganho mínimo necessário antes que o trailing stop avance. Deve ser > 0 quando o trailing estiver em uso.
ProfitClose Alvo de lucro flutuante que fecha todas as posições.
MaxNetPosition Posição líquida absoluta máxima permitida.
StartTime / EndTime Limites da janela de negociação.

Notas de uso

  • Defina a propriedade Volume da instância de estratégia para controlar o tamanho da ordem. O dimensionamento de posição baseado em risco da versão MetaTrader não está portado intencionalmente.
  • As médias móveis usam médias móveis simples (SMA). Se outros modos de suavização forem necessários, estenda a estratégia adequadamente.
  • O limiar de fechamento por lucro usa o PnL não realizado calculado a partir do preço médio de posição em vez da moeda da conta, porque dados específicos de swap/comissão do broker não estão disponíveis diretamente.
  • A estratégia opera em um ambiente de netting; as negociações de reversão enviam ordens de mercado na direção oposta, fechando automaticamente a exposição atual primeiro.
  • O trailing stop requer um valor positivo de TrailingStepSteps; caso contrário, a estratégia lança uma exceção durante a inicialização.

Diferenças da versão MQL original

  • O gerenciamento de dinheiro baseado em lotes fixos ou porcentagem de risco não está implementado; os usuários do StockSharp devem gerenciar o tamanho através da propriedade Volume ou gestores de portfólio externos.
  • Apenas médias móveis simples são suportadas; o original permitia diferentes tipos de MA.
  • A lógica de fechamento por lucro usa o PnL flutuante calculado a partir do preço médio de posição em vez da moeda da conta, porque dados específicos de swap/comissão do broker não estão diretamente disponíveis.
  • O log é tratado pelo StockSharp; mensagens detalhadas de resultado de negociação do MetaTrader são omitidas.
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 PreviousCandleBreakdownLevelsStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private decimal? _prevHigh, _prevLow;

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

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

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevHigh = null; _prevLow = null;
		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { 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()) { _prevHigh = candle.HighPrice; _prevLow = candle.LowPrice; return; }
		if (_prevHigh == null) { _prevHigh = candle.HighPrice; _prevLow = candle.LowPrice; return; }
		var close = candle.ClosePrice;
		if (fast > slow && close > _prevHigh.Value && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (fast < slow && close < _prevLow.Value && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevHigh = candle.HighPrice; _prevLow = candle.LowPrice;
	}
}