Die MA2CCI-Strategie portiert den klassischen MetaTrader-Expertenberater, der auf dem Zusammenspiel zweier einfacher gleitender Durchschnitte (SMA) und des Commodity Channel Index (CCI) basiert. Es filtert Trades anhand der Nulllinie CCI und wendet Schutzstopps an, die vom Average True Range (ATR) abgeleitet sind. Das System ist für trendfolgende Einstiege mit schneller Reaktion auf Umkehrungen konzipiert.
Die StockSharp-Version behält die ursprüngliche Handelslogik bei und passt das Risikomanagement an die .NET-Umgebung an. Die Positionsgröße folgt einer Risiko-pro-Tausend-Regel mit einem zusätzlichen Verringerungsfaktor, der die Handelsgröße nach aufeinanderfolgenden Verlusten reduziert. Jeder Eintrag fügt einen volatilitätsgesteuerten Stopp hinzu, der die in der MQL-Implementierung verwendete Distanz ATR widerspiegelt.
Handelslogik
Indikatoren
Schnell SMA mit Standardlänge 4.
Langsam SMA mit Standardlänge 8.
CCI-Filter mit 4-Perioden-Lookback.
ATR mit Punkt 4 für Stop-Placement.
Eintrittsbedingungen
Lang: Der schnelle SMA kreuzt den langsamen SMA und der vorherige fertige Balken zeigt, dass CCI durch Null ansteigt (von negativ nach positiv).
Kurz: Der schnelle SMA kreuzt den langsamen SMA und der vorherige Balken zeigt, dass CCI durch Null fällt (von positiv nach negativ).
Exit Conditions
Gegenüberliegender SMA-Crossover schließt offene Positionen, auch wenn kein neuer Handel initiiert wird.
ATR Stop: Long-Positionen werden geschlossen, wenn der Preis auf entry - ATR fällt; Short-Positionen werden geschlossen, wenn der Preis auf entry + ATR steigt.
Risikomanagement
Das Grundauftragsvolumen ist konfigurierbar. standardmäßig 0,1 Lots (oder Umtauschäquivalent).
Die optionale dynamische Größenanpassung skaliert das Volumen auf free capital * MaxRiskPerThousand / 1000, wenn Portfoliodaten verfügbar sind.
Nach mehr als einem aufeinanderfolgenden Verlust wird die Positionsgröße linear um losses / DecreaseFactor des berechneten Volumens reduziert.
Volatilitätsstopps basieren auf der zuletzt abgeschlossenen Kerze. Intrabar-Spitzen über die Stop-Levels hinaus lösen beim nächsten Strategie-Tick einen Marktausstieg aus.
Parameter
Name
Beschreibung
Standard
CandleType
Arbeitszeitrahmen für alle Indikatoren.
1 Stunde Kerzen
OrderVolume
Mindesthandelsgröße, wenn eine risikobasierte Größenbestimmung nicht verfügbar ist.
0,1
FastMaPeriod
Zeitraum des Fastens SMA.
4
SlowMaPeriod
Zeitraum der langsamen SMA.
8
CciPeriod
Zeitraum des Filters CCI.
4
AtrPeriod
ATR Länge für Stoppberechnung.
4
MaxRiskPerThousand
Anteil des pro Trade zugewiesenen freien Kapitals (pro 1000 Einheiten).
0,02
DecreaseFactor
Divisor wurde verwendet, um das Volumen nach Verluststrähnen zu verkleinern.
3
Notizen
Die Strategie verarbeitet nur fertige Kerzen und gewährleistet so eine Entscheidung pro Balken, ähnlich wie beim ursprünglichen EA, bei dem Volume[0] > 1 als Gate verwendet wurde.
Stop-Levels werden intern simuliert, anstatt Börsen-Stop-Orders zu registrieren; Dies entspricht dem Verhalten der MetaTrader-Version, die sich auf Marktschließungen stützte, als die Schwellenwerte von ATR erreicht wurden.
Aktivieren Sie die Diagrammerstellung in StockSharp Designer, um SMA, CCI und ausgeführte Trades mithilfe der integrierten Zeichenhilfen zu visualisieren.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// MA2CCI Classic strategy - dual SMA crossover with CCI zero-line filter.
/// Buys when fast SMA crosses above slow SMA and CCI above zero.
/// Sells when fast SMA crosses below slow SMA and CCI below zero.
/// </summary>
public class Ma2CciClassicStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Ma2CciClassicStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetDisplay("CCI Period", "CCI lookback", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal cci)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_prevFast <= _prevSlow && fast > slow && cci > 0 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (_prevFast >= _prevSlow && fast < slow && cci < 0 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevFast = fast; _prevSlow = slow;
}
}
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 SimpleMovingAverage, CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class ma2_cci_classic_strategy(Strategy):
def __init__(self):
super(ma2_cci_classic_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 12).SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 26).SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._cci_period = self.Param("CciPeriod", 14).SetDisplay("CCI Period", "CCI lookback", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
@property
def fast_period(self): return self._fast_period.Value
@property
def slow_period(self): return self._slow_period.Value
@property
def cci_period(self): return self._cci_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(ma2_cci_classic_strategy, self).OnReseted()
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
def OnStarted2(self, time):
super(ma2_cci_classic_strategy, self).OnStarted2(time)
self._has_prev = False
fast = SimpleMovingAverage(); fast.Length = self.fast_period
slow = SimpleMovingAverage(); slow.Length = self.slow_period
cci = CommodityChannelIndex(); cci.Length = self.cci_period
sub = self.SubscribeCandles(self.candle_type)
sub.Bind(fast, slow, cci, self.process_candle).Start()
def process_candle(self, candle, fast, slow, cci):
if candle.State != CandleStates.Finished: return
f = float(fast); s = float(slow); c = float(cci)
if not self._has_prev: self._prev_fast = f; self._prev_slow = s; self._has_prev = True; return
if self._prev_fast <= self._prev_slow and f > s and c > 0 and self.Position <= 0:
if self.Position < 0: self.BuyMarket()
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and f < s and c < 0 and self.Position >= 0:
if self.Position > 0: self.SellMarket()
self.SellMarket()
self._prev_fast = f; self._prev_slow = s
def CreateClone(self): return ma2_cci_classic_strategy()