The Eugene Inside Breakout strategy is a direct port of the original MetaTrader expert by barabashkakvn. It focuses on pure price
action: an inside candle sequence followed by a range breakout. Confirmation levels derived from the previous candle body ensure
that the breakout develops momentum before the strategy takes a position.
Overview
The strategy watches for a fresh high or low relative to the previous candle. Long setups require that the prior candle has a lo
w below the high of the candle before it, highlighting compression before the breakout. Short setups refuse to trade if the prev
ious candle is an inside bar, mirroring the safeguards in the source MQL logic. Orders are always executed at market with a fixe
d volume.
Market Logic
Emphasises breakouts of the most recent high/low to catch directional moves early.
Uses the prior candle body to compute two one-third retracement levels (zigLevelBuy and zigLevelSell). The price must touch
these levels, or the session must be past the configured activation hour, before an entry is allowed.
Prevents new positions when a breakout coincides with an inside candle against the trade direction.
Closes open positions whenever the opposite breakout signal confirms, ensuring the strategy is always flat or aligned with the
latest signal.
Entry Rules
Long
Current candle high is greater than the previous candle high.
Confirmation is received when the current low pierces the one-third retracement of the prior candle body, or the current hour
is beyond the activation hour parameter.
The current low must stay above the prior low while the prior low sits below the high from two candles ago.
No existing position is open.
Short
Current candle low is lower than the previous candle low.
Confirmation is received when the current high tests the upper one-third retracement of the prior candle body, or the current
hour is beyond the activation hour parameter.
The previous candle must not be an inside bar.
The current high must be below the prior high.
No existing position is open.
Exit Rules
Close long positions when a validated short breakout forms (conditions 1–3 of the short entry logic).
Close short positions when a validated long breakout forms (conditions 1–3 of the long entry logic).
Parameters
Name
Description
Default
CandleType
Time frame of the candles processed by the strategy.
1-hour candles
Volume
Order size sent with each market order.
0.1
ActivationHour
Hour of day after which confirmations are automatically accepted, replicating the TimeCurrent() filter fro
m the MQL code.
8
Notes
The confirmation checks labelled “white bird” and “black bird” in the original script always evaluate to false because of the
source conditions; they are preserved for parity but do not affect trading decisions.
No additional indicators or trailing stops are used—the approach is purely price-based and flips positions on each opposite br
eakout.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Breakout strategy derived from the Eugene expert advisor.
/// </summary>
public class EugeneInsideBreakoutStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _activationHour;
private decimal _prevOpen1;
private decimal _prevClose1;
private decimal _prevHigh1;
private decimal _prevLow1;
private decimal _prevOpen2;
private decimal _prevClose2;
private decimal _prevHigh2;
private decimal _prevLow2;
private bool _hasPrev1;
private bool _hasPrev2;
/// <summary>
/// Candle type to process.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Hour of day after which confirmations are automatically valid.
/// </summary>
public int ActivationHour
{
get => _activationHour.Value;
set => _activationHour.Value = value;
}
/// <summary>
/// Initializes <see cref="EugeneInsideBreakoutStrategy"/>.
/// </summary>
public EugeneInsideBreakoutStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to process", "General");
_activationHour = Param(nameof(ActivationHour), 8)
.SetRange(0, 23)
.SetDisplay("Activation Hour", "Hour when confirmations become unconditional", "Filters");
ResetHistory();
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
ResetHistory();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev2)
{
UpdateHistory(candle);
return;
}
var open1 = _prevOpen1;
var close1 = _prevClose1;
var open2 = _prevOpen2;
var close2 = _prevClose2;
var high0 = candle.HighPrice;
var high1 = _prevHigh1;
var high2 = _prevHigh2;
var low0 = candle.LowPrice;
var low1 = _prevLow1;
var low2 = _prevLow2;
// Replicate the original expert advisor checks for inside bars.
var blackInsider = high1 <= high2 && low1 >= low2 && close1 <= open1;
var whiteInsider = high1 <= high2 && low1 >= low2 && close1 > open1;
var whiteBird = whiteInsider && close2 > open2;
var blackBird = blackInsider && close2 < open2;
// ZigZag style confirmation levels based on the previous candle body.
var zigLevelBuy = close1 < open1
? open1 - (close1 - open1) / 3m
: open1 - (open1 - low1) / 3m;
var zigLevelSell = close1 > open1
? open1 + (close1 - open1) / 3m
: open1 + (high1 - open1) / 3m;
var confirmBuy = (low0 <= zigLevelBuy || candle.CloseTime.Hour >= ActivationHour) && !blackBird && !whiteInsider;
var confirmSell = (high0 >= zigLevelSell || candle.CloseTime.Hour >= ActivationHour) && !whiteBird && !blackInsider;
var buySignal = high0 > high1;
var sellSignal = low0 < low1;
if (Position == 0)
{
if (buySignal && confirmBuy && low0 > low1 && low1 < high2)
{
BuyMarket();
}
else if (sellSignal && confirmSell && high0 < high1)
{
SellMarket();
}
}
else if (Position > 0)
{
if (sellSignal && confirmSell && high0 < high1)
SellMarket();
}
else if (Position < 0)
{
if (buySignal && confirmBuy && low0 > low1 && low1 < high2)
BuyMarket();
}
UpdateHistory(candle);
}
private void UpdateHistory(ICandleMessage candle)
{
// Keep the two most recent completed candles for decision making.
_prevOpen2 = _prevOpen1;
_prevClose2 = _prevClose1;
_prevHigh2 = _prevHigh1;
_prevLow2 = _prevLow1;
_hasPrev2 = _hasPrev1;
_prevOpen1 = candle.OpenPrice;
_prevClose1 = candle.ClosePrice;
_prevHigh1 = candle.HighPrice;
_prevLow1 = candle.LowPrice;
_hasPrev1 = true;
}
private void ResetHistory()
{
_prevOpen1 = default;
_prevClose1 = default;
_prevHigh1 = default;
_prevLow1 = default;
_prevOpen2 = default;
_prevClose2 = default;
_prevHigh2 = default;
_prevLow2 = default;
_hasPrev1 = false;
_hasPrev2 = false;
}
}
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.Strategies import Strategy
class eugene_inside_breakout_strategy(Strategy):
"""
Breakout strategy derived from the Eugene expert advisor.
Detects inside bars and trades breakouts with zigzag confirmation.
"""
def __init__(self):
super(eugene_inside_breakout_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._activation_hour = self.Param("ActivationHour", 8) \
.SetDisplay("Activation Hour", "Hour when confirmations become unconditional", "Filters")
self._prev_open1 = 0.0
self._prev_close1 = 0.0
self._prev_high1 = 0.0
self._prev_low1 = 0.0
self._prev_open2 = 0.0
self._prev_close2 = 0.0
self._prev_high2 = 0.0
self._prev_low2 = 0.0
self._has_prev1 = False
self._has_prev2 = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(eugene_inside_breakout_strategy, self).OnReseted()
self._reset_history()
def OnStarted2(self, time):
super(eugene_inside_breakout_strategy, self).OnStarted2(time)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
if not self._has_prev2:
self._update_history(candle)
return
high0 = float(candle.HighPrice)
low0 = float(candle.LowPrice)
close0 = float(candle.ClosePrice)
open1 = self._prev_open1
close1 = self._prev_close1
high1 = self._prev_high1
low1 = self._prev_low1
open2 = self._prev_open2
close2 = self._prev_close2
high2 = self._prev_high2
low2 = self._prev_low2
black_insider = high1 <= high2 and low1 >= low2 and close1 <= open1
white_insider = high1 <= high2 and low1 >= low2 and close1 > open1
white_bird = white_insider and close2 > open2
black_bird = black_insider and close2 < open2
if close1 < open1:
zig_level_buy = open1 - (close1 - open1) / 3.0
else:
zig_level_buy = open1 - (open1 - low1) / 3.0
if close1 > open1:
zig_level_sell = open1 + (close1 - open1) / 3.0
else:
zig_level_sell = open1 + (high1 - open1) / 3.0
hour = candle.CloseTime.Hour
confirm_buy = (low0 <= zig_level_buy or hour >= self._activation_hour.Value) and not black_bird and not white_insider
confirm_sell = (high0 >= zig_level_sell or hour >= self._activation_hour.Value) and not white_bird and not black_insider
buy_signal = high0 > high1
sell_signal = low0 < low1
if self.Position == 0:
if buy_signal and confirm_buy and low0 > low1 and low1 < high2:
self.BuyMarket()
elif sell_signal and confirm_sell and high0 < high1:
self.SellMarket()
elif self.Position > 0:
if sell_signal and confirm_sell and high0 < high1:
self.SellMarket()
elif self.Position < 0:
if buy_signal and confirm_buy and low0 > low1 and low1 < high2:
self.BuyMarket()
self._update_history(candle)
def _update_history(self, candle):
self._prev_open2 = self._prev_open1
self._prev_close2 = self._prev_close1
self._prev_high2 = self._prev_high1
self._prev_low2 = self._prev_low1
self._has_prev2 = self._has_prev1
self._prev_open1 = float(candle.OpenPrice)
self._prev_close1 = float(candle.ClosePrice)
self._prev_high1 = float(candle.HighPrice)
self._prev_low1 = float(candle.LowPrice)
self._has_prev1 = True
def _reset_history(self):
self._prev_open1 = 0.0
self._prev_close1 = 0.0
self._prev_high1 = 0.0
self._prev_low1 = 0.0
self._prev_open2 = 0.0
self._prev_close2 = 0.0
self._prev_high2 = 0.0
self._prev_low2 = 0.0
self._has_prev1 = False
self._has_prev2 = False
def CreateClone(self):
return eugene_inside_breakout_strategy()