La estrategia de ruptura del Plan X replica el MetaTrader asesor experto "plan x" de Peter Ingram. Se centra en la sesión de última hora de la mañana de Londres y espera a que el precio se separe de una vela de referencia antes de entrar. Sólo se puede abrir una posición neta a la vez, y el riesgo se controla mediante paradas basadas en pips que siguen a la operación a medida que se mueve a favor.
Lógica de trading
Ancla de sesión
La estrategia observa velas de 15 minutos.
A la hora de inicio de sesión configurada (por defecto 11:00), registra el cierre de esa vela. Este cierre actúa como precio ancla para el resto de la sesión.
La negociación solo se considera después de que se haya cerrado al menos una vela adicional y antes de la hora de finalización de la sesión (por defecto, 15:00).
Condiciones de entrada
Largo: cuando la última vela terminada cierra más de LongTargetPips (25 pips predeterminado) por encima del cierre del ancla y no hay ninguna posición abierta.
Corto: Cuando la última vela terminada cierra más de ShortTargetPips (20 pips predeterminado) por debajo del cierre del ancla y no hay ninguna posición abierta.
Todas las comparaciones se realizan en unidades de pips derivadas del tamaño del tick del instrumento.
Gestión de posiciones
Se establece un stop-loss inicial fijo igual a InitialStopPips (25 pips por defecto) en relación con el precio de entrada.
El stop se convierte en un trailing stop una vez que la operación gana al menos TrailTriggerPips (10 pips por defecto).
Cada vez que el precio avanza otro TrailTriggerPips, el stop se mueve TrailStepPips (5 pips predeterminado) más en la dirección rentable.
Si el precio llega al tope, la posición se cierra en el mercado.
Volumen
Los pedidos utilizan el parámetro TradeVolume (por defecto 0,1 lotes). Ajústelo para que coincida con el tamaño del contrato de seguridad.
Parámetros
Nombre
Descripción
Predeterminado
TradeVolume
Volumen de órdenes de mercado utilizado para entradas y salidas.
0.1
LongTargetPips
Distancia de ruptura por encima del ancla requerida para entradas largas.
25
ShortTargetPips
Distancia de ruptura debajo del ancla requerida para entradas cortas.
20
InitialStopPips
Distancia desde el precio de entrada hasta el stop-loss protector.
25
TrailTriggerPips
Ganancia en pips necesarios antes de que se active o avance el trailing stop.
10
TrailStepPips
Incremento de pip aplicado al trailing stop cada vez que se mueve.
5
SessionStartHour
Hora decimal que indica cuándo comienza la vela ancla (por ejemplo, 11.0, 11.5).
11.0
SessionEndHour
Hora decimal a partir de la cual no se realizan nuevas entradas. Debe ser posterior a SessionStartHour.
15.0
CandleType
Serie de velas utilizadas para evaluaciones. El valor predeterminado es velas de 15 minutos.
15 minutos
Notas
El tamaño del pip se adapta automáticamente según el PriceStep y la precisión decimal del instrumento (3 o 5 decimales reciben un multiplicador de 10x).
La estrategia espera un mercado intradiario continuo; en instrumentos con brechas diarias, el comportamiento de reancla ocurre cada día de negociación.
Debido a que las estrategias StockSharp utilizan posiciones netas, la conversión asume solo una dirección abierta a la vez. Esto refleja el comportamiento predeterminado del experto original cuando no hay cobertura activa.
Archivos
CS/PlanXBreakoutStrategy.cs: implementación en C# de la lógica de ruptura del Plan X para StockSharp.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Plan X Breakout strategy using highest high / lowest low channel breakout.
/// Buy when price breaks above the highest high of the lookback period.
/// Sell when price breaks below the lowest low of the lookback period.
/// </summary>
public class PlanXBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _lookback;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevHigh;
private decimal _prevLow;
private bool _hasPrev;
public int Lookback { get => _lookback.Value; set => _lookback.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public PlanXBreakoutStrategy()
{
_lookback = Param(nameof(Lookback), 20)
.SetDisplay("Lookback", "Channel lookback period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = 0m;
_prevLow = 0m;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var highestHigh = new Highest { Length = Lookback };
var lowestLow = new Lowest { Length = Lookback };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highestHigh, lowestLow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevHigh = highest;
_prevLow = lowest;
_hasPrev = true;
return;
}
// Breakout above previous highest high
if (Position <= 0 && candle.ClosePrice > _prevHigh)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Breakout below previous lowest low
else if (Position >= 0 && candle.ClosePrice < _prevLow)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevHigh = highest;
_prevLow = lowest;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class plan_x_breakout_strategy(Strategy):
"""Plan X Breakout strategy using highest high / lowest low channel breakout.
Buy when price breaks above the highest high of the lookback period.
Sell when price breaks below the lowest low of the lookback period."""
def __init__(self):
super(plan_x_breakout_strategy, self).__init__()
self._lookback = self.Param("Lookback", 20) \
.SetDisplay("Lookback", "Channel lookback period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def Lookback(self):
return self._lookback.Value
def OnReseted(self):
super(plan_x_breakout_strategy, self).OnReseted()
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(plan_x_breakout_strategy, self).OnStarted2(time)
self._has_prev = False
highest = Highest()
highest.Length = self.Lookback
lowest = Lowest()
lowest.Length = self.Lookback
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(highest, lowest, self._process_candle).Start()
def _process_candle(self, candle, highest, lowest):
if candle.State != CandleStates.Finished:
return
high_val = float(highest)
low_val = float(lowest)
close = float(candle.ClosePrice)
if not self._has_prev:
self._prev_high = high_val
self._prev_low = low_val
self._has_prev = True
return
# Breakout above previous highest high
if self.Position <= 0 and close > self._prev_high:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Breakout below previous lowest low
elif self.Position >= 0 and close < self._prev_low:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_high = high_val
self._prev_low = low_val
def CreateClone(self):
return plan_x_breakout_strategy()