Auf GitHub ansehen

Doji-Trader-Strategie

Diese Strategie wandelt den MQL4 „DojiTrader“ Expert Advisor in ein StockSharp C#-Beispiel um. Es sucht nach aktuellen Doji-Kerzen und handelt mit einem Ausbruch aus der Doji-Range während der wichtigsten Sitzungen in Europa und den USA.

Handelslogik

  • Die Strategie verarbeitet nur fertige Kerzen aus dem ausgewählten Zeitrahmen (standardmäßig 30-Minuten-Kerzen).
  • Der Handel ist nur zwischen 08:00 und 17:00 Uhr Plattformzeit gestattet.
  • Während er flach ist, blickt er auf drei abgeschlossene Kerzen zurück und merkt sich den letzten Doji (Eröffnungspreis entspricht Schlusspreis).
  • Wenn die Kerze unmittelbar nach dem Doji über dem Doji-Hoch schließt, ist ein langer Ausbruch möglich. Wenn es unter dem Doji-Tief schließt, ist ein kurzer Ausbruch möglich.
  • Sobald eine nachfolgende Kerze über dem Aktivierungspreis schließt, sendet die Strategie eine Marktorder in Ausbruchsrichtung.
  • Nach dem Eintritt wird der Doji-Bereich zur Austrittskontrolle beibehalten. Die Position wird geschlossen, wenn:
    • Die vorherige Kerze schließt wieder innerhalb der Spanne (Long: knapp unter dem Doji-Tief, Short: knapp über dem Doji-Hoch).
    • Die Candle-Extreme erreichen die synthetischen Stop-Loss- oder Take-Profit-Niveaus, die die ursprünglichen MQL4-Fixkomma-Ausstiege nachahmen.

Parameter

  • Auftragsvolumen – für Marktaufträge verwendetes Volumen.
  • Take Profit (Schritte) – Abstand zum Gewinnziel gemessen in Preisschritten.
  • Stop-Loss (Schritte) – Abstand zum Schutzstopp in Preisschritten.
  • Kerzentyp – Zeitrahmen der Kerzen, die zur Signalerkennung verwendet werden.

Die Stop-Loss- und Take-Profit-Berechnungen basieren auf dem Wertpapierpreisschritt und emulieren den ursprünglichen EA, der feste Pip-Abstände verwendete. Wenn innerhalb der letzten drei Kerzen kein gültiger Doji vorhanden ist, wird der Ausbruchsstatus gelöscht und die Suche beginnt erneut.

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>
/// Doji Trader breakout strategy.
/// Detects doji candles and enters on breakout of doji range.
/// Uses SMA as trend filter for direction.
/// </summary>
public class DojiTraderBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<decimal> _dojiRatio;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevHigh;
	private decimal _prevLow;
	private bool _prevWasDoji;
	private bool _hasPrev;

	public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
	public decimal DojiRatio { get => _dojiRatio.Value; set => _dojiRatio.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public DojiTraderBreakoutStrategy()
	{
		_smaPeriod = Param(nameof(SmaPeriod), 20)
			.SetDisplay("SMA Period", "SMA period for trend filter", "Indicators");

		_dojiRatio = Param(nameof(DojiRatio), 0.25m)
			.SetDisplay("Doji Ratio", "Max body/range ratio for doji detection", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevHigh = 0m; _prevLow = 0m; _prevWasDoji = false; _hasPrev = false; }

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_hasPrev = false;
		_prevWasDoji = false;

		var sma = new SimpleMovingAverage { Length = SmaPeriod };

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

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

		var range = candle.HighPrice - candle.LowPrice;
		var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
		var isDoji = range > 0 && body / range < DojiRatio;

		if (_hasPrev && _prevWasDoji)
		{
			// Bullish breakout above doji high with SMA confirmation
			if (candle.ClosePrice > _prevHigh && candle.ClosePrice > sma && Position <= 0)
			{
				if (Position < 0)
					BuyMarket();
				BuyMarket();
			}
			// Bearish breakout below doji low with SMA confirmation
			else if (candle.ClosePrice < _prevLow && candle.ClosePrice < sma && Position >= 0)
			{
				if (Position > 0)
					SellMarket();
				SellMarket();
			}
		}

		_prevHigh = candle.HighPrice;
		_prevLow = candle.LowPrice;
		_prevWasDoji = isDoji;
		_hasPrev = true;
	}
}