Ver en GitHub

Estrategia de Rompimiento de Niveles de Vela Anterior

Descripción general

Esta estrategia reproduce el asesor experto de MetaTrader "Previous Candle Breakdown". Espera a que el precio rompa por encima o por debajo de la vela de referencia anterior con una sangría configurable medida en pasos de precio. La implementación se basa en las APIs de alto nivel de StockSharp con suscripciones de velas para cálculos de niveles y suscripciones de ticks para decisiones de ejecución.

Lógica de trading

  1. Al cierre de cada vela de referencia (4 horas por defecto), la estrategia almacena el máximo y mínimo de la vela anterior y los desplaza por IndentSteps * Security.PriceStep para construir niveles de ruptura.
  2. Se monitorizan los precios de tick (últimas operaciones). Una entrada larga se activa cuando el precio alcanza el nivel superior y una entrada corta cuando el precio cae por el nivel inferior.
  3. Un filtro de media móvil opcional requiere que la MA rápida (con desplazamiento opcional hacia adelante) se mantenga por encima de la MA lenta para las operaciones largas y por debajo para las cortas. Establecer cualquier período de MA a cero deshabilita el filtro.
  4. Las operaciones solo se permiten dentro de la ventana de sesión configurada entre StartTime y EndTime. Se admiten sesiones que cruzan la medianoche.
  5. La ganancia flotante se monitorea continuamente: los stops, objetivos y reglas de trailing cierran posiciones existentes antes de que una señal de ruptura pueda activar reversiones.

Gestión de riesgo

  • StopLossSteps / TakeProfitSteps — distancias en pasos de precio desde el precio de entrada. Los pasos se convierten mediante distance = steps * Security.PriceStep.
  • TrailingStopSteps / TrailingStepSteps — habilita una salida de trailing una vez que la posición se mueve a favor al menos la distancia de trailing. El stop se mueve más solo cuando la ganancia avanza por el paso de trailing.
  • ProfitClose — cierra todas las posiciones una vez que la ganancia no realizada (Position * (último precio - PositionPrice)) supera el umbral. Establecer a 0 para deshabilitar.
  • MaxNetPosition — limita la posición neta absoluta para que la estrategia no pueda piramidarse más allá de esa cantidad. El tamaño de la posición en sí se controla por la propiedad Volume de la estrategia.

Parámetros

Parámetro Descripción
CandleType Marco temporal de referencia usado para calcular los niveles de ruptura.
IndentSteps Desplazamiento por encima/debajo del máximo/mínimo de la vela anterior expresado en pasos de precio.
FastMaPeriod / FastMaShift Longitud de la media móvil rápida y desplazamiento hacia adelante opcional (barras).
SlowMaPeriod / SlowMaShift Longitud de la media móvil lenta y desplazamiento hacia adelante opcional (barras).
StopLossSteps Distancia de stop loss en pasos de precio.
TakeProfitSteps Distancia de take profit en pasos de precio.
TrailingStopSteps Distancia del trailing stop (0 deshabilita el trailing).
TrailingStepSteps Ganancia mínima requerida antes de que el trailing stop avance. Debe ser > 0 cuando se use trailing.
ProfitClose Objetivo de ganancia flotante que cierra todas las posiciones.
MaxNetPosition Posición neta absoluta máxima permitida.
StartTime / EndTime Límites de la ventana de trading.

Notas de uso

  • Establezca la propiedad Volume de la instancia de estrategia para controlar el tamaño de la orden. El dimensionamiento de posición basado en riesgo de la versión de MetaTrader no está portado intencionalmente.
  • Las medias móviles usan medias móviles simples (SMA). Si se requieren otros modos de suavizado, extienda la estrategia en consecuencia.
  • El umbral de cierre por ganancia usa la ganancia no realizada en unidades de precio del instrumento (cantidad × diferencia de precio). Ajuste el umbral para que coincida con su instrumento.
  • La estrategia opera en un entorno de netting; las operaciones de reversión envían órdenes de mercado en la dirección opuesta, cerrando automáticamente primero la exposición actual.
  • El trailing stop requiere un valor positivo de TrailingStepSteps; de lo contrario, la estrategia lanza una excepción durante el inicio.

Diferencias con la versión MQL original

  • La gestión de dinero basada en lotes fijos o porcentaje de riesgo no está implementada; los usuarios de StockSharp deben gestionar el tamaño a través de la propiedad Volume o gestores de portafolio externos.
  • Solo se admiten medias móviles simples; el original permitía diferentes tipos de MA.
  • La lógica de cierre por ganancia usa el PnL flotante calculado desde el precio promedio de posición en lugar de moneda de cuenta, porque los datos específicos de swap/comisión del bróker no están disponibles directamente.
  • El registro es manejado por StockSharp; los mensajes detallados de resultado de operaciones de MetaTrader se omiten.
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;
	}
}