Diese StockSharp-Strategie portiert den MetaTrader 5 Expertenberater Expert_ABE_BE_CCI (Ordner MQL/306). Das Original EA kombiniert bullische/bearische Engulfing-Kerzenmuster mit einem Commodity Channel Index (CCI)-Bestätigungsmodul und einer festen Lot-Geldverwaltung. Die C#-Implementierung behält die gleiche Entscheidungslogik bei und nutzt gleichzeitig die von StockSharp bereitgestellten Abonnement- und Indikatorbindungen auf hoher Ebene.
Die Engine überwacht abgeschlossene Kerzen im ausgewählten Zeitrahmen, berechnet einen gleitenden Durchschnitt der Kerzenkörper, einen Durchschnitt der Schlusskurse und einen CCI mit konfigurierbarem Zeitraum. Bullische oder bärische Engulfing-Muster werden nur akzeptiert, wenn die Kerzenkörper den aktuellen Durchschnitt überschreiten und der Mittelpunkt der verschlungenen Kerze auf der richtigen Seite des gleitenden Durchschnitts liegt, was die MQL CCandlePattern-Prüfungen nachahmt. Long-Trades erfordern ein bullisches Engulfing plus CCI unter dem überverkauften Schwellenwert, während Short-Trades die Spiegelbedingung mit CCI über dem überkauften Schwellenwert erfordern. Positionsausgänge spiegeln die EA-„Abstimmungs“-Logik wider: CCI Überschreitungen von ±ExitLevel neutralisieren offene Positionen unabhängig von der Richtung.
Arbeitsablauf
Abonnieren Sie den konfigurierten Kerzentyp und berechnen Sie:
Kerzenkörperdurchschnitt über BodyAveragePeriod Balken.
Gleitender Durchschnitt der Schlusskurse im selben Fenster.
Rohstoffkanalindex mit der Länge CciPeriod.
Für jede fertige Kerze:
Stellen Sie sicher, dass die vorherige Kerze einen umhüllten Balken mit entgegengesetzter Farbe bildet.
Überprüfen Sie, ob der einhüllende Körper größer als der Durchschnitt des Rollkörpers ist und über die vorherige Öffnung hinaus schließt, indem Sie die MQL-Filter replizieren.
Bestätigen Sie den Trendkontext, indem Sie den Mittelpunkt der vorherigen Kerze mit dem gleitenden Durchschnitt des Schlusskurses vergleichen.
Bestätigen Sie die Dynamik mit CCI vs. EntryOversoldLevel oder EntryOverboughtLevel.
Trades verwalten:
Wenn die bullischen Bedingungen übereinstimmen und keine Long-Position aktiv ist, schließen Sie Short-Positionen und kaufen Sie das konfigurierte Volumen.
Wenn die rückläufigen Bedingungen übereinstimmen und kein Short aktiv ist, schließen Sie Long-Positionen und verkaufen Sie das konfigurierte Volumen.
Überwachen Sie CCI auf Exits: Jede Kreuzung unter +ExitLevel oder über -ExitLevel schließt Long-Positionen, während Kreuzungen über -ExitLevel oder unter +ExitLevel Short-Positionen schließen, was der 40-Punkte-Abstimmungslogik von EA entspricht.
Standardparameter
Name
Standard
Beschreibung
CciPeriod
49
Länge des Commodity Channel Index-Indikators.
BodyAveragePeriod
11
Fenster zur Mittelung der Kerzenkörpergröße und des Mittelwerts des Schlusskurses.
EntryOversoldLevel
-50
CCI-Schwellenwert, der bullische Engulfing-Setups bestätigt.
EntryOverboughtLevel
50
CCI-Schwellenwert, der die bärischen Engulfing-Setups bestätigt.
ExitLevel
80
Absolutes CCI-Niveau, das bei Überschreiten Positionsausstiege auslöst.
CandleType
1 Stunde
Für das Kerzenabonnement verwendeter Zeitrahmen.
Notizen
Die Volumenverarbeitung spiegelt typische StockSharp-Konvertierungen wider: Volume definiert die Basisauftragsgröße; Gegenüberliegende Positionen werden vor dem Umkehren abgeflacht.
Trailing- und Money-Management-Komponenten (TrailingNone, MoneyFixedLot) aus dem Paket MQL werden nicht neu erstellt; Die Auftragsgröße von StockSharp deckt bereits das Verhalten bei festen Losen ab.
Alle Kommentare im Code sind auf Englisch, Tabulatoren werden zum Einrücken verwendet und es werden keine Indikatorwerte über GetValue abgerufen, gemäß den Repository-Richtlinien.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// ABE BE CCI strategy: Engulfing pattern with CCI confirmation.
/// Bullish engulfing + negative CCI for long, bearish engulfing + positive CCI for short.
/// </summary>
public class AbeBeCciStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _entryLevel;
private readonly StrategyParam<int> _signalCooldownCandles;
private readonly List<ICandleMessage> _candles = new();
private decimal _prevCci;
private bool _hasPrevCci;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public decimal EntryLevel { get => _entryLevel.Value; set => _entryLevel.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public AbeBeCciStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
_entryLevel = Param(nameof(EntryLevel), 100m)
.SetDisplay("Entry Level", "CCI threshold for entry", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candles.Clear();
_prevCci = 0m;
_hasPrevCci = false;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candles.Clear();
_hasPrevCci = false;
_candlesSinceTrade = SignalCooldownCandles;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
_candles.Add(candle);
if (_candles.Count > 5)
_candles.RemoveAt(0);
if (_candles.Count >= 2)
{
var curr = _candles[^1];
var prev = _candles[^2];
var bullishEngulfing = prev.OpenPrice > prev.ClosePrice
&& curr.ClosePrice > curr.OpenPrice
&& curr.OpenPrice <= prev.ClosePrice
&& curr.ClosePrice >= prev.OpenPrice;
var bearishEngulfing = prev.ClosePrice > prev.OpenPrice
&& curr.OpenPrice > curr.ClosePrice
&& curr.OpenPrice >= prev.ClosePrice
&& curr.ClosePrice <= prev.OpenPrice;
if (bullishEngulfing && cciValue < -EntryLevel && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (bearishEngulfing && cciValue > EntryLevel && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
if (_hasPrevCci)
{
if (Position > 0 && _prevCci > EntryLevel && cciValue < EntryLevel && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
else if (Position < 0 && _prevCci < -EntryLevel && cciValue > -EntryLevel && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
}
_prevCci = cciValue;
_hasPrevCci = true;
}
}
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.Indicators import CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class abe_be_cci_strategy(Strategy):
def __init__(self):
super(abe_be_cci_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._cci_period = self.Param("CciPeriod", 14)
self._entry_level = self.Param("EntryLevel", 100.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._candles = []
self._prev_cci = 0.0
self._has_prev_cci = False
self._candles_since_trade = 6
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def CciPeriod(self):
return self._cci_period.Value
@CciPeriod.setter
def CciPeriod(self, value):
self._cci_period.Value = value
@property
def EntryLevel(self):
return self._entry_level.Value
@EntryLevel.setter
def EntryLevel(self, value):
self._entry_level.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(abe_be_cci_strategy, self).OnReseted()
self._candles.clear()
self._prev_cci = 0.0
self._has_prev_cci = False
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(abe_be_cci_strategy, self).OnStarted2(time)
self._candles.clear()
self._has_prev_cci = False
self._candles_since_trade = self.SignalCooldownCandles
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(cci, self._process_candle).Start()
def _process_candle(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
cci_val = float(cci_value)
self._candles.append(candle)
if len(self._candles) > 5:
self._candles.pop(0)
if len(self._candles) >= 2:
curr = self._candles[-1]
prev = self._candles[-2]
bullish_engulfing = (float(prev.OpenPrice) > float(prev.ClosePrice)
and float(curr.ClosePrice) > float(curr.OpenPrice)
and float(curr.OpenPrice) <= float(prev.ClosePrice)
and float(curr.ClosePrice) >= float(prev.OpenPrice))
bearish_engulfing = (float(prev.ClosePrice) > float(prev.OpenPrice)
and float(curr.OpenPrice) > float(curr.ClosePrice)
and float(curr.OpenPrice) >= float(prev.ClosePrice)
and float(curr.ClosePrice) <= float(prev.OpenPrice))
if bullish_engulfing and cci_val < -self.EntryLevel and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif bearish_engulfing and cci_val > self.EntryLevel and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
if self._has_prev_cci:
if self.Position > 0 and self._prev_cci > self.EntryLevel and cci_val < self.EntryLevel and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
elif self.Position < 0 and self._prev_cci < -self.EntryLevel and cci_val > -self.EntryLevel and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
self._prev_cci = cci_val
self._has_prev_cci = True
def CreateClone(self):
return abe_be_cci_strategy()