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:
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.
Comprueba si la última barra horaria completada cruzó el pivote desde arriba o desde abajo.
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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class tcp_floor_pivot_breakout_strategy(Strategy):
def __init__(self):
super(tcp_floor_pivot_breakout_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 48).SetDisplay("Channel Period", "Channel lookback", "Indicators")
self._cooldown_candles = self.Param("CooldownCandles", 150).SetDisplay("Cooldown", "Candles between signals", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown_remaining = 0
@property
def channel_period(self): return self._channel_period.Value
@property
def cooldown_candles(self): return self._cooldown_candles.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(tcp_floor_pivot_breakout_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(tcp_floor_pivot_breakout_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown_remaining = 0
highest = Highest()
highest.Length = self.channel_period
lowest = Lowest()
lowest.Length = self.channel_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(highest, lowest, self.process_candle).Start()
def process_candle(self, candle, highest, lowest):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
mid = (float(highest) + float(lowest)) / 2.0
if not self._has_prev:
self._prev_close = close
self._prev_mid = mid
self._has_prev = True
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_close = close
self._prev_mid = mid
return
if self._prev_close <= self._prev_mid and close > mid and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown_remaining = self.cooldown_candles
elif self._prev_close >= self._prev_mid and close < mid and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown_remaining = self.cooldown_candles
self._prev_close = close
self._prev_mid = mid
def CreateClone(self):
return tcp_floor_pivot_breakout_strategy()