Auf GitHub ansehen

CashMachine-5-Minuten-Strategie

Überblick

Diese Strategie ist eine direkte Konvertierung des Expert Advisors CashMachine 5min von MQL auf die StockSharp High-Level-API. Sie ist für Fünf-Minuten-Kerzen ausgelegt und kombiniert den DeMarker-Indikator mit einem Stochastik-Crossover-Filter. Das Trade-Management verwendet versteckte Stop-Loss/Take-Profit-Levels zusammen mit stufenweisen Trailing-Regeln, die versuchen, Gewinne zu sichern, sobald Preismomentum erscheint.

Handelslogik

Einstiegsbedingungen

  • Long: Vorheriger DeMarker-Wert unter 0.30 und aktueller Wert bei oder über 0.30 und Stochastik-%K kreuzt über 20 auf derselben Kerze. Es darf keine Position offen sein.
  • Short: Vorheriger DeMarker-Wert über 0.70 und aktueller Wert bei oder unter 0.70 und Stochastik-%K kreuzt unter 80. Es darf keine Position offen sein.

Positionsmanagement

  • Es wird nur eine Position gleichzeitig gehalten; entgegengesetzte Signale werden ignoriert, bis der aktuelle Trade geschlossen ist.
  • Versteckte Exits schließen die Position, wenn der Preis Entry ± HiddenStopLoss oder Entry ± HiddenTakeProfit berührt (Werte in Pips interpretiert).
  • Drei Zwischengewinnziele (TargetTp1/2/3) bewegen einen versteckten Trailing Stop auf aktueller Preis - (Ziel - 13) Pips für Longs und aktueller Preis + (Ziel + 13) Pips für Shorts. Die zusätzlichen 13 Pips imitieren das ursprüngliche EA-Verhalten und sichern Gewinne nach jedem Meilenstein ohne sofortigen Ausstieg.
  • Wenn der Trailing Stop nach der Aktivierung berührt wird, wird die Position zum Marktpreis geschlossen.

Indikatoren

  • DeMarker – Erkennt Momentum-Umkehrungen; der Längenparameter entspricht dem ursprünglichen Mittelungsperiod.
  • Stochastik-Oszillator – Verwendet den ursprünglichen %K-Zeitraum (StochasticLength), %K-Glättung (StochasticK) und %D-Glättung (StochasticD).

Parameter

Name Beschreibung Standard
HiddenTakeProfit Versteckter Take-Profit-Abstand in Pips. 60
HiddenStopLoss Versteckter Stop-Loss-Abstand in Pips. 30
TargetTp1 Erster Trailing-Aktivierungslevel (Pips). 20
TargetTp2 Zweiter Trailing-Aktivierungslevel (Pips). 35
TargetTp3 Dritter Trailing-Aktivierungslevel (Pips). 50
DeMarkerLength DeMarker-Mittelungsperiode. 14
StochasticLength Stochastik-%K-Lookback-Periode. 5
StochasticK %K-Glättungslänge. 3
StochasticD %D-Glättungslänge. 3
CandleType Für Berechnungen verwendete Kerzenserie (Standard 5 Minuten). 5-Minuten-Zeitrahmen

Hinweise

  • Die Pip-Größe wird aus Security.PriceStep abgeleitet. Wenn der Schritt unbekannt ist, wird ein Fallback-Wert von 0.0001 verwendet, der die EA-Logik für 3- und 5-stellige Notierungen reproduziert.
  • Alle Handelsentscheidungen basieren auf abgeschlossenen Kerzen; das Intrabar-Verhalten des ursprünglichen EAs kann leicht abweichen, da die MQL-Version auf jedem Tick lief.
  • Die Strategie verlässt sich auf StockSharp's Standard-Ordervolumen-Handling — Strategy.Volume zum Steuern der Trade-Größe setzen.
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Cash Machine strategy: combines DeMarker and Stochastic oscillator crossovers
/// with staged profit protection using ATR-based distances.
/// </summary>
public class CashMachine5minStrategy : Strategy
{
	private readonly StrategyParam<decimal> _tpAtrMult;
	private readonly StrategyParam<decimal> _slAtrMult;
	private readonly StrategyParam<decimal> _trailAtrMult;
	private readonly StrategyParam<int> _deMarkerLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevDeMarker;
	private decimal? _prevRsi;
	private decimal _entryPrice;
	private decimal? _stopPrice;

	public decimal TpAtrMult { get => _tpAtrMult.Value; set => _tpAtrMult.Value = value; }
	public decimal SlAtrMult { get => _slAtrMult.Value; set => _slAtrMult.Value = value; }
	public decimal TrailAtrMult { get => _trailAtrMult.Value; set => _trailAtrMult.Value = value; }
	public int DeMarkerLength { get => _deMarkerLength.Value; set => _deMarkerLength.Value = value; }
	public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public CashMachine5minStrategy()
	{
		_tpAtrMult = Param(nameof(TpAtrMult), 2.5m)
			.SetGreaterThanZero()
			.SetDisplay("TP ATR Mult", "Take profit ATR multiplier", "Risk");

		_slAtrMult = Param(nameof(SlAtrMult), 1.5m)
			.SetGreaterThanZero()
			.SetDisplay("SL ATR Mult", "Stop loss ATR multiplier", "Risk");

		_trailAtrMult = Param(nameof(TrailAtrMult), 1.0m)
			.SetGreaterThanZero()
			.SetDisplay("Trail ATR Mult", "Trailing stop ATR multiplier", "Risk");

		_deMarkerLength = Param(nameof(DeMarkerLength), 14)
			.SetGreaterThanZero()
			.SetDisplay("DeMarker Length", "DeMarker period", "Indicators");

		_rsiLength = Param(nameof(RsiLength), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Length", "RSI period", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetGreaterThanZero()
			.SetDisplay("ATR Length", "ATR calculation period", "Indicators");

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

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevDeMarker = null;
		_prevRsi = null;
		_entryPrice = 0;
		_stopPrice = null;
	}

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

		var deMarker = new DeMarker { Length = DeMarkerLength };
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(deMarker, rsi, atr, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var close = candle.ClosePrice;

		// Manage position
		if (Position > 0)
		{
			// Trailing stop
			var trail = close - TrailAtrMult * atr;
			if (_stopPrice == null || trail > _stopPrice)
				_stopPrice = trail;

			// Take profit
			var tp = _entryPrice + TpAtrMult * atr;

			if (close <= _stopPrice || close >= tp)
			{
				SellMarket(Math.Abs(Position));
				_stopPrice = null;
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			var trail = close + TrailAtrMult * atr;
			if (_stopPrice == null || trail < _stopPrice)
				_stopPrice = trail;

			var tp = _entryPrice - TpAtrMult * atr;

			if (close >= _stopPrice || close <= tp)
			{
				BuyMarket(Math.Abs(Position));
				_stopPrice = null;
				_entryPrice = 0;
			}
		}

		// Entry signals
		if (Position == 0 && _prevDeMarker is decimal prevDe && _prevRsi is decimal prevRsi)
		{
			var longSignal = (prevDe < 0.25m && deMarker >= 0.25m) || (prevRsi < 25m && rsi >= 25m);
			var shortSignal = (prevDe > 0.75m && deMarker <= 0.75m) || (prevRsi > 75m && rsi <= 75m);

			if (longSignal)
			{
				BuyMarket();
				_entryPrice = close;
				_stopPrice = close - SlAtrMult * atr;
			}
			else if (shortSignal)
			{
				SellMarket();
				_entryPrice = close;
				_stopPrice = close + SlAtrMult * atr;
			}
		}

		_prevDeMarker = deMarker;
		_prevRsi = rsi;
	}
}