Diese Strategie ist eine direkte Portierung des MetaTrader 4 Expertenberaters up3x1_Investor. Es handelt ein einzelnes Instrument mit abgeschlossenen Kerzen aus einem konfigurierbaren Zeitrahmen (standardmäßig H1). Der Port repliziert die ursprüngliche Logik mit StockSharp High-Level-APIs und fügt klare Risikomanagementparameter hinzu.
Handelslogik
Die Strategie wertet die letzte vollständig geschlossene Kerze aus und prüft Folgendes:
Der Kerzenbereich (Hoch minus Tief) überschreitet 0.0060 Preiseinheiten.
Der Kerzenkörper (absolute Differenz zwischen Eröffnung und Schluss) überschreitet 0.0050 Preiseinheiten.
Wenn die Kerze bullisch schloss und die oben genannten Bedingungen erfüllt sind, eröffnet die Strategie eine Long-Marktposition.
Wenn die Kerze bärisch schloss und die Bedingungen erfüllt sind, eröffnet die Strategie eine Short-Marktposition.
Der Handel ist montags vollständig deaktiviert (um den Schutz DayOfWeek()==1 aus dem Code MQL widerzuspiegeln).
Positionsmanagement
Beim Eintritt legt die Strategie interne Ziele anhand der konfigurierten schrittbasierten Distanzen fest:
TakeProfitPoints → Distanz zum Gewinnziel.
StopLossPoints → Schutzstoppabstand.
TrailingStopPoints → Distanz, die verwendet wird, um den Stop zu verfolgen, sobald sich der Preis positiv bewegt.
Stopps und Ziele werden bei jeder fertigen Kerze ausgewertet:
Wenn der Preis das Ziel erreicht, wird die Position zum Zielpreis geschlossen.
Wenn der Preis den Stop erreicht, wird die Position geschlossen, um den Verlust zu begrenzen.
Sobald der Preis über die Trailing-Distanz hinaus steigt, wird der Stop näher an den Marktpreis verschoben, um einen Gewinn zu sichern.
Wenn außerdem die für dieselben Kerzen berechneten einfachen gleitenden Durchschnitte über 24 und 60 Perioden gleich werden (innerhalb eines Preisschritts), wird die Position sofort geschlossen. Dies ahmt die MQL-Logik nach, bei der die Order geschlossen wird, wenn beide Durchschnittswerte genau übereinstimmen.
Volumen- und Risikomanagement
BaseVolume definiert die Fallback-Losgröße, wenn keine kontobasierte Anpassung berechnet werden kann.
MaximumRisk repliziert die ursprüngliche AccountFreeMargin()*MaximumRisk/1000-Formel. Wenn der Portfoliowert verfügbar ist, schätzt die Strategie die Position auf value * MaximumRisk / 1000, gerundet auf eine Dezimalstelle.
DecreaseFactor imitiert die Loss-Streak-Reduktion: Nach mehr als einem aufeinanderfolgenden Verlust wird die Lautstärke proportional zu losses / DecreaseFactor verringert.
MinimumVolume stellt sicher, dass das Volumen niemals unter die kleinste handelbare Größe fällt, die im MQL-Skript verwendet wird (0,1 Lots).
Parameter
Name
Standard
Beschreibung
BaseVolume
0.1
Basispositionsgröße in Lots, wenn keine Risikoanpassung angewendet wird.
MaximumRisk
0.2
Risikofaktor, der zur Ableitung des Volumens aus dem Kontokapital verwendet wird (identisch mit dem ursprünglichen EA).
DecreaseFactor
3
Reduziert die Positionsgröße nach aufeinanderfolgenden Verlusten.
MinimumVolume
0.1
Kleinstes zulässiges Volumen.
TakeProfitPoints
20
Gewinnzielentfernung gemessen in Preisschritten.
StopLossPoints
50
Stop-Loss-Distanz gemessen in Preisschritten.
TrailingStopPoints
10
Trailing-Stop-Distanz, gemessen in Preisschritten.
SkipMondays
true
Deaktivieren Sie alle Handelsaktivitäten montags.
CandleType
1 hour
Zeitrahmen für das Kerzenabonnement.
Notizen
Die Strategie hält jeweils nur eine Position offen und entspricht dem ursprünglichen CalculateCurrentOrders-Guard.
Die Verfolgung aufeinanderfolgender Verluste erfolgt rein intern, da StockSharp-Broker die Auftragshistorie von MetaTrader nicht offenlegen.
Es werden keine ausstehenden Bestellungen verwendet; Alle Geschäfte werden als Marktaufträge über BuyMarket und SellMarket gesendet.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class Up3x1InvestorRangeFilterStrategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose; private decimal _prevEma; private bool _hasPrev;
private int _cooldown;
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Up3x1InvestorRangeFilterStrategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 14).SetDisplay("EMA Period", "EMA lookback", "Indicators");
_atrPeriod = Param(nameof(AtrPeriod), 14).SetDisplay("ATR Period", "ATR lookback", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = default;
_prevEma = default;
_hasPrev = default;
_cooldown = default;
}
/// <inheritdoc />
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ema)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) return;
var close = candle.ClosePrice;
if (!_hasPrev) { _prevClose = close; _prevEma = ema; _hasPrev = true; return; }
if (_cooldown > 0)
{
_cooldown--;
_prevClose = close; _prevEma = ema;
return;
}
if (_prevClose <= _prevEma && close > ema && Position <= 0)
{
var volume = Volume + Math.Abs(Position);
BuyMarket(volume);
_cooldown = 6;
}
else if (_prevClose >= _prevEma && close < ema && Position >= 0)
{
var volume = Volume + Math.Abs(Position);
SellMarket(volume);
_cooldown = 6;
}
_prevClose = close; _prevEma = ema;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class up3x1_investor_range_filter_strategy(Strategy):
def __init__(self):
super(up3x1_investor_range_filter_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 14).SetDisplay("EMA Period", "EMA lookback", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_close = 0.0; self._prev_ema = 0.0; self._has_prev = False; self._cooldown = 0
@property
def ema_period(self): return self._ema_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(up3x1_investor_range_filter_strategy, self).OnReseted()
self._prev_close = 0.0; self._prev_ema = 0.0; self._has_prev = False; self._cooldown = 0
def OnStarted2(self, time):
super(up3x1_investor_range_filter_strategy, self).OnStarted2(time)
self._has_prev = False; self._cooldown = 0
ema = ExponentialMovingAverage(); ema.Length = self.ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self.process_candle).Start()
def process_candle(self, candle, ema):
if candle.State != CandleStates.Finished: return
if not self.IsFormedAndOnlineAndAllowTrading(): return
close = float(candle.ClosePrice); ema_val = float(ema)
if not self._has_prev:
self._prev_close = close; self._prev_ema = ema_val; self._has_prev = True; return
if self._cooldown > 0:
self._cooldown -= 1; self._prev_close = close; self._prev_ema = ema_val; return
if self._prev_close <= self._prev_ema and close > ema_val and self.Position <= 0:
volume = self.Volume + abs(self.Position)
self.BuyMarket(volume); self._cooldown = 6
elif self._prev_close >= self._prev_ema and close < ema_val and self.Position >= 0:
volume = self.Volume + abs(self.Position)
self.SellMarket(volume); self._cooldown = 6
self._prev_close = close; self._prev_ema = ema_val
def CreateClone(self): return up3x1_investor_range_filter_strategy()