Ver en GitHub

Estrategia de detención de sesión de TCPivot

Descripción general

La estrategia TCPivot Session Stop es un puerto directo del MetaTrader 4 asesor experto gpfTCPivotStop. Opera alrededor del clásico nivel de pivote diario calculado a partir del día de negociación anterior. La estrategia:

  • Calcula el punto de pivote, tres niveles de resistencia y tres niveles de soporte a partir del máximo, mínimo y cierre del día anterior.
  • Espera a que el cierre actual cruce el nivel de pivote desde abajo (configuración larga) o desde arriba (configuración corta).
  • Abre una posición de mercado en la dirección de la ruptura y asigna un límite de pérdidas y una toma de ganancias en el nivel de pivote seleccionado.
  • Opcionalmente, fuerza el cierre de la posición al comienzo de una hora de sesión específica para emular la salida intradiaria original.

La implementación se basa en el StockSharp nivel alto API. Las posiciones se dimensionan con la propiedad Volume de la clase base Strategy.

Parámetros

Nombre Descripción Predeterminado
TargetLevel Nivel de pivote utilizado para detener pérdidas y obtener ganancias (1, 2 o 3). 1
CloseAtSessionStart Si está habilitado, cierra posiciones abiertas cuando comienza la hora configurada. false
SessionCloseHour Hora de sesión (0-23) evaluada cuando CloseAtSessionStart está habilitado. 0
CandleType Marco de tiempo que alimenta las señales comerciales. H1

Lógica de trading

  1. Suscríbase a velas horarias (o configuradas) para señales y velas diarias para cálculo de pivote.
  2. Al finalizar cada vela diaria, calcule los niveles de pivote clásicos:
    • Pivot = (High + Low + Close) / 3
    • R1 = 2 * Pivot - Low, S1 = 2 * Pivot - High
    • R2 = Pivot + (R1 - S1), S2 = Pivot - (R1 - S1)
    • R3 = High + 2 * (Pivot - Low), S3 = Low - 2 * (High - Pivot)
  3. Cuando termina una vela de señal:
    • Si CloseAtSessionStart está habilitado y la vela se abre en SessionCloseHour, aplana la posición inmediatamente.
    • Si es plano y el cierre anterior estuvo por debajo del pivote mientras que el cierre actual está por encima de él, ingrese largo con el objetivo/parada seleccionado por TargetLevel.
    • Si está plano y el cierre anterior estuvo por encima del pivote mientras que el cierre actual está por debajo de él, entre en corto con el objetivo/stop reflejado.
    • Si ya está en una posición, salga cuando el cierre toque el nivel de stop-loss o take-profit configurado.

Notas

  • La estrategia utiliza StartProtection() para integrarse con los controles de riesgo integrados de la plataforma. Las salidas de stop-loss y take-profit se manejan explícitamente dentro de la lógica de la estrategia.
  • La versión MetaTrader incluía notificaciones por correo electrónico opcionales y un tamaño de posición dinámico basado en el riesgo de la cuenta. Estas funciones no forman parte del puerto StockSharp; utilice los módulos de notificación y administración de dinero de la plataforma si es necesario.
  • El asesor experto original cerró las operaciones a medianoche cuando isTradeDay estaba habilitado. Este comportamiento se reproduce mediante CloseAtSessionStart + SessionCloseHour (establecido en 0 para imitar la medianoche).
using System;



using StockSharp.Algo.Indicators;

using StockSharp.Algo.Strategies;

using StockSharp.BusinessEntities;

using StockSharp.Messages;



namespace StockSharp.Samples.Strategies;



public class TcpPivotSessionStopStrategy : Strategy

{

	private readonly StrategyParam<int> _fastPeriod;

	private readonly StrategyParam<int> _slowPeriod;

	private readonly StrategyParam<DataType> _candleType;



	private decimal _prevFast; private decimal _prevSlow; private bool _hasPrev;

	private int _cooldown;



	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }

	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }



	public TcpPivotSessionStopStrategy()

	{

		_fastPeriod = Param(nameof(FastPeriod), 7).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 21).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");

	}



	/// <inheritdoc />

	protected override void OnReseted()

	{

		base.OnReseted();

		_prevFast = default;

		_prevSlow = default;

		_hasPrev = default;

		_cooldown = default;

	}



	/// <inheritdoc />

	protected override void OnStarted2(DateTime time)

	{

		base.OnStarted2(time);

		_hasPrev = false;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };

		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);

		subscription.Bind(fast, slow, ProcessCandle).Start();

	}



	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)

	{

		if (candle.State != CandleStates.Finished) return;

		if (!IsFormedAndOnlineAndAllowTrading()) return;

		if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }

		if (_cooldown > 0)

		{

			_cooldown--;

			_prevFast = fast; _prevSlow = slow;

			return;

		}



		if (_prevFast <= _prevSlow && fast > slow && Position <= 0)

		{

			var volume = Volume + Math.Abs(Position);

			BuyMarket(volume);

			_cooldown = 2;

		}

		else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)

		{

			var volume = Volume + Math.Abs(Position);

			SellMarket(volume);

			_cooldown = 2;

		}

		_prevFast = fast; _prevSlow = slow;

	}

}