Auf GitHub ansehen

Trading Criteria-Strategie

Übersicht

Die Trading Criteria-Strategie ist ein Multi-Zeitrahmen-Trendfolge-Ansatz, der aus dem ursprünglichen MQL4-Expertenberater "Trading Criteria" konvertiert wurde. Der Port basiert auf linear gewichteten gleitenden Durchschnitten, Momentum-Abweichungsfiltern und MACD-Bestätigungen aus Trend- und Monats-Zeitrahmen. Risikomanagement-Funktionen umfassen Trailing Stops, Break-Even-Schutz und konfigurierbare Stop-Loss/Take-Profit-Ziele.

Einstiegslogik

  1. Primärer Zeitrahmen: Verwendet einen schnellen und langsamen linear gewichteten gleitenden Durchschnitt (LWMA). Long-Signale erfordern, dass der schnelle MA über dem langsamen bleibt; Short-Signale erfordern das Gegenteil.
  2. Momentum-Filter: Berechnet die Momentum-Abweichung (|Momentum-100|) auf dem Trend-Zeitrahmen und prüft die drei neuesten Werte gegen bullische oder bärische Schwellenwerte.
  3. Trend-MACD-Filter: Bewertet die MACD-Hauptlinie relativ zur Signallinie auf demselben Trend-Zeitrahmen. Signale werden nur ausgelöst wenn die aktuelle Beziehung mit der vorherigen Bar übereinstimmt, um schnelle Wechsel zu vermeiden.
  4. Monatlicher MACD-Filter: Bestätigt die größere Richtungsneigung mit MACD auf einem monatlichen (oder benutzerspezifizierten langsamen) Zeitrahmen.
  5. Positions-Exposure: Begrenzt die maximale Netto-Positionsgröße auf MaxPositions * Volume. Wenn ein neues Signal erscheint während eine entgegengesetzte Position gehalten wird, wird die Strategie zuerst die Exposure durch Kauf oder Verkauf ausreichenden Volumens neutralisieren.

Ausstieg und Risikomanagement

  • Stop Loss / Take Profit: Via StopLossPoints und TakeProfitPoints definiert, in tatsächliche Preis-Offsets unter Verwendung der normalisierten Pip-Größe des Instruments umgerechnet.
  • Trailing Stop: Mit EnableTrailing und TrailingStopPoints aktiviert. Für Longs verfolgt der Stop den höchsten Preis minus der Trailing-Distanz sobald die Bewegung den Schwellenwert überschreitet; Shorts spiegeln die Logik mit dem niedrigsten Preis.
  • Break-Even-Bewegung: Wenn aktiviert (EnableBreakEven), migriert der Stop zum Einstiegspreis plus einem optionalen Offset, sobald der Schlusskurs die Distanz BreakEvenTriggerPoints zugunsten der offenen Position erreicht.
  • Manuelle Schutzausstiege: Wenn die Kerze die berechneten Stop- oder Zielniveaus berührt, schließt die Strategie die gesamte Nettoposition auf dieser Bar.

Parameter

Parameter Beschreibung
CandleType Basis-Zeitrahmen für Signalgenerierung und gleitende Durchschnitte.
TrendCandleType Zeitrahmen für Momentum- und MACD-Filter.
MonthlyCandleType Langsamer Zeitrahmen für langfristige MACD-Bestätigung.
FastMaPeriod / SlowMaPeriod Längen des schnellen und langsamen LWMA auf dem Einstiegs-Zeitrahmen.
MomentumPeriod Momentum-Lookback-Periode auf dem Trend-Zeitrahmen.
MomentumBuyThreshold / MomentumSellThreshold Mindestabweichung von 100 für Long- oder Short-Einstiege.
MaxPositions Maximale Anzahl der Basis-Lots die gleichzeitig offen sein können.
StopLossPoints / TakeProfitPoints Abstände in Punkten für Schutz-Stops und Gewinnziele.
EnableTrailing / TrailingStopPoints Aktiviert Trailing Stops und setzt ihre Distanz.
EnableBreakEven Aktiviert Break-Even-Verhalten.
BreakEvenTriggerPoints / BreakEvenOffsetPoints Steuert wie weit der Preis sich bewegen muss bevor der Stop auf Break-Even wechselt und welchen Offset anwenden.

Verwendungshinweise

  • Die Strategie an ein Instrument mit geeigneter Kerzen-Serien-Unterstützung für die gewählten Zeitrahmen anhängen.
  • Sicherstellen, dass das Wertpapier einen genauen PriceStep bereitstellt; die Implementierung passt Fraktional-Pip-Instrumente (3 oder 5 Dezimalstellen) an MQL-Konventionen an.
  • Trailing- und Break-Even-Schutz operieren auf abgeschlossenen Kerzen. In schnellen Märkten können Schutzniveaus auf der folgenden Bar ausgeführt werden wenn eine Lücke auftritt.
  • Der Standard-Parametersatz spiegelt die veröffentlichten MQL-Inputs wider, kann aber über die integrierten Parameter-Metadaten optimiert werden.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

public class TradingCriteriaStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public TradingCriteriaStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}