Ver en GitHub

Estrategia de ruptura de piso TCPivotStop

Descripción general

La Estrategia TCPivotStop Floor Breakout es una adaptación directa del MetaTrader asesor experto gpfTCPivotStop. La lógica gira en torno cálculos clásicos de pivote del piso realizados el día de negociación anterior. Al inicio de cada nueva sesión diaria la estrategia:

  1. Agrega el máximo, el mínimo y el cierre del día anterior para calcular el punto de pivote más los primeros tres niveles de soporte y resistencia.
  2. Comprueba si la última barra horaria completada cruzó el pivote desde arriba o desde abajo.
  3. Abre una orden de mercado en la dirección del cruce mientras fija niveles de stop-loss y take-profit que reflejan el comportamiento del experto original.

Sólo puede haber una posición activa a la vez. La gestión de sesiones opcional permite aplanar la exposición cuando comienza un nuevo día.

Reglas de trading

  • Período de tiempo: diseñado para velas de 1 hora (configurable).
  • Cálculo de pivote: utiliza el máximo, el mínimo y el cierre del día anterior para calcular Pivot, R1, R2, R3, S1, S2, S3.
  • Condiciones de entrada
    • Ingrese short cuando la última barra completada se cerró por debajo del pivote mientras que la barra anterior se cerró por encima de él.
    • Ingrese long cuando la última barra completada se cerró por encima del pivote mientras que la barra anterior se cerró por debajo de él.
  • Tamaño de posición: tamaño de lote fijo definido por el parámetro OrderVolume.
  • Condiciones de salida
    • Los precios de stop-loss y take-profit se asignan a los niveles de pivote clásicos.
    • Si el indicador CloseAtSessionEnd está habilitado, la estrategia liquida las operaciones abiertas antes de que comience la siguiente sesión.
    • Los niveles de protección se monitorean en los máximos y mínimos de las velas y se ejecutan con órdenes de mercado cuando se tocan.

Parámetros

Nombre Descripción Predeterminado
OrderVolume Tamaño de la operación para las entradas al mercado. 0.1
TakeProfitTarget Elige qué nivel dinámico actúa como objetivo de ganancias (1 = más cercano, 3 = más lejano). 1
CloseAtSessionEnd Cierre cualquier posición abierta una vez que comience una nueva sesión diaria. false
CandleType Periodo utilizado para todos los cálculos (por hora por defecto). H1

Notas

  • La estrategia ejecuta órdenes solo una vez al día cuando hay un nuevo conjunto de pivote disponible, al igual que la fuente EA que se activa en el primer tick de la sesión diaria.
  • La versión MetaTrader recalculó los tamaños de lote utilizando el historial de márgenes de la cuenta. Este puerto mantiene el tamaño de la posición fijo y delega la gestión del dinero a otros componentes si es necesario.
  • Las órdenes de protección se emulan monitoreando los extremos de las velas y enviando órdenes de mercado una vez que se cruza un umbral.

Archivos

  • CS/TcpFloorPivotBreakoutStrategy.cs – Implementación en C# de la lógica comercial.
  • README.md – Documentación en inglés (este archivo).
  • README_zh.md – Traducción al chino simplificado.
  • README_ru.md – traducción al ruso.
using System;

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

namespace StockSharp.Samples.Strategies;

public class TcpFloorPivotBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _channelPeriod;
	private readonly StrategyParam<int> _cooldownCandles;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevMid;
	private bool _hasPrev;
	private int _cooldownRemaining;

	public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
	public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public TcpFloorPivotBreakoutStrategy()
	{
		_channelPeriod = Param(nameof(ChannelPeriod), 48).SetDisplay("Channel Period", "Channel lookback", "Indicators");
		_cooldownCandles = Param(nameof(CooldownCandles), 150).SetDisplay("Cooldown", "Candles between signals", "General");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = default;
		_prevMid = default;
		_hasPrev = default;
		_cooldownRemaining = default;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = 0;
		_prevMid = 0;
		_hasPrev = false;
		_cooldownRemaining = 0;

		var highest = new Highest { Length = ChannelPeriod };
		var lowest = new Lowest { Length = ChannelPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(highest, lowest, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		var mid = (highest + lowest) / 2;
		if (!_hasPrev) { _prevClose = close; _prevMid = mid; _hasPrev = true; return; }

		if (_cooldownRemaining > 0)
		{
			_cooldownRemaining--;
			_prevClose = close;
			_prevMid = mid;
			return;
		}

		if (_prevClose <= _prevMid && close > mid && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_cooldownRemaining = CooldownCandles;
		}
		else if (_prevClose >= _prevMid && close < mid && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_cooldownRemaining = CooldownCandles;
		}
		_prevClose = close;
		_prevMid = mid;
	}
}