Ver en GitHub

Estrategia ZeeZee Level

Descripción general

La estrategia ZeeZee Level replica el comportamiento del asesor experto original de MetaTrader "ZeeZee Level" usando la API de alto nivel de StockSharp. La estrategia analiza oscilaciones ZigZag en el marco temporal seleccionado y opera en la dirección del extremo más reciente. Las distancias de stop loss, take profit y trailing stop de protección se expresan en pips, y el tamaño de posición sigue una progresión de estilo martingala después de operaciones perdedoras.

Lógica de trading

  1. Las velas se suscriben usando el marco temporal definido por CandleType.
  2. Un ZigZagIndicator con parámetros configurables de profundidad, desviación y backstep rastrea máximos y mínimos oscilantes.
  3. Cuando no hay posición abierta, la estrategia compara la recencia del último máximo y mínimo ZigZag confirmados dentro de la ventana ZigZagIdInterval:
    • Si el último máximo oscilante es más reciente que el último mínimo oscilante, se abre una posición corta.
    • Si el último mínimo oscilante es más reciente que el último máximo oscilante, se abre una posición larga.
  4. Se mantiene solo una posición a la vez. El volumen de entrada se redondea al paso de volumen del instrumento.
  5. Después de abrir la posición, se adjuntan niveles de stop loss, take profit y trailing stop opcional usando las distancias en pips configuradas. El trailing stop sigue el precio extremo a medida que la operación se mueve a favor.
  6. Las posiciones se cierran en cuanto se toca el nivel de stop loss o take profit. Cuando ambos niveles se alcanzan en la misma vela, el nivel más cercano al precio de entrada gana el desempate.
  7. Después de cada salida, el volumen se reinicia al valor inicial en operaciones rentables o se multiplica por el factor martingala en operaciones perdedoras.

Parámetros

Parámetro Descripción
ZigZagDepth Número de velas consideradas al buscar nuevos pivotes ZigZag.
ZigZagDeviation Movimiento mínimo de precio (en pasos de precio) requerido para confirmar un nuevo pivote.
ZigZagBackstep Número mínimo de barras antes de que el indicador pueda cambiar de dirección.
ZigZagIdInterval Número máximo de barras usadas para mirar hacia atrás en busca de los últimos máximos y mínimos ZigZag.
StopLossPips Distancia de stop loss en pips. Establecer en cero para desactivar.
TakeProfitPips Distancia de take profit en pips. Establecer en cero para desactivar.
TrailingStopPips Distancia de trailing stop en pips. Establecer en cero para desactivar.
InitialVolume Volumen base de operación usado al inicio de un ciclo martingala.
MartingaleMultiplier Factor aplicado al volumen de la siguiente operación después de una posición perdedora.
CandleType Tipo de vela y marco temporal usado para el análisis.

Gestión monetaria

  • Los volúmenes se alinean con el paso de volumen del instrumento y se limitan entre los límites mínimo y máximo del mercado.
  • Las operaciones ganadoras reinician el volumen a InitialVolume, mientras que las perdedoras lo multiplican por MartingaleMultiplier.

Gestión de riesgos

  • Las distancias de stop loss, take profit y trailing stop se evalúan en cada vela cerrada.
  • El trailing stop se mueve solo en la dirección de la operación y nunca retrocede.
  • El trading se omite mientras la estrategia ya mantiene una posición o mientras las oscilaciones ZigZag no están disponibles dentro del intervalo configurado.

Notas

  • La estrategia usa solo velas cerradas para coincidir con el comportamiento del asesor experto original.
  • Las conversiones de pips dependen del PriceStep del instrumento. Asegúrese de que los metadatos del instrumento estén cargados antes de iniciar la estrategia.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

public class ZeeZeeLevelStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public ZeeZeeLevelStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}