Auf GitHub ansehen

Virtual-Profit-Close-Strategie

Überblick

Virtual Profit Close repliziert das Verhalten des MetaTrader 4 Expertenberaters Virtual_Profit_Close.mq4. Die Strategie beobachtet die aktuelle Position des konfigurierten Wertpapiers und beendet sich, sobald ein virtuelles Gewinnziel erreicht ist. Im Gegensatz zu einer regulären Take-Profit-Order Das Exit-Level wird intern ausgewertet, sodass keine Gewinnaufträge mehr im Auftragsbuch verbleiben. Ein konfigurierbarer Trailing Stop kann den Ausgang verschieben Der Preis nähert sich dem Markt an, wenn der Handel Gewinne erwirtschaftet. Im Testmodus kann die Strategie automatisch Probenpositionen öffnen um seine Logik zu demonstrieren.

Konvertierungshinweise

  • Tick-Ereignisse werden durch SubscribeTrades().Bind(ProcessTrade).Start() verbraucht, um die ursprüngliche OnTick-Routine nachzuahmen.
  • MetaTrader „Punkte“ werden in Pips umgewandelt, indem Security.PriceStep überprüft und für 3/5-stellige Symbole angepasst wird.
  • Virtuelle Gewinn- und Trailing-Berechnungen verwenden den aktuellen Geldkurs für Long-Positionen und den Briefkurs für Short-Positionen, passend zu MQL. Implementierung, die auf Bid- und Ask-Preisen beruhte.
  • Die Trailing-Stop-Logik wird nach der konfigurierten Gewinnschwelle aktiviert und hält den Stop in einem festen Abstand zum Markt Preis, ähnlich dem wiederholten Aufruf von OrderModify in MQL.
  • Ein Demonstrationsmodus ersetzt den ursprünglichen Strategietester-Helfer (SendTest), indem er Marktaufträge entsprechend der Auswahl öffnet Richtung und Lautstärke. Optionale Schutzstopps werden mit SetStopLoss platziert.

Parameter

Parameter Beschreibung
ProfitPips Virtuelles Take-Profit-Niveau, ausgedrückt in MetaTrader Pips. Die Strategie schließt die Position, sobald der Gewinn diese Distanz überschreitet.
UseTrailingStop Aktiviert das Nachlaufverhalten, wenn es auf true eingestellt ist.
TrailingOffsetPips Abstand zwischen dem aktuellen Preis und dem Trailing Stop, sobald dieser aktiv ist.
TrailingActivationPips Mindestgewinn in Pips erforderlich, bevor der Trailing Stop aktiviert wird.
EnableDemoMode Öffnet jedes Mal automatisch Demonstrationsaufträge, wenn die Position flach wird. Nützlich für Backtests.
DemoOrderDirection Richtung der Demo-Bestellungen (Buy oder Sell).
DemoOrderVolume Für Demobestellungen eingereichtes Volumen.
DemoStopPips Optionaler Schutzstopp für Demo-Orders, ausgedrückt in Pips.

Verhalten

  1. Wenn die Strategie startet, berechnet sie die Pip-Größe und die Abstände für Gewinn-, Trailing- und Demo-Stops.
  2. Jeder über ProcessTrade empfangene Tick wertet die aktuelle Position aus:
    • Long-Positionen werden geschlossen, wenn der Geldkurs den konfigurierten virtuellen Gewinn liefert.
    • Short-Positionen werden geschlossen, wenn der Briefkurs die gleiche Distanz in die entgegengesetzte Richtung zurücklegt.
  3. Wenn Trailing aktiviert ist und der Aktivierungsschwellenwert erreicht ist, bewegt sich der Trailing Stop zusammen mit der günstigen Preisbewegung. Einmal Wenn der Markt das nachlaufende Niveau überschreitet, sendet die Strategie einen Marktauftrag zum Ausstieg.
  4. Der Demomodus kann automatisch eine neue Position eröffnen, wenn die Strategie flach wird, und stellt so die Nur-Tester-Funktion von wieder her ursprünglicher Experte.

Anforderungen

  • Die Strategie benötigt Marktdaten auf Tick-Ebene, um präzise auf Preisänderungen reagieren zu können.
  • Der Strategieinstanz sollte nur ein Symbol zugewiesen werden. Mehrere gleichzeitige Symbole werden nicht unterstützt und entsprechen dem Original MQL-Implementierung, die das aktuelle Diagrammsymbol überwacht.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Virtual Profit Close strategy: EMA crossover with profit target management.
/// Enters on EMA crossover, closes when profit target is hit.
/// </summary>
public class VirtualProfitCloseStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;
	private decimal _entryPrice;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }

	public VirtualProfitCloseStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0m;
		_prevSlow = 0m;
		_hasPrev = false;
		_entryPrice = 0m;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;
		_entryPrice = 0;
		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;

		if (_hasPrev)
		{
			if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
			{
				BuyMarket();
				_entryPrice = close;
			}
			else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
			{
				SellMarket();
				_entryPrice = close;
			}
		}

		_prevFast = fast;
		_prevSlow = slow;
		_hasPrev = true;
	}
}