Die Eugene Inside-Ausbruch-Strategie ist eine direkte Portierung des ursprünglichen MetaTrader-Expertenberaters von barabashkakvn. Sie konzentriert sich auf reine Price-Action: eine Inside-Kerzen-Sequenz gefolgt von einem Bereichsausbruch. Bestätigungsniveaus aus dem Körper der vorherigen Kerze stellen sicher, dass der Ausbruch Momentum entwickelt, bevor die Strategie eine Position eingeht.
Übersicht
Die Strategie überwacht auf ein frisches Hoch oder Tief relativ zur vorherigen Kerze. Long-Setups erfordern, dass die vorherige Kerze ein Tief unterhalb des Hochs der Kerze davor hat, was die Kompression vor dem Ausbruch betont. Short-Setups lehnen den Handel ab, wenn die vorherige Kerze eine Inside-Bar ist, und spiegeln die Sicherheitsvorkehrungen in der Quell-MQL-Logik wider. Orders werden immer zum Markt mit einem festen Volumen ausgeführt.
Marktlogik
Betont Ausbrüche des jüngsten Hochs/Tiefs, um Richtungsbewegungen früh zu erfassen.
Verwendet den Körper der vorherigen Kerze zur Berechnung von zwei Ein-Drittel-Retracement-Niveaus (zigLevelBuy und zigLevelSell). Der Preis muss diese Niveaus berühren, oder die Sitzung muss über die konfigurierte Aktivierungsstunde hinaus sein, bevor ein Einstieg erlaubt wird.
Verhindert neue Positionen, wenn ein Ausbruch mit einer Inside-Kerze gegen die Trade-Richtung zusammenfällt.
Schließt offene Positionen, sobald das entgegengesetzte Ausbruchssignal bestätigt wird, und stellt sicher, dass die Strategie immer flach oder am letzten Signal ausgerichtet ist.
Einstiegsregeln
Long
Das aktuelle Kerzenhoch ist höher als das vorherige Kerzenhoch.
Bestätigung wird erhalten, wenn das aktuelle Tief das Ein-Drittel-Retracement des vorherigen Kerzenkörpers durchbricht, oder die aktuelle Stunde über dem Aktivierungsstunden-Parameter liegt.
Das aktuelle Tief muss über dem vorherigen Tief bleiben, während das vorherige Tief unter dem Hoch von zwei Kerzen zuvor liegt.
Keine bestehende Position ist offen.
Short
Das aktuelle Kerzentief liegt unter dem vorherigen Kerzentief.
Bestätigung wird erhalten, wenn das aktuelle Hoch das obere Ein-Drittel-Retracement des vorherigen Kerzenkörpers testet, oder die aktuelle Stunde über dem Aktivierungsstunden-Parameter liegt.
Die vorherige Kerze darf keine Inside-Bar sein.
Das aktuelle Hoch muss unter dem vorherigen Hoch liegen.
Keine bestehende Position ist offen.
Ausstiegsregeln
Long-Positionen schließen, wenn ein validierter Short-Ausbruch entsteht (Bedingungen 1–3 der Short-Einstiegslogik).
Short-Positionen schließen, wenn ein validierter Long-Ausbruch entsteht (Bedingungen 1–3 der Long-Einstiegslogik).
Parameter
Name
Beschreibung
Standard
CandleType
Zeitrahmen der von der Strategie verarbeiteten Kerzen.
1-Stunden-Kerzen
Volume
Ordergröße, die mit jeder Marktorder gesendet wird.
0.1
ActivationHour
Tagesstunde, nach der Bestätigungen automatisch akzeptiert werden, und der TimeCurrent()-Filter aus dem MQL-Code repliziert wird.
8
Hinweise
Die Bestätigungsprüfungen, die im Originalskript als "white bird" und "black bird" bezeichnet werden, werten aufgrund der Quellbedingungen immer als falsch aus; sie werden für Parität erhalten, beeinflussen aber keine Handelsentscheidungen.
Keine zusätzlichen Indikatoren oder Trailing-Stops werden verwendet—der Ansatz ist rein preisbasiert und kehrt Positionen bei jedem entgegengesetzten Ausbruch um.
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()