The MultiBreakout V001k strategy reproduces the classic MT4 expert advisor "Multibreakout_v001k". It trades breakouts from the previous hourly session by stacking buy-stop and sell-stop orders once the reference hour finishes. Position management follows the original staged take-profit and break-even logic, including the optional moving break-even that trails stops using the latest hourly lows/highs.
Trading Rules
Reference hour – Up to four trading sessions can be defined. After each enabled session hour closes, the strategy measures the finished hourly candle and prepares orders for the next hour.
Entry placement –
Buy-stop orders are positioned at the previous hour high plus the current spread and an additional entry buffer (PipsForEntry).
Sell-stop orders are positioned at the previous hour low minus the entry buffer.
Each side places NumberOfOrdersPerSide pending orders with identical volume.
Take-profit ladder – Every entry receives an individual profit target spaced by TakeProfitIncrement points. When the market touches each level, the strategy closes one tranche at market to mimic the original MT4 take-profit queue.
Stop-loss management – An initial stop is set StopLoss points away from the entry price. Once price moves BreakEven points in favour, the stop jumps to break-even. If MovingBreakEven is enabled and the configured delay passes, the stop trails using the most recent hourly lows (for longs) or highs (for shorts) when those levels continue to tighten.
Session exit – At ExitMinute within the configured session hour the strategy flat-out closes all positions and removes every pending order.
Parameters
Parameter
Description
TradeVolume
Volume for each breakout order.
NumberOfOrdersPerSide
Quantity of stacked pending orders for both directions.
TakeProfitIncrement
Distance (in points) between consecutive take-profit targets.
PipsForEntry
Extra points added to the breakout trigger above/below the session range.
StopLoss
Initial stop distance from the entry price.
BreakEven
Profit (in points) required before the stop moves to break-even.
MovingBreakEven
Enables the moving break-even trailing logic.
MovingBreakEvenHoursToStart
Delay (in hours) after the reference session before the moving break-even may trail.
BrokerOffsetToGmt
Hour offset between broker time and GMT used by the moving break-even scheduler.
TradeSession1..4
Toggles for the four independent trading sessions.
SessionHour1..4
Hour (0-23) defining each reference session.
ExitMinute
Minute within the session hour to liquidate positions and cancel orders.
CandleType
Candle type used to measure the reference hour (defaults to 1-hour candles).
Usage Notes
Ensure the instrument has a valid PriceStep so point-value calculations match the MT4 version.
The strategy assumes broker times are aligned with the candle timestamps. Adjust BrokerOffsetToGmt when a different MT4 server offset was used historically.
Moving break-even evaluates the two latest finished hourly candles before tightening the stop, matching the behaviour from the original expert advisor.
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()