Auf GitHub ansehen

DeMarker gewinnt an Position Band 2 Strategie

Diese Strategie reproduziert den MetaTrader 5 Expertenberater „DeMarker gewinnt Positionsvolumen 2“ unter Verwendung des High-Levels API von StockSharp. Es analysiert eine konfigurierbare Kerzenreihe mit dem DeMarker-Oszillator und reagiert, wenn der Wert extreme Zonen erreicht. Die Implementierung behält den ursprünglichen Stil des Geldmanagements mit fester Lotgröße, optionaler Signalumkehr, integriertem Stop-Loss/Take-Profit-Handling und einem optionalen Handelssitzungsfilter bei.

Originelles Expertenverhalten

  • Plattform: MetaTrader 5.
  • Indikator: klassischer DeMarker-Oszillator (DEM), Standardperiode 14.
  • Einträge: Long-Positionen eröffnen, wenn DeMarker unter einen unteren Schwellenwert fällt, Short-Positionen öffnen, wenn er über einen oberen Schwellenwert steigt.
  • Risikokontrollen: fester Stop-Loss/Take-Profit, ausgedrückt in Punkten, optionaler Trailing-Stop mit Schritt, optionales Zeitfenster.
  • Positionsmanagement: Stellen Sie sicher, dass nur ein Trade pro Balken erfolgt und schließen Sie die Gegenseite, bevor Sie die Richtung ändern.

Die StockSharp-Konvertierung folgt den gleichen Prinzipien. Schutzaufträge werden mit StartProtection implementiert, sodass Stop-Loss, Take-Profit und Trailing automatisch verwaltet werden, sobald eine Position eröffnet wird.

Handelslogik

  1. Abonnieren Sie den konfigurierten Kerzentyp (CandleType, standardmäßig 5-Minuten-Kerzen) und berechnen Sie den DeMarker-Wert mit dem ausgewählten Zeitraum (DeMarkerPeriod).
  2. Wenn eine Kerze schließt, bewerten Sie den Oszillator:
    • Wenn ReverseSignals false ist (Standard):
      • Lange EinrichtungDeMarker <= LowerLevel.
      • Kurze EinrichtungDeMarker >= UpperLevel.
    • Wenn ReverseSignals wahr ist, werden die Long-/Short-Regeln vertauscht.
  3. Handeln Sie nur innerhalb des optionalen Sitzungsfensters, das durch SessionStart/SessionEnd definiert ist, wenn UseTimeFilter aktiviert ist. Übernachtungssitzungen werden unterstützt.
  4. Führen Sie höchstens einen neuen Eintrag pro Kerze aus. Bevor eine neue Position eröffnet wird, schließt die Strategie alle entgegengesetzten Bestände, um die MT5-Logik widerzuspiegeln.
  5. Die Lautstärke wird durch den Parameter TradeVolume festgelegt. Wenn die Strategie bereits teilweise in die gewünschte Richtung geht, wird auf das gewünschte Volumen aufgefüllt.

Risikomanagement

  • StopLossPoints und TakeProfitPoints (in Preisschritten) werden den punktbasierten Stop- und Take-Profit-Distanzen des Experten zugeordnet.
  • Durch die Aktivierung von EnableTrailing wird der Stoppabstand auf TrailingStopPoints umgeschaltet und die integrierte Nachlauf-Engine mit TrailingStepPoints als Anpassungsschritt aktiviert.
  • StartProtection ist mit useMarketOrders = true konfiguriert, sodass Schutzaufträge sofort ausgeführt werden, ähnlich dem MT5-Handelsschließungsverhalten.

Parameter

Parameter Beschreibung
DeMarkerPeriod Mittelungszeitraum des DeMarker-Indikators.
UpperLevel / LowerLevel Überkaufte/überverkaufte Schwellenwerte lösen Short-/Long-Positionen aus.
ReverseSignals Tauschen Sie Long- und Short-Konditionen aus.
StopLossPoints Anfänglicher Schutzstoppabstand, gemessen in Preisschritten.
TakeProfitPoints Take-Profit-Distanz gemessen in Preisschritten.
EnableTrailing Aktiviert den Trailing-Stop-Block.
TrailingStopPoints Abstand des Trailing Stops, sobald das Trailing aktiv ist.
TrailingStepPoints Minimale günstige Bewegung, bevor der Trailing Stop vorgeschoben wird.
UseTimeFilter Beschränkt den Handel auf das Fenster SessionStartSessionEnd.
SessionStart / SessionEnd Inklusive/exklusive Sitzungsgrenzen (unterstützt Wrap-Around).
TradeVolume Menge, die mit jeder Marktorder gesendet werden soll.
CandleType Zu analysierende Kerzenserie (Standard 5 Minuten).

Hinweise zur Implementierung

  • Der MT5-Experte hat einen Schwellenwert für die „nachlaufende Aktivierung“ einbezogen. Der Standard-Trailing-Schutz von StockSharp stellt nicht denselben Parameter bereit, daher wird das Trailing sofort aktiviert, wenn EnableTrailing wahr ist.
  • Die Fehlerbehandlung für ungültige Losgrößen, Einfrierniveaus und Bid/Ask-Aktualisierungslogik wird von der Infrastruktur von StockSharp übernommen und daher bei der Konvertierung nicht berücksichtigt.
  • Die Protokollierung erfolgt über die Basisklasse Strategy (rufen Sie LogInfo/LogError auf, wenn zusätzliche Ablaufverfolgung erforderlich ist).
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

/// <summary>
/// Strategy converted from "DeMarker gaining position volume 2" expert advisor.
/// Uses DeMarker oscillator thresholds for entry signals.
/// </summary>
public class DeMarkerGainingPositionVolume2Strategy : Strategy
{
	private readonly StrategyParam<int> _deMarkerPeriod;
	private readonly StrategyParam<decimal> _upperLevel;
	private readonly StrategyParam<decimal> _lowerLevel;
	private readonly StrategyParam<DataType> _candleType;

	private RelativeStrengthIndex _rsi;
	private decimal? _prevOscillator;

	/// <summary>
	/// DeMarker averaging period.
	/// </summary>
	public int DeMarkerPeriod
	{
		get => _deMarkerPeriod.Value;
		set => _deMarkerPeriod.Value = value;
	}

	/// <summary>
	/// Upper DeMarker threshold.
	/// </summary>
	public decimal UpperLevel
	{
		get => _upperLevel.Value;
		set => _upperLevel.Value = value;
	}

	/// <summary>
	/// Lower DeMarker threshold.
	/// </summary>
	public decimal LowerLevel
	{
		get => _lowerLevel.Value;
		set => _lowerLevel.Value = value;
	}

	/// <summary>
	/// Candle type for DeMarker calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public DeMarkerGainingPositionVolume2Strategy()
	{
		_deMarkerPeriod = Param(nameof(DeMarkerPeriod), 14)
			.SetDisplay("DeMarker Period", "Number of bars used by the oscillator.", "Indicator");

		_upperLevel = Param(nameof(UpperLevel), 0.7m)
			.SetDisplay("Upper Level", "Overbought threshold.", "Indicator");

		_lowerLevel = Param(nameof(LowerLevel), 0.3m)
			.SetDisplay("Lower Level", "Oversold threshold.", "Indicator");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for calculations.", "Data");
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevOscillator = null;
		_rsi = new RelativeStrengthIndex { Length = DeMarkerPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(_rsi, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_rsi.IsFormed)
		{
			_prevOscillator = rsiValue / 100m;
			return;
		}

		var oscillatorValue = rsiValue / 100m;

		var volume = Volume;
		if (volume <= 0)
			volume = 1;

		// Cross below lower level => oversold => buy
		if (_prevOscillator is decimal prev)
		{
			var crossBelow = prev >= LowerLevel && oscillatorValue < LowerLevel;
			var crossAbove = prev <= UpperLevel && oscillatorValue > UpperLevel;

			if (crossBelow)
			{
				if (Position <= 0)
					BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
			}
			else if (crossAbove)
			{
				if (Position >= 0)
					SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
			}
		}

		_prevOscillator = oscillatorValue;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_rsi = null;
		_prevOscillator = null;

		base.OnReseted();
	}
}