Die einfachste DeMarker-Strategie reproduziert die Logik des ursprünglichen MetaTrader-Expertenberaters. Es verfolgt den DeMarker-Oszillator, um zu erkennen, wann die Preisdynamik überkaufte oder überverkaufte Zonen verlässt. Wenn der Oszillator wieder in den neutralen Bereich zurückkehrt, eröffnet die Strategie eine Position in Richtung der erwarteten Umkehr und steuert gleichzeitig das Risiko über konfigurierbare Stop-Loss- und Take-Profit-Abstände.
Kernlogik
Abonnieren Sie Kerzen des ausgewählten Zeitrahmens und berechnen Sie den DeMarker-Indikator mit dem konfigurierten Zeitraum.
Markieren Sie den Marktzustand als überkauft, wenn der vorherige DeMarker-Wert über dem überkauften Schwellenwert liegt, und als überverkauft, wenn er unter dem überverkauften Schwellenwert liegt.
Erzeugen Sie Signale, wenn der aktuelle DeMarker-Wert wieder in den neutralen Bereich zurückkehrt:
Verkaufen Sie, wenn der Oszillator unter das überkaufte Niveau fällt, nachdem er zuvor darüber gelegen hat.
Kaufen Sie, wenn der Oszillator über den überverkauften Wert steigt, nachdem er zuvor darunter lag.
Platzieren Sie jeweils nur eine Position. Wenn Trade On Bar Open aktiviert ist, wird die Bestellung verzögert, bis der nächste Balken geöffnet wird. andernfalls wird die Position sofort beim aktuellen Schlusskurs des Balkens eingegeben.
Wenden Sie Stop-Loss- und Take-Profit-Orders mithilfe des integrierten Schutzdienstes an, um die festen Abstände der MQL-Version nachzuahmen.
Parameter
Volumen – Bestellgröße in Losen/Verträgen.
DeMarker-Periode – Periode des DeMarker-Oszillators.
Überkauft-Level – oberer DeMarker-Schwellenwert, der überkaufte Bedingungen definiert.
Überverkauft-Level – unterer DeMarker-Schwellenwert, der überverkaufte Bedingungen definiert.
Trade On Bar Open – wenn aktiviert, werden Eingaben bei der nächsten Baröffnung und nicht sofort ausgeführt.
Stop-Loss-Punkte – schützende Stop-Loss-Distanz, ausgedrückt in Preispunkten.
Take Profit Points – Gewinnzieldistanz ausgedrückt in Preispunkten.
Kerzentyp – Kerzentyp (Zeitrahmen), der für Indikatorberechnungen verwendet wird.
Money-Management
Stop-Loss- und Take-Profit-Orders werden automatisch über StartProtection registriert, wobei die Distanzen in Preispunkte umgewandelt werden.
Es kann jeweils nur eine Position aktiv sein. Neue Signale werden ignoriert, solange eine Position besteht.
Diagrammelemente
Preiskerzen für das ausgewählte Abonnement.
Die DeMarker-Indikatorkurve.
Eigene Handelsmarkierungen zur visuellen Validierung von Ein- und Ausgängen.
Notizen
Verwenden Sie Instrumente mit ausreichend hoher Liquidität, um die Qualität der Stop-Loss- und Take-Profit-Ausführung sicherzustellen.
Das Flag Trade On Bar Open entspricht in etwa dem ursprünglichen Verhalten des Expert Advisors, der auf einen neuen Balken wartet, bevor er die Bestellung sendet.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Simplest DeMarker strategy: DeMarker oscillator crossover.
/// Buys when DeMarker crosses above oversold, sells when crosses below overbought.
/// </summary>
public class SimplestDeMarkerStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _demarkerPeriod;
private readonly StrategyParam<decimal> _oversold;
private readonly StrategyParam<decimal> _overbought;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevValue;
private int _candlesSinceTrade;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int DemarkerPeriod { get => _demarkerPeriod.Value; set => _demarkerPeriod.Value = value; }
public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public SimplestDeMarkerStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_demarkerPeriod = Param(nameof(DemarkerPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("DeMarker Period", "DeMarker period", "Indicators");
_oversold = Param(nameof(Oversold), 0.2m)
.SetDisplay("Oversold", "DeMarker oversold level", "Signals");
_overbought = Param(nameof(Overbought), 0.8m)
.SetDisplay("Overbought", "DeMarker overbought level", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevValue = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevValue = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
var demarker = new DeMarker { Length = DemarkerPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(demarker, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal demarkerValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_hasPrev)
{
if (_prevValue < Oversold && demarkerValue >= Oversold && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevValue > Overbought && demarkerValue <= Overbought && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevValue = demarkerValue;
_hasPrev = true;
}
}