Auf GitHub ansehen

MA2CCI klassische Strategie

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

  1. 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.
  2. 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.
  3. 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;
	}
}