Auf GitHub ansehen

Flache Trendstrategie

Überblick

Die Flat-Trend-Strategie reproduziert die Kernideen des ursprünglichen Flat-Trend-Expertenberaters durch die Kombination von Multi-Speed-Trendfiltern, ADX-Bestätigung und einem Standardabweichungs-„Saft“-Breakout-Filter. Die Strategie konzentriert sich darauf, den Moment zu erkennen, in dem der Preis eine Schwankungsphase verlässt und das Momentum zunimmt, sodass er Richtungsbewegungen mit dynamischem Positionsschutz verbinden kann.

Handelslogik

  1. Trendfilter – drei exponentielle gleitende Durchschnitte (EMAs) mit konfigurierbarer Länge stellen den Auslöser, den ersten Filter und den zweiten Filter dar. Ihre Steigung und die Preisposition relativ zu jedem EMA werden in Zustände übersetzt:
    • Stark bullisch (Preis über EMA und EMA steigend).
    • Moderat bullisch (Preis über EMA, aber Steigung neutral).
    • Stark bärisch (Preis unter EMA und EMA fallend).
    • Mäßig rückläufig (Preis unter EMA, aber Steigung neutral).
  2. Eintrittsregeln
    • Long-Trades erfordern bullische Zustände am Auslöser und Filter EMA. Der zweite Filter kann optional ignoriert werden. Der strikte Modus erzwingt die Verwendung nur starker bullischer Staaten.
    • Short-Trades spiegeln die Bedingungen für bärische Zustände wider.
    • Die optionale ADX-Bestätigung stellt sicher, dass der durchschnittliche Richtungsindex einen Schwellenwert überschreitet und, wenn aktiviert, die +DI- und –DI-Komponenten mit der Handelsrichtung übereinstimmen.
    • Der „Saft“-Filter überprüft, ob die Standardabweichung der Preise über einem benutzerdefinierten Ausbruchsniveau liegt, und verhindert so Trades in Phasen flacher Volatilität.
    • Der Handel kann auf ein ausgewähltes Intraday-Fenster beschränkt werden.
  3. Ausgangsregeln
    • Entgegengesetzte Trendzustände am Auslöser EMA initiieren einen Exit. Im strikten Modus wartet die Strategie auf das stärkste Gegensignal.
    • Dynamische Stopps bei Ausstiegspositionen immer dann, wenn der Preis das berechnete Stop-Level berührt.

Risikomanagement

  • Erster Stopp – wird entweder aus einer statischen Pip-Distanz oder aus dem Average True Range (ATR)-Wert berechnet und emuliert die ADR-basierte Logik des ursprünglichen EA.
  • Trailing Stop – bewegt sich mit dem höchsten (oder niedrigsten) Preis seit der Eingabe unter Verwendung von ATR multipliziert mit einem Divisor.
  • Break-Even – sobald der Preis um die konfigurierte Distanz steigt, bewegt sich der Stop um einen kleinen Sperrwert über den Einstiegspreis hinaus.

Parameter

Name Beschreibung
TriggerLength EMA Länge für den Triggerfilter.
FilterLength1 EMA Länge für den ersten Bestätigungsfilter.
FilterLength2 EMA Länge für den zweiten Bestätigungsfilter.
UseOnlyPrimaryIndicators Für Einträge nur Trigger und ersten Filter verwenden.
IgnoreModerateForEntry Erfordern starke Trendzustände für neue Trades.
IgnoreModerateForExit Erfordern starke Gegensignale, um Geschäfte abzuschließen.
UseTradingHours Aktivieren Sie das Intraday-Handelsfenster.
TradingHourBegin / TradingHourEnd Start- und Endzeit des Handelsfensters.
UseJuiceFilter, JuicePeriod, JuiceThreshold Parameter des Standardabweichungs-Breakout-Filters.
UseAdxFilter, AdxPeriod, AdxThreshold, UseDirectionalFilter ADX Stärke und DI-Bestätigung.
UseAdrForStop, StopLossPips Anfängliche Stop-Loss-Konfiguration.
TrailingDivisor ATR-Multiplikator für die Trailing-Stop-Berechnung.
BreakEvenPips, BreakEvenLockPips Break-Even-Aktivierung und Sperrdistanz.
AtrPeriod ATR-Lookback, der zur Volatilitätsschätzung verwendet wird.
CandleType Zeitrahmen der primären Kerze.

Zusammenfassung der Indikatoren

  • Exponentieller gleitender Durchschnitt (EMA) – drei Instanzen für die Trendbewertung mit mehreren Geschwindigkeiten.
  • Standardabweichung – modelliert den „Saft“-Volatilitäts-Breakout-Filter.
  • Average True Range (ATR) – misst die Volatilität für Stops und Trailing.
  • Durchschnittlicher Richtungsindex (ADX) – bestätigt die Stärke und Richtung des Trends.

Nutzungshinweise

  1. Stellen Sie sicher, dass die Strategiesicherheit über einen definierten PriceStep verfügt. andernfalls wird für Pip-basierte Abstände der Standardschritt von 0,0001 verwendet.
  2. Die Strategie verwendet Marktaufträge (BuyMarket, SellMarket) und skaliert das Volumen automatisch, wenn Positionen umgekehrt werden.
  3. Dynamische Stopps werden intern simuliert, indem Positionen geschlossen werden, wenn das virtuelle Stoppniveau berührt wird.
  4. Kombinieren Sie das Handelsfenster und strenge Einstiegsoptionen, um sich auf Sitzungen mit hoher Liquidität zu konzentrieren und unruhige Phasen zu vermeiden.
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>
/// Flat Trend strategy - breakout from low volatility using ATR and EMA.
/// Buys when ATR expands and price is above EMA.
/// Sells when ATR expands and price is below EMA.
/// </summary>
public class FlatTrendStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevAtr;
	private decimal _prevClose;
	private decimal _prevEma;
	private bool _hasPrev;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public FlatTrendStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetDisplay("EMA Period", "EMA trend filter", "Indicators");

		_atrPeriod = Param(nameof(AtrPeriod), 14)
			.SetDisplay("ATR Period", "ATR volatility period", "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(); _prevAtr = 0m; _prevClose = 0m; _prevEma = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var atr = new AverageTrueRange { Length = AtrPeriod };

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

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevAtr = atr;
			_prevClose = close;
			_prevEma = ema;
			_hasPrev = true;
			return;
		}

		// Volatility expansion: ATR increasing
		var atrExpanding = atr > _prevAtr;

		// Breakout above EMA with expanding volatility
		if (atrExpanding && _prevClose <= _prevEma && close > ema && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Breakout below EMA with expanding volatility
		else if (atrExpanding && _prevClose >= _prevEma && close < ema && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevAtr = atr;
		_prevClose = close;
		_prevEma = ema;
	}
}