Diese Strategie ist ein StockSharp-Port des MetaTrader Expert_ADC_PL_CCI-Advisors. Es durchsucht die Preisbewegung nach Piercing Line- und Dark Cloud Cover-Kerzenumkehrungen und verwendet den Commodity Channel Index (CCI) als Bestätigung. Sobald ein gültiges Muster zusammen mit einem extremen CCI-Wert erkannt wird, eröffnet die Strategie eine Marktposition in Richtung der Umkehr und verlässt sie später, wenn der CCI seinen extremen Bereich verlässt.
Indikatoren
Commodity Channel Index (CCI): bestätigt Momentum-Extreme und erstellt die Ausstiegsbedingungen.
Durchschnittliche Körperlänge (SMA): misst die Körpergröße der Kerze, um „lange“ Kerzen innerhalb der Musterdefinition zu validieren.
Durchschnittlicher Schlusskurs (SMA): fungiert als einfacher Trendfilter, der den in der ursprünglichen MQL-Logik verwendeten gleitenden Durchschnitt widerspiegelt.
Handelsregeln
Entry
Bulles Signal (Durchdringungslinie):
Die vorherige Kerze muss eine lange bärische Kerze sein, die über ihrem Schlusskurs öffnet.
Die letzte Kerze muss eine lange bullische Kerze sein, die unterhalb des vorherigen Tiefs öffnet und innerhalb des vorherigen Körpers schließt, oberhalb ihres Mittelpunkts, aber unterhalb der vorherigen Eröffnung.
Der Mittelpunkt der älteren Kerze muss unter dem gleitenden Durchschnitt liegen, um einen kurzfristigen Abwärtstrend zu bestätigen.
The most recent completed CCI value must be less than or equal to -EntryConfirmationLevel (default 50).
Wenn eine Short-Position besteht, wird diese vollständig geschlossen, bevor eine Long-Position eingegangen wird.
Bearisches Signal (dunkle Wolkendecke): spiegelte die Logik des bullischen Signals mit einer langen bullischen Kerze, gefolgt von einer langen bärischen Kerze, die eine Lücke nach oben bildet, den vorherigen Körper durchdringt und unter seinem Mittelpunkt schließt, während CCI größer oder gleich EntryConfirmationLevel ist.
Ausstieg
Long-Positionen: geschlossen, wenn der CCI unter ExitLevel fällt oder von oben unter -ExitLevel fällt, was signalisiert, dass sich die Dynamik normalisiert hat.
Short-Positionen: geschlossen, wenn der CCI über -ExitLevel oder über ExitLevel von unten kreuzt.
Positionsgrößen
Verwendet die Basiseigenschaft Volume. Wenn das Signal die Umkehrung einer bestehenden Position erfordert, addiert die Strategie automatisch die absolute Größe der aktuellen Position zum Auftragsvolumen und stellt so eine vollständige Umkehrung sicher.
Parameter
Name
Beschreibung
Standard
CandleType
Kerzentyp und Zeitrahmen, die zur Erkennung verwendet werden.
1H Zeitrahmen
CciPeriod
Lookback-Länge des Commodity Channel Index.
49
AverageBodyPeriod
Anzahl der Kerzen für den gleitenden Durchschnitt der Körpergröße.
11
EntryConfirmationLevel
Absoluter CCI-Level, der Mustereinträge validiert.
50
ExitLevel
Absoluter CCI-Level, der Positionsausstiege auslöst.
80
Notizen
The strategy processes only finished candles and ignores partial updates.
No stop-loss or take-profit orders are set automatically; Ausstiege erfolgen ausschließlich signalbasiert wie im ursprünglichen Expert Advisor.
Ensure the instrument has a price step configured because the equality tolerance of the candlestick logic depends on the security settings.
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>
/// Dark Cloud Piercing CCI strategy: trades Dark Cloud Cover and Piercing Line
/// candlestick patterns confirmed by CCI indicator levels.
/// </summary>
public class DarkCloudPiercingCciStrategy : 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 DarkCloudPiercingCciStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
_entryLevel = Param(nameof(EntryLevel), 50m)
.SetDisplay("Entry Level", "CCI level for confirmation", "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();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
}
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 && _hasPrevCci)
{
var curr = _candles[^1];
var prev = _candles[^2];
// Piercing Line: prev bearish, curr bullish, curr opens below prev low, closes above midpoint
var isPiercing = prev.OpenPrice > prev.ClosePrice
&& curr.ClosePrice > curr.OpenPrice
&& curr.OpenPrice < prev.LowPrice
&& curr.ClosePrice > (prev.OpenPrice + prev.ClosePrice) / 2m;
// Dark Cloud Cover: prev bullish, curr bearish, curr opens above prev high, closes below midpoint
var isDarkCloud = prev.ClosePrice > prev.OpenPrice
&& curr.OpenPrice > curr.ClosePrice
&& curr.OpenPrice > prev.HighPrice
&& curr.ClosePrice < (prev.OpenPrice + prev.ClosePrice) / 2m;
if (isPiercing && cciValue < -EntryLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (isDarkCloud && cciValue > EntryLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_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, Unit, UnitTypes
from StockSharp.Algo.Indicators import CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class dark_cloud_piercing_cci_strategy(Strategy):
def __init__(self):
super(dark_cloud_piercing_cci_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 14) \
.SetDisplay("CCI Period", "CCI period", "Indicators")
self._entry_level = self.Param("EntryLevel", 50.0) \
.SetDisplay("Entry Level", "CCI level for confirmation", "Signals")
self._signal_cooldown = self.Param("SignalCooldownCandles", 6) \
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading")
self._cci = None
self._candles = []
self._has_prev_cci = False
self._candles_since_trade = 0
@property
def cci_period(self):
return self._cci_period.Value
@property
def entry_level(self):
return self._entry_level.Value
@property
def signal_cooldown(self):
return self._signal_cooldown.Value
def OnReseted(self):
super(dark_cloud_piercing_cci_strategy, self).OnReseted()
self._cci = None
self._candles = []
self._has_prev_cci = False
self._candles_since_trade = self.signal_cooldown
def OnStarted2(self, time):
super(dark_cloud_piercing_cci_strategy, self).OnStarted2(time)
self._cci = CommodityChannelIndex()
self._cci.Length = self.cci_period
self._candles = []
self._has_prev_cci = False
self._candles_since_trade = self.signal_cooldown
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._cci, self._process_candle)
subscription.Start()
self.StartProtection(takeProfit=Unit(2, UnitTypes.Percent), stopLoss=Unit(1, UnitTypes.Percent))
def _process_candle(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
cci_val = float(cci_value)
if self._candles_since_trade < self.signal_cooldown:
self._candles_since_trade += 1
self._candles.append(candle)
if len(self._candles) > 5:
self._candles.pop(0)
if len(self._candles) >= 2 and self._has_prev_cci:
curr = self._candles[-1]
prev = self._candles[-2]
is_piercing = (float(prev.OpenPrice) > float(prev.ClosePrice)
and float(curr.ClosePrice) > float(curr.OpenPrice)
and float(curr.OpenPrice) < float(prev.LowPrice)
and float(curr.ClosePrice) > (float(prev.OpenPrice) + float(prev.ClosePrice)) / 2.0)
is_dark_cloud = (float(prev.ClosePrice) > float(prev.OpenPrice)
and float(curr.OpenPrice) > float(curr.ClosePrice)
and float(curr.OpenPrice) > float(prev.HighPrice)
and float(curr.ClosePrice) < (float(prev.OpenPrice) + float(prev.ClosePrice)) / 2.0)
if is_piercing and cci_val < -self.entry_level and self.Position == 0 and self._candles_since_trade >= self.signal_cooldown:
self.BuyMarket()
self._candles_since_trade = 0
elif is_dark_cloud and cci_val > self.entry_level and self.Position == 0 and self._candles_since_trade >= self.signal_cooldown:
self.SellMarket()
self._candles_since_trade = 0
self._has_prev_cci = True
def CreateClone(self):
return dark_cloud_piercing_cci_strategy()