Diese Strategie portiert den Expertenberater Trickerless RHMP von MetaTrader auf das hohe Niveau von StockSharp API. Es bleibt die Mehrstufigigkeit erhalten
Eingabelogik des ursprünglichen Roboters – Kombination aus Bestätigung des durchschnittlichen Richtungsindex, geglätteter gleitender Durchschnittsstruktur und
Volatilitätsgesteuertes Positionsmanagement – unter Einhaltung der in AGENTS.md dokumentierten Rahmenkonventionen.
Handelslogik
Indikatoren
Durchschnittlicher wahrer Bereich (ATR) mit konfigurierbarem Zeitraum für die Volatilitätsgröße.
Durchschnittlicher Richtungsindex (ADX) mit vollständigen +DI/-DI-Komponenten zur Qualifizierung der Trendstärke.
Zwei geglättete gleitende Durchschnitte (SMMA), die die schnellen und langsamen Trendfilter darstellen.
Trendauswertung
Die langsame SMMA-Steigung muss innerhalb des MinSlopePips…MaxSlopePips-Korridors liegen (gemessen in Instrumenten-Pips).
ADX muss AdxThreshold überschreiten und im Vergleich zur vorherigen Kerze steigen.
Der Preis muss mindestens TrendSpacePips vom schnellen SMMA entfernt bleiben, um eine Überlastung zu vermeiden.
Eine bullische Tendenz erfordert den schnellen SMMA über dem langsamen SMMA, +DI ≥ -DI und einen steigenden schnellen Durchschnitt. Die bärische Tendenz spiegelt dies wider
Schecks.
Primäre Einträge
Wenn die bullische (oder bärische) Tendenz aktiv ist, eröffnet die Strategie eine Long- (oder Short-)Order mit einem Volumen von OrderVolumeMaxNetPositions und mindestens SleepInterval Wartezeit zwischen den Einträgen.
Wenn eine entgegengesetzte Nettoposition vorhanden ist, wird diese zunächst abgeflacht, um die Absicherung deaktiviert zu halten.
Spike-Einträge
Wenn die aktuelle Kerzenspanne das CandleSpikeMultiplier-fache der vorherigen Spanne überschreitet, kann die Strategie eine Hilfskerze auslösen
Position in Richtung des Kerzenkörpers, wenn die ADX-Komponenten übereinstimmen. Die Position verwendet OrderVolume * SpikeVolumeMultiplier.
Risikomanagement
ATR-basierter Stop-Loss, Take-Profit und optionaler Trailing-Stop (StopLossAtrMultiplier, TakeProfitAtrMultiplier, TrailingAtrMultiplier).
Sitzungsweiter Schutz: Sobald der realisierte PnL DailyProfitTarget (Bruchteil des Startkapitals) erreicht, werden neue Einträge blockiert.
Der globale Notschalter EmergencyExit schließt beim Umschalten sofort alle Positionen.
Parameter
Name
Beschreibung
Standard
CandleType
Für alle Berechnungen verwendeter Zeitrahmen.
5-Minuten-Kerzen
OrderVolume
Basisvolumen für jeden Eintrag.
0,03
AtrPeriod
ATR Lookback-Länge.
14
AdxPeriod
ADX Lookback-Länge.
14
AdxThreshold
Mindestwert von ADX, um den Handel zu ermöglichen.
Mindestzeit zwischen aufeinanderfolgenden Einträgen.
24 Minuten
DailyProfitTarget
Bruchteil des anfänglichen Eigenkapitals, der den Handel blockiert, sobald er erreicht ist.
0,045
AllowNewEntries
Hauptschalter zum Aktivieren/Deaktivieren von Einträgen.
wahr
SpikeVolumeMultiplier
Volumenmultiplikator für Spitzeneinträge.
1,0
EmergencyExit
Schließt alle Positionen sofort, wenn wahr.
falsch
Notizen
Der StockSharp-Port konzentriert sich auf die saubere, hohe Ebene API anstelle der Ticket-für-Ticket-Mikroverwaltung von MetaTrader. Alle
Die Geldverwaltungslogik wird über Volume- und ATR-basierte Ebenen implementiert.
Das Original EA hatte mehrere Saldo- und Margenprüfungen. Diese werden mit DailyProfitTarget, MaxNetPositions angenähert.
und ATR Größenparameter, damit das Verhalten ohne direkte MT4-Kontoaufrufe angepasst bleibt.
Da die Strategie geglättete Durchschnittswerte verwendet, stellen Sie sicher, dass eine ausreichende Aufwärmphase vorhanden ist, bevor Sie Trades bewerten.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified from "Trickerless RHMP" MetaTrader expert.
/// Uses fast/slow EMA crossover for entries.
/// Fast EMA above slow = buy, below = sell.
/// </summary>
public class TrickerlessRhmpStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastMaPeriod;
private readonly StrategyParam<int> _slowMaPeriod;
private ExponentialMovingAverage _fastMa;
private ExponentialMovingAverage _slowMa;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastMaPeriod
{
get => _fastMaPeriod.Value;
set => _fastMaPeriod.Value = value;
}
public int SlowMaPeriod
{
get => _slowMaPeriod.Value;
set => _slowMaPeriod.Value = value;
}
public TrickerlessRhmpStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Primary timeframe", "General");
_fastMaPeriod = Param(nameof(FastMaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Fast MA", "Fast EMA period", "Indicators");
_slowMaPeriod = Param(nameof(SlowMaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow MA", "Slow SMA period (computed manually)", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
_fastMa = new ExponentialMovingAverage { Length = FastMaPeriod };
_slowMa = new ExponentialMovingAverage { Length = SlowMaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_fastMa, _slowMa, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _fastMa);
DrawIndicator(area, _slowMa);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_fastMa.IsFormed || !_slowMa.IsFormed)
{
_prevFast = fastValue;
_prevSlow = slowValue;
return;
}
if (_prevFast is null || _prevSlow is null)
{
_prevFast = fastValue;
_prevSlow = slowValue;
return;
}
var volume = Volume;
if (volume <= 0)
volume = 1;
var crossUp = _prevFast.Value <= _prevSlow.Value && fastValue > slowValue;
var crossDown = _prevFast.Value >= _prevSlow.Value && fastValue < slowValue;
if (crossUp)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
else if (crossDown)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
_prevFast = fastValue;
_prevSlow = slowValue;
}
/// <inheritdoc />
protected override void OnReseted()
{
_fastMa = null;
_slowMa = null;
_prevFast = null;
_prevSlow = null;
base.OnReseted();
}
}