Auf GitHub ansehen

Breakeven V3 Manager

Übersicht

Der Breakeven V3 Manager ist eine Konvertierung des MetaTrader 5 Expertenberaters Breakeven v3 (barabashkakvn's edition). Das ursprüngliche Skript eröffnet keine Trades. Stattdessen berechnet es kontinuierlich das Portfolio-Break-Even-Level für das ausgewählte Symbol und verschiebt Schutzorders (Stop-Loss oder Take-Profit) für jede offene Long- und Short-Position, sodass das gesamte Buch rund um diesen Break-Even-Preis mit einem optionalen Puffer geschlossen wird.

Strategielogik

  • Break-Even-Rekonstruktion – jedes Mal, wenn ein Trade ausgeführt wird oder neue Kurse eintreffen, rekonstruiert die Strategie den gewichteten durchschnittlichen Eröffnungspreis für Long- und Short-Exposition separat. Sie berücksichtigt die positions-bezogenen Provisionen, die StockSharp in den MyTrade-Objekten meldet, um die MQL-Implementierung widerzuspiegeln.
  • Zielpreisberechnung – der Break-Even-Preis wird um Delta (points) MetaTrader-Punkte verschoben. Die Verschiebung wird addiert, wenn die Nettoposition long ist, und subtrahiert, wenn sie short ist, und repliziert damit den ursprünglichen "Delta"-Parameter.
  • Schutzorder-Platzierung
    • Wenn die Nettoposition long ist, wird ein Sell-Limit Take-Profit für das gesamte Long-Volumen und ein Buy-Stop Stop-Loss an das aggregierte Short-Volumen am selben Preis angehängt.
    • Wenn die Nettoposition short ist, wird ein Buy-Limit Take-Profit für das gesamte Short-Volumen und ein Sell-Stop Stop-Loss für etwaige Long-Absicherungen platziert.
    • Wenn beide Seiten flat sind, werden alle Schutzorders storniert.
  • Kursüberwachung und Diagnose – die Strategie abonniert Level1-Updates. Das neueste Bid/Ask wird verwendet, um Abstands-zum-Ziel-Statistiken und einen geschätzten schwebenden Gewinn zu berechnen. Wenn Enable Logging true ist, werden diese Werte in das Strategie-Log geschrieben, um die On-Chart-Kommentare der MQL-Version zu emulieren.

Parameter

  • Delta (points) – Offset, der auf den berechneten Break-Even-Preis angewendet wird. Der Wert wird in MetaTrader-Punkten ausgedrückt, d.h. ein Zehntel Pip bei fünfstelligen FX-Symbolen. Standard: 100.
  • Enable Logging – schaltet die detaillierte Log-Ausgabe um, die das aktuelle Break-Even-Level, den Abstand zum Ziel und den schwebenden PnL beschreibt. Standard: true.

Verwendungshinweise

  • Die Strategie ist ein Trade-Manager. Sie sollte auf einer bestehenden Strategie oder manuellen Position aufgesetzt werden. Sie wird selbst keine Market-Orders öffnen.
  • Beim Start inspiziert der Code das Portfolio und rekonstruiert ein einzelnes synthetisches Lot für jede Seite der Position unter Verwendung des von StockSharp gemeldeten Durchschnittspreises. Für beste Genauigkeit die Strategie immer laufen lassen, wenn neue Trades eröffnet werden.
  • Swap-Gebühren sind von StockSharp nicht verfügbar, daher wird beim Neuaufbau des Break-Even-Preises nur die Provisionsinfo berücksichtigt. Falls der Broker Overnight-Swaps anwendet, müssen diese manuell behandelt werden.
  • Das Skript setzt voraus, dass das Konto Hedging (gleichzeitige Long- und Short-Positionen) erlaubt. Wenn der Broker Positionen nettet, reduzieren sich die Long- und Short-Aggregate genau wie in MetaTrader auf eine einzelne Nettoexposition.
  • Es gibt keine Python-Version dieses Ports. Nur die C#-Implementierung wird bereitgestellt.
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>
/// Break-even management strategy that enters on EMA crossover and moves
/// the exit level to break-even once price moves a configurable distance in favor.
/// </summary>
public class BreakevenV3Strategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _activationPoints;
	private readonly StrategyParam<int> _deltaPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private decimal _breakEvenPrice;
	private bool _breakEvenActivated;
	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 ActivationPoints { get => _activationPoints.Value; set => _activationPoints.Value = value; }
	public int DeltaPoints { get => _deltaPoints.Value; set => _deltaPoints.Value = value; }

	public BreakevenV3Strategy()
	{
		_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");
		_activationPoints = Param(nameof(ActivationPoints), 200).SetNotNegative().SetDisplay("Activation", "Distance price must move before break-even activates", "Risk");
		_deltaPoints = Param(nameof(DeltaPoints), 100).SetNotNegative().SetDisplay("Delta", "Offset from entry for break-even stop", "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; _breakEvenPrice = 0;
		_breakEvenActivated = false; _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;

		// Manage break-even for open position
		if (Position != 0 && _entryPrice > 0)
		{
			var activationDistance = ActivationPoints * step;
			var deltaOffset = DeltaPoints * step;

			if (Position > 0)
			{
				if (!_breakEvenActivated && activationDistance > 0 && close >= _entryPrice + activationDistance)
				{
					_breakEvenActivated = true;
					_breakEvenPrice = _entryPrice + deltaOffset;
				}
				if (_breakEvenActivated && close <= _breakEvenPrice)
				{
					SellMarket();
					_entryPrice = 0; _breakEvenPrice = 0; _breakEvenActivated = false;
					_cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue;
					return;
				}
			}
			else if (Position < 0)
			{
				if (!_breakEvenActivated && activationDistance > 0 && close <= _entryPrice - activationDistance)
				{
					_breakEvenActivated = true;
					_breakEvenPrice = _entryPrice - deltaOffset;
				}
				if (_breakEvenActivated && close >= _breakEvenPrice)
				{
					BuyMarket();
					_entryPrice = 0; _breakEvenPrice = 0; _breakEvenActivated = false;
					_cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue;
					return;
				}
			}
		}

		// Entry: EMA crossover
		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_entryPrice = close; _breakEvenActivated = false; _cooldown = 100;
		}
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_entryPrice = close; _breakEvenActivated = false; _cooldown = 100;
		}

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}