Diese Strategie ist ein High-Level-StockSharp-Port des MetaTrader-Expertenberaters „iCHO Trend CCIDualOnMA Filter“. Es kombiniert einen Chaikin-Oszillator-Nulllinienregimefilter mit einer dualen Commodity Channel Index (CCI)-Bestätigung, die auf einer geglätteten Preisreihe berechnet wird. Das Ergebnis ist ein Trendfolge-Ansatz, der auf Momentum-Verschiebungen reagiert, aber dennoch eine Momentum-Bestätigung durch das Paar CCI erfordert, bevor ein Handel eingeleitet wird.
Handelslogik
Chaikin-Oszillatorkern – die Akkumulations-/Verteilungslinie wird durch zwei konfigurierbare gleitende Durchschnitte geglättet. Ihr Unterschied spiegelt den Chaikin-Oszillator wider. Kreuze über/unter Null signalisieren eine Änderung des vorherrschenden Kapitalflusses.
Dualer CCI-Filter – beide CCI-Instanzen verwenden dieselbe Preiseingabe mit gleitendem Durchschnitt und Glättung, aber unterschiedliche Lookback-Zeiträume. Bei einem langen Setup muss sich der schnelle CCI vom negativen Bereich erholen und den langsamen CCI überschreiten, während der Chaikin-Oszillator über Null bleibt. Ein kurzer Aufbau spiegelt diese Bedingungen wider.
Optionale Umkehrung – das Original EA bietet eine „Umkehr“-Flagge, die Long- und Short-Signale vertauscht. Der Port behält dieses Verhalten bei, sodass die gleichen Regeln für Gegentrendtests verwendet werden können.
Positionsverwaltung – optionale Flags schließen das Gegenrisiko, bevor eine neue Position eröffnet wird, und beschränken die Strategie auf eine einzige offene Position. Zur Nachahmung der MetaTrader-Implementierung wird eine Ein-Trade-pro-Barren-Regel durchgesetzt.
Sitzungsfilter – Der Handel kann auf ein benutzerdefiniertes Intraday-Fenster beschränkt werden, einschließlich Wrap-Around-Sitzungen, die über Mitternacht hinausgehen.
Parameter
Parameter
Beschreibung
FastChaikinLength
Schnelle gleitende Durchschnittsperiode, die im Chaikin-Oszillator verwendet wird.
SlowChaikinLength
Langsame gleitende Durchschnittsperiode, die im Chaikin-Oszillator verwendet wird.
ChaikinMethod
Methode des gleitenden Durchschnitts (einfach, exponentiell, geglättet, linear gewichtet), angewendet auf die Akkumulations-/Verteilungslinie.
FastCciLength
Rückblick auf den Fast Commodity Channel Index.
SlowCciLength
Rückblick auf den langsamen Commodity Channel Index.
MaLength
Länge des gleitenden Vorverarbeitungsdurchschnitts, der die CCIs speist.
MaMethod
Methode des gleitenden Durchschnitts, die zur Vorverarbeitung des Preises verwendet wird, bevor er die CCIs erreicht.
MaPrice
Preisart (Schluss, Eröffnung, Hoch, Tief, Median, typisch, gewichtet), die vor den CCIs geglättet wird.
UseClosedBar
Verarbeiten Sie nur vollständig fertige Kerzen (Standardeinstellung: wahr, identisch mit SignalsBarCurrent=bar_1 im EA).
ReverseSignals
Tauschen Sie Long- und Short-Logik aus.
CloseOpposite
Schließen Sie eine offene Position in die entgegengesetzte Richtung, bevor Sie eine neue eröffnen.
OnlyOnePosition
Erlauben Sie immer nur eine einzige offene Position.
TradeMode
Beschränken Sie die Ausführung auf Longs, Shorts oder beides (BuyOnly, SellOnly, BuyAndSell).
UseTimeFilter
Aktivieren Sie den Handelssitzungsfilter.
StartHour, StartMinute, EndHour, EndMinute
Sitzungsgrenzen (einschließlich Beginn, ausschließlich Ende), ausgedrückt in Austauschzeit. Wrap-Around-Sitzungen werden unterstützt.
CandleType
Zeitrahmen des Kerzenabonnements, das die Indikatoren speist.
Notizen
Die Strategie verwendet nur SubscribeCandles-Bindungen und integrierte Indikatoren auf hoher Ebene. Es sind keine benutzerdefinierten Puffer oder historischen Anforderungen erforderlich.
Alle preisbasierten Berechnungen verwenden die gleiche Vorverarbeitung des gleitenden Durchschnitts wie der Indikator MetaTrader CCIDualOnMA, indem sie den Indikator CCI mit einer geglätteten Preisreihe versorgen.
Die Standardparameter reproduzieren die ursprünglichen EA-Standardwerte: Chaikin 3/10 EMA, CCI Perioden 14 und 50, 12-Perioden-SMA-Vorverarbeitung und ein Handelsfenster von 10:01 bis 15:02.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Combines a Chaikin oscillator zero-line filter with CCI confirmation.
/// Buys when Chaikin crosses above zero and CCI is rising, sells on opposite.
/// </summary>
public class iCHO_Trend_CCIDualOnMA_FilterStrategy : Strategy
{
private readonly StrategyParam<int> _cciLength;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _cciLevel;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal? _prevCci;
private decimal? _prevPrevCci;
private int _candlesSinceTrade;
public int CciLength
{
get => _cciLength.Value;
set => _cciLength.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public decimal CciLevel
{
get => _cciLevel.Value;
set => _cciLevel.Value = value;
}
public int SignalCooldownCandles
{
get => _signalCooldownCandles.Value;
set => _signalCooldownCandles.Value = value;
}
public iCHO_Trend_CCIDualOnMA_FilterStrategy()
{
_cciLength = Param(nameof(CciLength), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Length", "CCI period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Primary candle series", "Data");
_cciLevel = Param(nameof(CciLevel), 100m)
.SetDisplay("CCI Level", "CCI threshold for entry", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between entries", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCci = null;
_prevPrevCci = null;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCci = null;
_prevPrevCci = null;
_candlesSinceTrade = SignalCooldownCandles;
var cci = new CommodityChannelIndex { Length = CciLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(cci, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, cci);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished)
return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_prevCci.HasValue && _prevPrevCci.HasValue)
{
if (_prevPrevCci.Value < -CciLevel && _prevCci.Value < -CciLevel && cciValue > -CciLevel && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevPrevCci.Value > CciLevel && _prevCci.Value > CciLevel && cciValue < CciLevel && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevPrevCci = _prevCci;
_prevCci = cciValue;
}
}
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 i_cho__trend_cci_dual_on_ma__filter_strategy(Strategy):
def __init__(self):
super(i_cho__trend_cci_dual_on_ma__filter_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._cci_length = self.Param("CciLength", 14)
self._cci_level = self.Param("CciLevel", 100.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 4)
self._prev_cci = 0.0
self._prev_prev_cci = 0.0
self._candles_since_trade = 4
self._has_two = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def CciLength(self):
return self._cci_length.Value
@CciLength.setter
def CciLength(self, value):
self._cci_length.Value = value
@property
def CciLevel(self):
return self._cci_level.Value
@CciLevel.setter
def CciLevel(self, value):
self._cci_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(i_cho__trend_cci_dual_on_ma__filter_strategy, self).OnReseted()
self._prev_cci = 0.0
self._prev_prev_cci = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_two = False
def OnStarted2(self, time):
super(i_cho__trend_cci_dual_on_ma__filter_strategy, self).OnStarted2(time)
self._prev_cci = 0.0
self._prev_prev_cci = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_two = False
cci = CommodityChannelIndex()
cci.Length = self.CciLength
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)
level = float(self.CciLevel)
if self._has_two:
# Both prev_prev and prev were below -level, now crossing above -level
if self._prev_prev_cci < -level and self._prev_cci < -level and cci_val > -level and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
# Both prev_prev and prev were above +level, now crossing below +level
elif self._prev_prev_cci > level and self._prev_cci > level and cci_val < level and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._prev_prev_cci = self._prev_cci
self._prev_cci = cci_val
if not self._has_two:
if self._prev_prev_cci != 0.0 or self._prev_cci != 0.0:
self._has_two = True
def CreateClone(self):
return i_cho__trend_cci_dual_on_ma__filter_strategy()