Auf GitHub ansehen

RobotPowerM5 Meta4 V12 Strategie

Überblick

Die RobotPowerM5 Meta4 V12-Strategie ist eine C#-Portierung des MetaTrader 4 Expert Advisors RobotPowerM5_meta4V12.mq4. Das Original EA wurde für Fünf-Minuten-Forex-Charts entwickelt und bewertet das Gleichgewicht zwischen Bulls Power und Bears Power, um zu entscheiden, ob ein neuer Es sollte eine Long- oder Short-Position eröffnet werden. Die StockSharp-Version behält das Verhalten bei jeweils einer Position bei und reproduziert den Punkt. basierend auf Stop-Loss-/Take-Profit-Einstellungen und implementiert die Trailing-Stop-Logik neu, die nach und nach Gewinne sichert, sobald der Markt erreicht ist bewegt sich zugunsten des Handels.

Handelslogik

  1. Indikatormotor
    • Fünf-Minuten-Kerzen werden standardmäßig abonniert (der Zeitrahmen ist über den Parameter CandleType konfigurierbar).
    • Ein Paar StockSharp-Indikatoren, BullsPower und BearsPower, werden bei jeder fertigen Kerze mithilfe der konfigurierten aktualisiert Mittelungszeitraum.
    • Der kombinierte Wert BullsPower + BearsPower wird mit einer Verzögerung von einem Takt gespeichert, um die shift=1-Aufrufe von zu imitieren MQL-Code, der immer auf den letzten vollständig geschlossenen Balken wirkt.
  2. Eintrittsregeln
    • Wenn keine Position offen ist und die verzögerte Summe der Bulls/Bears Power positiv ist, wird eine Marktkauforder ausgegeben.
    • Wenn keine Position offen ist und die verzögerte Summe negativ ist, wird ein Marktverkaufsauftrag erteilt.
    • Signale werden ignoriert, während eine Position aktiv ist; Der Handel wird ausschließlich über Schutzausgänge abgewickelt.
  3. Volumenhandhabung
    • Der Parameter Volume stellt die angeforderte Losgröße dar. Es wird direkt an BuyMarket / SellMarket übergeben, wodurch die Runden Sie den Stecker bei Bedarf auf die Lotstufe des Instruments auf.

Risikomanagement

  • Stop-Loss – Der anfängliche Stop wird StopLossPoints MetaTrader Punkte vom durchschnittlichen Ausführungspreis entfernt platziert. Das Niveau ist überwacht mit Kerzentiefs (für Long-Positionen) oder Kerzenhochs (für Short-Positionen); einmal berührt die Strategie Exits am Markt.
  • Take-Profit – Das Gewinnziel beträgt TakeProfitPoints Punkte ab dem Einstieg und wird entsprechend den entsprechenden Kerzenhochs/-tiefs bewertet wie MT4 Positionen schließt, wenn ein Ziel intrabar getroffen wird.
  • Trailing Stop – Nachdem sich der Preis um mehr als TrailingStopPoints zu Gunsten des Handels bewegt hat, wird ein Trailing Stop aktiviert. Bei Long-Positionen wird der Stop auf referencePrice - trailingDistance verschoben, wobei die Referenz das Maximum der Kerze ist nah und hoch. Bei Shorts folgt der Stop referencePrice + trailingDistance und verwendet dabei das Minimum aus Schluss- und Tiefstkurs der Kerze. Dies reproduziert das Nachlaufverhalten von EA, das ursprünglich mit OrderModify implementiert wurde.

Parameter

Name Beschreibung Standard Notizen
BullBearPeriod Mittelungszeitraum für die Bulls Power- und Bears Power-Indikatoren. 5 Durch Erhöhen des Werts wird der Impulsfilter geglättet.
Volume Gewünschte Losgröße für jeden Eintrag. 1 Das tatsächlich gehandelte Volumen hängt vom Lotschritt und den Limits des Brokers ab.
StopLossPoints Anfänglicher Schutzstoppabstand in MetaTrader Punkten. 45 Auf 0 setzen, um den harten Stop-Loss zu deaktivieren.
TakeProfitPoints Take-Profit-Distanz in MetaTrader Punkten. 150 Auf 0 setzen, um ohne festes Gewinnziel zu handeln.
TrailingStopPoints Vom Trailing Stop verwendete Distanz, sobald der Handel profitabel ist. 15 Auf 0 setzen, um das Nachstellen zu deaktivieren.
CandleType Für die Indikatorberechnungen verwendeter Zeitrahmen. 5m time frame Bei Bedarf kann jedes andere DataType ausgewählt werden.

Implementierungshinweise

  • Die Strategie speichert alle Risikostufen (Stop-Loss, Take-Profit, Trailing Stop) intern und gibt Marktausstiege bei Kerzen aus bestätigen, dass eine Preisschwelle überschritten wurde. Dies spiegelt den MT4-Ansatz wider, bei dem Aufträge Tick für Tick geändert wurden.
  • Indikatorabonnements werden über Subscription.Bind verkabelt, wodurch sowohl Bulls Power als auch Bears Power in einen einzigen Rückruf eingespeist werden.
  • Die Punktgröße wird von Security.PriceStep abgeleitet, wodurch die Parameter mit Instrumenten kompatibel bleiben, die in Ticks notieren. Pips oder Cent.
  • Bei Eintrittsprüfungen werden immer die vorherigen Indikatorwerte verwendet, um sicherzustellen, dass teilweise gebildete Kerzen niemals Aufträge auslösen.

Unterschiede zur MQL-Version

  • Das Handelsmanagement nutzt explizite Marktaustritte, anstatt die bestehende Stop-Loss-Order zu ändern. Dies ist insgesamt robuster verschiedene StockSharp-Anschlüsse verwenden und dabei das gleiche Ergebnis erzielen.
  • Parameterbereiche werden durch StrategyParam-Helfer validiert, sodass ungültige Werte (z. B. negative Trailing Stops) ausgeschlossen sind zum Zeitpunkt der Konfiguration abgelehnt.
  • Detaillierte Protokollierungs-Hooks, Diagrammausgabe und Kerzenabonnements nutzen StockSharps High-Level-API anstelle manueller Tick-Loops.
  • Die im MT4-Skript vorhandene Experten-ID-Zeichenfolge ist in StockSharp nicht erforderlich und wurde daher weggelassen.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RobotPowerM5: RSI momentum with EMA filter and ATR stops.
/// </summary>
public class RobotPowerM5Meta4V12Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevRsi;
	private decimal _entryPrice;
	private int _cooldown;

	public RobotPowerM5Meta4V12Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");

		_emaLength = Param(nameof(EmaLength), 50)
			.SetDisplay("EMA Length", "Trend filter.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int RsiLength
	{
		get => _rsiLength.Value;
		set => _rsiLength.Value = value;
	}

	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevRsi = 0;
		_entryPrice = 0;
		_cooldown = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevRsi = 0;
		_entryPrice = 0;
		_cooldown = 0;

		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, ema, atr, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, ema);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (_prevRsi == 0 || atrVal <= 0)
		{
			_prevRsi = rsiVal;
			return;
		}

		if (_cooldown > 0) { _cooldown--; _prevRsi = rsiVal; return; }

		var close = candle.ClosePrice;

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || rsiVal > 80)
			{
				SellMarket();
				_entryPrice = 0;
				_cooldown = 10;
			}
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || rsiVal < 20)
			{
				BuyMarket();
				_entryPrice = 0;
				_cooldown = 10;
			}
		}

		if (Position == 0)
		{
			if (rsiVal > 65 && _prevRsi <= 65 && close > emaVal)
			{
				_entryPrice = close;
				BuyMarket();
				_cooldown = 10;
			}
			else if (rsiVal < 35 && _prevRsi >= 35 && close < emaVal)
			{
				_entryPrice = close;
				SellMarket();
				_cooldown = 10;
			}
		}

		_prevRsi = rsiVal;
	}
}