Auf GitHub ansehen

PZ Umkehr-Trendfolge

Diese Strategie folgt Ausbrüchen aus langfristigen Hochs und Tiefs. Sie kauft, wenn der Schlusskurs das höchste Hoch des Rückblickzeitraums überschreitet, und verkauft leer, wenn der Schlusskurs unter das niedrigste Tief fällt. Die Position wird bei entgegengesetzten Signalen immer umgekehrt, sodass die Strategie kontinuierlich im Markt bleibt.

Der Ansatz versucht, anhaltende Trends zu erfassen, indem nach einem bedeutenden Ausbruch eingestiegen wird. Da das System nur bei wichtigen Extremen handelt, kann es kleinere Geräusche vermeiden, aber in trendlosen Marktphasen erhebliche Drawdowns erleiden.

Details

  • Einstiegskriterien: Ausbruch aus dem Hoch/Tief der vorherigen Period Balken.
  • Long/Short: Beide Richtungen, immer im Markt.
  • Ausstiegskriterien: Entgegengesetztes Ausbruchssignal.
  • Stops: Nein
  • Standardwerte:
    • Period = 100
    • Volume = 1m
    • CandleType = TimeSpan.FromDays(1)
  • Filter:
    • Kategorie: Trend
    • Richtung: Beide
    • Indikatoren: Highest, Lowest
    • Stops: Nein
    • Komplexität: Grundlegend
    • Zeitrahmen: Täglich
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Mittel
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;

/// <summary>
/// Breakout strategy using Highest/Lowest channels.
/// </summary>
public class PzReversalTrendFollowingStrategy : Strategy
{
	private readonly StrategyParam<int> _period;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevHighest;
	private decimal _prevLowest;
	private bool _hasPrev;

	public int Period { get => _period.Value; set => _period.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public PzReversalTrendFollowingStrategy()
	{
		_period = Param(nameof(Period), 30)
			.SetGreaterThanZero()
			.SetDisplay("Period", "Lookback period for breakout", "General");

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

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHighest = 0;
		_prevLowest = 0;
		_hasPrev = false;
	}

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

		var highest = new Highest { Length = Period };
		var lowest = new Lowest { Length = Period };

		SubscribeCandles(CandleType)
			.Bind(highest, lowest, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevHighest = highestValue;
			_prevLowest = lowestValue;
			_hasPrev = true;
			return;
		}

		if (candle.ClosePrice > _prevHighest && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (candle.ClosePrice < _prevLowest && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevHighest = highestValue;
		_prevLowest = lowestValue;
	}
}