Auf GitHub ansehen

Exp ColorMETRO MMRec Duplex-Strategie

Überblick

Diese Strategie portiert den MetaTrader 5-Expertenberater Exp_ColorMETRO_MMRec_Duplex zu StockSharp. Der originale Roboter führt zwei unabhängige ColorMETRO-Indikatormodule (eines für Long, eines für Short) aus und wendet eine MMRec-Überlagerung (Geldverwaltungs-Neuberechnung) an, die die Positionsgröße nach wiederholten Verlusten reduziert. Die C#-Version spiegelt dieses Verhalten mit StockSharpss High-Level-API für Kerzenabonnements und Order-Routing wider.

Handelslogik

  • Zwei verschiedene ColorMETRO-Indikatoren operieren auf konfigurierbaren Kerzentypen. Das Long-Modul verwaltet nur Long-Exposition, während das Short-Modul die Short-Exposition kontrolliert.
  • Jeder Indikator erzeugt ein schnelles und ein langsames RSI-Stufenband. Die Strategie imitiert die MQL5-CopyBuffer-Aufrufe, indem sie historische Werte speichert und die durch SignalBar definierte Barre inspiziert.
  • Ein Long-Einstieg wird generiert, wenn das schnelle Band auf der inspizierten Barre die langsame Band von unten kreuzt, während die vorherige Barre das schnelle Band noch über dem langsamen hatte. Alle offenen Short-Positionen werden vor der neuen Long-Position abgeflacht.
  • Long-Ausstiege erfolgen, wenn das langsame Band auf der vorherigen inspizierten Barre über dem schnellen Band sitzt, was ein bärisches Regime im originalen EA signalisiert.
  • Short-Einstiege und -Ausstiege spiegeln die Long-Logik wider (Kreuzen nach oben für Einstiege, schnelle Linie über der langsamen auf der vorherigen Barre für Ausstiege).
  • Nur fertige Kerzen werden verarbeitet und der Handel wird blockiert, bis der Indikator beide Bänder als bereit meldet, was die MetaTrader-Aufwärmphase reproduziert.

Geldverwaltung (MMRec)

  • Strategy.Volume definiert die Referenz-Lotgröße. Die Long- und Short-Module multiplizieren sie mit ihren jeweiligen LongMm/ShortMm-Koeffizienten bei der Dimensionierung neuer Orders.
  • Nach jeder abgeschlossenen Trade zeichnet die Strategie auf, ob das Ergebnis ein Verlust war (basierend auf Kerzenschlusspreisen, genauso wie der EA, der historische Deals inspiziert).
  • Wenn die letzten TotalTrigger-Trades eines Moduls mindestens LossTrigger-Verlierer enthalten, wechselt das Modul zum reduzierten Multiplikator (SmallMm). Sobald die Verlustanzahl unter den Schwellenwert fällt, wird der Standard-Multiplikator automatisch wiederhergestellt.
  • Positionsumkehrungen finalisieren zuerst das Ergebnis des bestehenden Trades (Aktualisierung der MMRec-Zähler), bevor die entgegengesetzte Richtung dimensioniert und eröffnet wird.

Indikatorhinweise

  • ColorMetroMmrecIndicator ist ein treuer Port des benutzerdefinierten ColorMETRO-Indikators. Er speist dieselben schnellen/langsamen Bänder, die von einem RSI-Kern mit Schrittverfolgung und Trend-Gedächtnis angetrieben werden.
  • Der Indikator legt den internen RSI und ein Bereitschafts-Flag frei, sodass die Strategie unvollständige Werte genau wie die MQL-Implementierung ignorieren kann.

Parameter

Gruppe Name Beschreibung
Long LongCandleType Kerzentyp für das Long-ColorMETRO-Modul.
Long LongTotalTrigger Anzahl abgeschlossener Long-Trades, die bei der MMRec-Auswertung inspiziert werden.
Long LongLossTrigger Verlustanzahl, die den reduzierten Long-Multiplikator aktiviert.
Long LongSmallMm Reduzierter Multiplikator für Long-Trades nach einer Verlustserie.
Long LongMm Standard-Multiplikator für Long-Trades.
Long LongEnableOpen Öffnen von Long-Positionen aktivieren.
Long LongEnableClose Schließen von Long-Positionen aktivieren.
Long LongPeriodRsi RSI-Länge im Long-ColorMETRO-Indikator.
Long LongStepSizeFast Schnelle Band-Schrittgröße für das Long-Modul.
Long LongStepSizeSlow Langsame Band-Schrittgröße für das Long-Modul.
Long LongSignalBar Historischer Versatz (in geschlossenen Barren) beim Lesen von Indikatorwerten.
Long LongMagic Originale MT5-Magicnummer, als Referenz beibehalten.
Long LongStopLossTicks Stop-Loss-Abstand-Platzhalter aus dem EA (nicht durchgesetzt).
Long LongTakeProfitTicks Take-Profit-Abstand-Platzhalter aus dem EA (nicht durchgesetzt).
Long LongDeviationTicks Erlaubter Slippage-Platzhalter aus dem EA (nicht durchgesetzt).
Long LongMarginMode MM-Modus-Flag für Kompatibilität beibehalten (Logik verwendet rohe Multiplikatoren).
Short ShortCandleType Kerzentyp für das Short-ColorMETRO-Modul.
Short ShortTotalTrigger Anzahl abgeschlossener Short-Trades, die bei der MMRec-Auswertung inspiziert werden.
Short ShortLossTrigger Verlustanzahl, die den reduzierten Short-Multiplikator aktiviert.
Short ShortSmallMm Reduzierter Multiplikator für Short-Trades nach einer Verlustserie.
Short ShortMm Standard-Multiplikator für Short-Trades.
Short ShortEnableOpen Öffnen von Short-Positionen aktivieren.
Short ShortEnableClose Schließen von Short-Positionen aktivieren.
Short ShortPeriodRsi RSI-Länge im Short-ColorMETRO-Indikator.
Short ShortStepSizeFast Schnelle Band-Schrittgröße für das Short-Modul.
Short ShortStepSizeSlow Langsame Band-Schrittgröße für das Short-Modul.
Short ShortSignalBar Historischer Versatz (in geschlossenen Barren) beim Lesen von Indikatorwerten.
Short ShortMagic Originale MT5-Magicnummer, als Referenz beibehalten.
Short ShortStopLossTicks Stop-Loss-Abstand-Platzhalter aus dem EA (nicht durchgesetzt).
Short ShortTakeProfitTicks Take-Profit-Abstand-Platzhalter aus dem EA (nicht durchgesetzt).
Short ShortDeviationTicks Erlaubter Slippage-Platzhalter aus dem EA (nicht durchgesetzt).
Short ShortMarginMode MM-Modus-Flag für Kompatibilität beibehalten (Logik verwendet rohe Multiplikatoren).

Implementierungshinweise

  • Die Strategie verlässt sich auf SubscribeCandles(...).BindEx(...) und vermeidet direkten Pufferzugriff, konform mit den Konvertierungsrichtlinien.
  • Schutz-Stops aus dem EA bleiben nur als Parameter; Benutzer können StartProtection oder benutzerdefinierte Risikomodule bei Bedarf anhängen.
  • Beide Module teilen dieselbe Sicherheitsinstanz, behalten aber ihre eigenen Kerzenabonnements und MMRec-Zähler, entsprechend dem Duplex-Layout von MetaTrader.
  • Alle Code-Kommentare sind auf Englisch und die Logik vermeidet verbotene API-Aufrufe wie GetTrades.

Haftungsausschluss

Dieser Port reproduziert die logische Struktur des originalen EA, aber die Ausführungsqualität hängt vom verbundenen Broker, dem Datenfeed und der StockSharp-Konfiguration ab. Validieren Sie das Verhalten immer auf historischen und Demo-Daten, bevor Sie mit echtem Kapital handeln.

using System;
using System.Collections.Generic;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// ColorMETRO MMRec Duplex strategy using EMA crossover.
/// Buys when fast EMA crosses above slow EMA, sells on reverse.
/// </summary>
public class ExpColorMetroMmrecDuplexStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public ExpColorMetroMmrecDuplexStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}