Schließen Sie den Gewinn oder Verlust in der Kontowährung ab
Diese Strategie reproduziert den Expertenberater MetaTrader Close_on_PROFIT_or_LOSS_inAccont_Currency. Es überwacht kontinuierlich das Portfolio-Eigenkapital, an das die Strategie gebunden ist, und sobald ein konfiguriertes Gewinnziel oder eine Drawdown-Untergrenze erreicht ist, wird jede offene Position liquidiert und alle von der Strategie verwalteten ausstehenden Aufträge storniert. Die Klasse basiert auf dem hohen Level API von StockSharp: Ein Kerzenabonnement sorgt für den Herzschlag, CancelActiveOrders() entfernt Arbeitsaufträge und ClosePosition() glättet das Engagement durch Marktaufträge.
Wie es funktioniert
Die Strategie fragt immer dann das aktuelle Eigenkapital (Portfolio.CurrentValue) ab, wenn eine Heartbeat-Kerze geschlossen wird.
Wenn das Eigenkapital größer oder gleich Positive Closing ist, sendet die Strategie eine vollständige Close-Anfrage.
Wenn das Eigenkapital kleiner oder gleich dem Negative Closing ist, wird die gleiche Liquidationsroutine ausgeführt, um die Verluste zu begrenzen.
Während der Liquidation storniert die Strategie jeden ausstehenden Auftrag, sendet Marktaufträge zum Schließen aller aktiven Positionen und stoppt sich schließlich selbst (was den ExpertRemove()-Aufruf des ursprünglichen EA widerspiegelt).
Wichtig: Legen Sie die Schwellenwerte in der Kontowährung fest. Um das ursprüngliche Verhalten zu emulieren, wählen Sie einen Positive-Closure-Wert über dem aktuellen Eigenkapital und einen Negative-Closure-Wert darunter; andernfalls wird der Exit sofort beim Start ausgelöst.
Parameter
Name
Beschreibung
Standard
PositiveClosureInAccountCurrency
Eigenkapitalniveau, bei dessen Überschreitung eine Vollliquidation ausgelöst wird.
0
NegativeClosureInAccountCurrency
Eigenkapitaluntergrenze, die bei Erreichen die Liquidation erzwingt.
0
CandleType
Zeitrahmen, der für die Heartbeat-Kerzen verwendet wird, die die Eigenkapitalprüfungen steuern. Reduzieren Sie es für schnellere Reaktionen.
1 minute
Notizen
StartProtection() wird beim Start aktiviert, um das ursprüngliche Sicherheitsverhalten zu kopieren.
Die Strategie interagiert nur mit den von ihr verwalteten Positionen und Aufträgen; Fügen Sie es dem Portfolio hinzu, das die Trades enthält, die Sie schützen möchten.
Es gibt keine separate Spread-/Slippage-Eingabe, da StockSharp Marktaufträge bereits konnektorspezifische Ausführungskosten berücksichtigen.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
using StockSharp.Algo.Candles;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Closes all positions when portfolio equity reaches configured profit or loss thresholds.
/// Pending orders are cancelled before liquidating the exposure.
/// </summary>
public class CloseOnProfitOrLossInAccountCurrencyStrategy : Strategy
{
private readonly StrategyParam<decimal> _positiveClosure;
private readonly StrategyParam<decimal> _negativeClosure;
private readonly StrategyParam<DataType> _candleType;
private bool _closeRequested;
private SimpleMovingAverage _smaFast;
private SimpleMovingAverage _smaSlow;
/// <summary>
/// Equity level in account currency that triggers closing all positions when exceeded.
/// </summary>
public decimal PositiveClosureInAccountCurrency
{
get => _positiveClosure.Value;
set => _positiveClosure.Value = value;
}
/// <summary>
/// Equity level in account currency that triggers closing all positions when reached on drawdown.
/// </summary>
public decimal NegativeClosureInAccountCurrency
{
get => _negativeClosure.Value;
set => _negativeClosure.Value = value;
}
/// <summary>
/// Candle type used as a heartbeat to evaluate portfolio equity.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="CloseOnProfitOrLossInAccountCurrencyStrategy"/> class.
/// </summary>
public CloseOnProfitOrLossInAccountCurrencyStrategy()
{
_positiveClosure = Param(nameof(PositiveClosureInAccountCurrency), 0m)
.SetDisplay("Positive Closure", "Equity level that triggers full liquidation", "Risk");
_negativeClosure = Param(nameof(NegativeClosureInAccountCurrency), 0m)
.SetDisplay("Negative Closure", "Equity floor that forces liquidation", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Heartbeat Candle", "Candle type that triggers equity checks", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
if (Security == null)
return Array.Empty<(Security, DataType)>();
return new (Security, DataType)[] { (Security, CandleType) };
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
if (Portfolio == null)
throw new InvalidOperationException("Portfolio cannot be null.");
if (Security == null)
throw new InvalidOperationException("Security must be set to subscribe for candles.");
_smaFast = new SimpleMovingAverage { Length = 10 };
_smaSlow = new SimpleMovingAverage { Length = 30 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_smaFast, _smaSlow, ProcessCandleWithIndicators)
.Start();
}
private void ProcessCandleWithIndicators(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (fast > slow && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (fast < slow && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
}
private void RequestCloseAll(string reason)
{
if (_closeRequested)
return;
_closeRequested = true;
LogInfo(reason);
// Cancel any pending orders to avoid unexpected executions during liquidation.
CancelActiveOrders();
foreach (var position in Positions.ToArray())
{
var value = GetPositionValue(position.Security, Portfolio) ?? 0m;
if (value == 0m)
continue;
// Submit a market order opposite to the current exposure.
ClosePosition(position.Security);
}
// Stop the strategy after sending exit orders, mirroring ExpertRemove behavior.
Stop();
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class close_on_profit_or_loss_in_account_currency_strategy(Strategy):
"""
SMA crossover strategy with equity-based closure.
Uses fast/slow SMA crossover for entries.
"""
def __init__(self):
super(close_on_profit_or_loss_in_account_currency_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Heartbeat Candle", "Candle type that triggers equity checks", "General")
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(close_on_profit_or_loss_in_account_currency_strategy, self).OnStarted2(time)
sma_fast = SimpleMovingAverage()
sma_fast.Length = 10
sma_slow = SimpleMovingAverage()
sma_slow.Length = 30
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma_fast, sma_slow, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma_fast)
self.DrawIndicator(area, sma_slow)
self.DrawOwnTrades(area)
def on_process(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
if fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return close_on_profit_or_loss_in_account_currency_strategy()