Die Markterfassungs-Strategie reproduziert die Logik des ursprünglichen MetaTrader 5-Experten. Der Algorithmus baut ein dynamisches Grid rund um einen beweglichen Zentrumspreis auf und eröffnet Hedge-artige Trades, wenn der Preis um dieses Zentrum schwingt. Positionen werden ober- und unterhalb des Zentrums mit festen Gewinnzielen verteilt, während Eigenkapital-Meilensteine des Kontos kontrollieren, wann die am stärksten verlierenden Trades liquidiert werden.
Handelsregeln
Zentrumslinie – die Strategie speichert ein internes Zentrumsniveau, das beim Schlusskurs der ersten verarbeiteten Kerze beginnt. Wenn der Markt weiter als der konfigurierte Grid-Abstand abweicht, wird das Zentrum schrittweise verschoben, um dem Preis zu folgen.
Initialer Short – eine optionale Short-Position kann unmittelbar nach dem Start eröffnet werden, um das Verhalten des MQL-Skripts zu entsprechen.
Long-Einstiege – ein Long-Trade ist erlaubt, wenn der letzte Schlusskurs über dem Zentrum liegt und die vorherige Kerze darunter gehandelt hat. Eine Näheprüfung stellt sicher, dass kein anderer Long-Trade in der Nähe desselben Niveaus aktiv ist.
Short-Einstiege – ein Short-Trade ist erlaubt, wenn der letzte Schlusskurs unter dem Zentrum liegt und die vorherige Kerze darüber gehandelt hat. Derselbe Nähefilter verhindert das Stapeln identischer Shorts.
Take Profit – jeder Trade speichert ein Zielniveau, das ein festes Vielfaches des Instrument-Preisschritts vom Einstiegspreis entfernt ist. Kerzenhochs (für Longs) oder Kerzenchiefs (für Shorts), die das Ziel erreichen, lösen einen Marktausstieg aus.
Eigenkapital-Management – die Strategie überwacht das Portfolio-Eigenkapital. Nach einem konfigurierbaren prozentualen Gewinn schließt sie eine Anzahl der am schlechtesten laufenden Trades, um Gewinne zu sichern. Ein weiterer Prozentschwellenwert definiert, wann das Risiko während eines Rückgangs durch Liquidierung verlierender Trades reduziert werden soll. Jedes Mal, wenn ein Schwellenwert ausgelöst wird, wird die Eigenkapital-Basislinie neu berechnet.
Parameter
Enable Long / Enable Short – Trades in jede Richtung erlauben oder blockieren.
Grid Steps – Abstand zwischen Grid-Niveaus, gemessen in Preisschritten.
Take Profit Steps – Take-Profit-Distanz in Preisschritten.
Open Initial Short – die erste Short-Order, die sofort nach dem Start platziert wird, aktivieren.
Use Equity Target – Eigenkapitalwachstumsregel zum Trimmen verlierender Trades aktivieren.
Track Drawdown – Rückgangsregel zum Trimmen verlierender Trades aktivieren.
Equity Gain % / Equity Loss % – Eigenkapitaländerungsprozentzahlen, die die obigen Regeln auslösen.
Loss Trades Up / Loss Trades Down – maximale Anzahl verlierender Trades, die beim Auslösen jeder Regel geschlossen werden.
Candle Type – Zeitrahmen oder benutzerdefinierter Kerzentyp für den Entscheidungsprozess.
Volume (Strategie-Eigenschaft) – Handelsgröße für jede Marktorder.
Hinweise
Die Strategie führt ein internes Register offener Trades, um den Hedging-Stil des ursprünglichen Experten nachzuahmen, während sie mit dem Netto-Positionsmodell von StockSharp arbeitet.
Abstandsparameter werden mit dem Instrument-Preisschritt multipliziert; stellen Sie sicher, dass das ausgewählte Instrument einen gültigen PriceStep-Wert exponiert.
Die Logik arbeitet nur mit abgeschlossenen Kerzen. Wählen Sie einen Kerzentyp, der dem beabsichtigten Handelshorizont entspricht, von sehr kurzfristigen Grids bis zu breiteren Swing-Grids.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Market capture strategy using EMA crossover to capture market direction changes.
/// </summary>
public class MarketCaptureStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
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 MarketCaptureStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fast;
_prevSlow = slow;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast;
_prevSlow = slow;
if (!prevAbove && currAbove)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
else if (prevAbove && !currAbove)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class market_capture_strategy(Strategy):
def __init__(self):
super(market_capture_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 8) \
.SetDisplay("Fast Period", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 21) \
.SetDisplay("Slow Period", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(market_capture_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(market_capture_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastPeriod
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif prev_above and not curr_above:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return market_capture_strategy()