La estrategia MultiBreakout V001k reproduce el clásico asesor experto MT4 "Multibreakout_v001k". Opera con rupturas de la sesión horaria anterior acumulando órdenes de compra y venta una vez finalizada la hora de referencia. La gestión de posiciones sigue la lógica original de obtención de beneficios y equilibrio por etapas, incluido el equilibrio móvil opcional que rastrea las paradas utilizando los últimos máximos y mínimos horarios.
Reglas de trading
Hora de referencia – Se pueden definir hasta cuatro sesiones de negociación. Después de que se cierra cada hora de sesión habilitada, la estrategia mide la vela horaria terminada y prepara órdenes para la siguiente hora.
Ubicación de entrada –
Las órdenes de stop de compra se colocan en el máximo de la hora anterior más el diferencial actual y un colchón de entrada adicional (PipsForEntry).
Las órdenes Sell-Stop se colocan en el mínimo de la hora anterior menos el colchón de entrada.
Cada lado coloca NumberOfOrdersPerSide órdenes pendientes con volumen idéntico.
Escalera de obtención de beneficios: cada entrada recibe un objetivo de beneficio individual espaciado por TakeProfitIncrement puntos. Cuando el mercado toca cada nivel, la estrategia cierra un tramo en el mercado para imitar la cola de obtención de beneficios original de MT4.
Gestión de stop-loss: se establece un stop inicial a StopLoss puntos del precio de entrada. Una vez que el precio se mueve BreakEven puntos a favor, el stop salta al punto de equilibrio. Si MovingBreakEven está habilitado y pasa el retraso configurado, la parada sigue utilizando los mínimos horarios más recientes (para largos) o máximos (para cortos) cuando esos niveles continúan apretándose.
Salida de la sesión: a las ExitMinute dentro de la hora de la sesión configurada, la estrategia cierra por completo todas las posiciones y elimina todas las órdenes pendientes.
Parámetros
Parámetro
Descripción
TradeVolume
Volumen para cada orden de ruptura.
NumberOfOrdersPerSide
Cantidad de órdenes pendientes apiladas para ambas direcciones.
TakeProfitIncrement
Distancia (en puntos) entre objetivos de obtención de beneficios consecutivos.
PipsForEntry
Se agregaron puntos adicionales al disparador de ruptura por encima/por debajo del rango de la sesión.
StopLoss
Distancia de parada inicial desde el precio de entrada.
BreakEven
Beneficio (en puntos) requerido antes de que el stop llegue al punto de equilibrio.
MovingBreakEven
Habilita la lógica móvil de seguimiento del punto de equilibrio.
MovingBreakEvenHoursToStart
Retraso (en horas) después de la sesión de referencia antes de que el punto de equilibrio móvil pueda retroceder.
BrokerOffsetToGmt
Desfase horario entre la hora del corredor y el GMT utilizado por el programador de equilibrio móvil.
TradeSession1..4
Alterna para las cuatro sesiones de negociación independientes.
SessionHour1..4
Hora (0-23) que define cada sesión de referencia.
ExitMinute
Minuto dentro de la hora de sesión para liquidar posiciones y cancelar órdenes.
CandleType
Tipo de vela utilizado para medir la hora de referencia (el valor predeterminado es velas de 1 hora).
Notas de uso
Asegúrese de que el instrumento tenga un PriceStep válido para que los cálculos del valor en puntos coincidan con la versión MT4.
La estrategia supone que los tiempos de los corredores están alineados con las marcas de tiempo de las velas. Ajuste BrokerOffsetToGmt cuando históricamente se haya utilizado un desplazamiento de servidor MT4 diferente.
El punto de equilibrio móvil evalúa las dos últimas velas horarias terminadas antes de apretar el tope, igualando el comportamiento del asesor experto original.
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>
/// Multi-breakout strategy - Highest/Lowest channel breakout.
/// Buys when price breaks above the channel high, sells when below channel low.
/// Reverses position on opposite breakout.
/// </summary>
public class MultiBreakoutV001kStrategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevHigh;
private decimal _prevLow;
private bool _hasPrev;
public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MultiBreakoutV001kStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 20)
.SetDisplay("Channel Period", "Lookback for breakout channel", "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();
_prevClose = 0m;
_prevHigh = 0m;
_prevLow = 0m;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
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 high, decimal low)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var mid = (high + low) / 2m;
if (!_hasPrev)
{
_prevClose = close;
_prevHigh = mid;
_prevLow = mid;
_hasPrev = true;
return;
}
// Cross above midpoint - go long
if (_prevClose <= _prevHigh && close > mid && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Cross below midpoint - go short
else if (_prevClose >= _prevLow && close < mid && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevClose = close;
_prevHigh = mid;
_prevLow = 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, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class multi_breakout_v001k_strategy(Strategy):
"""Multi-breakout strategy using Highest/Lowest channel midpoint crossover.
Buys when price crosses above midpoint, sells when below."""
def __init__(self):
super(multi_breakout_v001k_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 20) \
.SetDisplay("Channel Period", "Lookback for breakout channel", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_close = 0.0
self._prev_mid = 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 ChannelPeriod(self):
return self._channel_period.Value
def OnReseted(self):
super(multi_breakout_v001k_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(multi_breakout_v001k_strategy, self).OnStarted2(time)
self._has_prev = False
highest = Highest()
highest.Length = self.ChannelPeriod
lowest = Lowest()
lowest.Length = self.ChannelPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(highest, lowest, self._process_candle).Start()
def _process_candle(self, candle, high, low):
if candle.State != CandleStates.Finished:
return
high_val = float(high)
low_val = float(low)
close = float(candle.ClosePrice)
mid = (high_val + low_val) / 2.0
if not self._has_prev:
self._prev_close = close
self._prev_mid = mid
self._has_prev = True
return
# Cross above midpoint - go long
if self._prev_close <= self._prev_mid and close > mid and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Cross below midpoint - go short
elif self._prev_close >= self._prev_mid and close < mid and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_mid = mid
def CreateClone(self):
return multi_breakout_v001k_strategy()