Auf GitHub ansehen

TRIX-Kreuzungs-Strategie

Diese Strategie verwendet zwei TRIX-Indikatoren (Triple Exponential Moving Average Oscillator) mit unterschiedlichen Perioden, um potenzielle Umkehrungen zu erkennen. Eine Long-Position wird eröffnet, wenn der schnelle TRIX einen lokalen Tiefpunkt bildet, während der langsame TRIX steigt. Eine Short-Position wird eröffnet, wenn der schnelle TRIX einen lokalen Hochpunkt bildet, während der langsame TRIX fällt.

Parameter

  • Fast TRIX Period – Periode des schnellen TRIX-Indikators.
  • Slow TRIX Period – Periode des langsamen TRIX-Indikators.
  • Take Profit – Gewinnziel in absoluten Preiseinheiten.
  • Stop Loss – Maximalverlust in absoluten Preiseinheiten.
  • Candle Type – Zeitrahmen oder Datentyp für Kerzen.

Handelslogik

  1. Abonnieren des ausgewählten Kerzentyps.
  2. Berechnen der schnellen und langsamen TRIX-Werte bei jeder abgeschlossenen Kerze.
  3. Long einsteigen, wenn der aktuelle TRIX-Wert höher als der vorherige ist, der vorherige niedriger als der davor liegende ist und der langsame TRIX steigt.
  4. Short einsteigen, wenn der aktuelle TRIX-Wert niedriger als der vorherige ist, der vorherige höher als der davor liegende ist und der langsame TRIX fällt.
  5. Es wird nur eine Position gleichzeitig gehalten.
  6. Stop Loss und Take Profit Schutzmaßnahmen werden automatisch angewendet.

Hinweise

Die Strategie ist eine Anpassung eines MQL5-Skripts und zeigt, wie man mit TRIX-Indikatoren in StockSharp arbeitet.

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>
/// Strategy based on fast and slow TRIX indicator signals.
/// A long position opens when the fast TRIX forms a local bottom and the slow TRIX is rising.
/// A short position opens when the fast TRIX forms a local top and the slow TRIX is falling.
/// </summary>
public class TrixCrossoverStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<decimal> _minTrix;
	private readonly StrategyParam<decimal> _takeProfit;
	private readonly StrategyParam<decimal> _stopLoss;
	private readonly StrategyParam<DataType> _candleType;

	// Store previous TRIX values for decision making
	private decimal _fastTrixPrev1;
	private decimal _fastTrixPrev2;
	private decimal _slowTrixPrev;
	private decimal _prevFastTema;
	private decimal _prevSlowTema;
	private TripleExponentialMovingAverage _fastTema = null!;
	private TripleExponentialMovingAverage _slowTema = null!;

	/// <summary>
	/// Fast TRIX period.
	/// </summary>
	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	/// <summary>
	/// Slow TRIX period.
	/// </summary>
	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	/// <summary>
	/// Minimum TRIX value required for a signal.
	/// </summary>
	public decimal MinTrix
	{
		get => _minTrix.Value;
		set => _minTrix.Value = value;
	}

	/// <summary>
	/// Take profit size in absolute price units.
	/// </summary>
	public decimal TakeProfit
	{
		get => _takeProfit.Value;
		set => _takeProfit.Value = value;
	}

	/// <summary>
	/// Stop loss size in absolute price units.
	/// </summary>
	public decimal StopLoss
	{
		get => _stopLoss.Value;
		set => _stopLoss.Value = value;
	}

	/// <summary>
	/// Candle type.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes <see cref="TrixCrossoverStrategy"/>.
	/// </summary>
	public TrixCrossoverStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Fast TRIX Period", "Period for the fast TRIX indicator", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow TRIX Period", "Period for the slow TRIX indicator", "Indicators");
		_minTrix = Param(nameof(MinTrix), 0.0005m)
			.SetGreaterThanZero()
			.SetDisplay("Min TRIX", "Minimum TRIX magnitude for signals", "Indicators");
		_takeProfit = Param(nameof(TakeProfit), 1500m)
			.SetNotNegative()
			.SetDisplay("Take Profit", "Take profit in absolute price units", "Risk Management");
		_stopLoss = Param(nameof(StopLoss), 500m)
			.SetNotNegative()
			.SetDisplay("Stop Loss", "Stop loss in absolute price units", "Risk Management");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_fastTrixPrev1 = 0m;
		_fastTrixPrev2 = 0m;
		_slowTrixPrev = 0m;
		_prevFastTema = 0m;
		_prevSlowTema = 0m;
		_fastTema = null!;
		_slowTema = null!;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_fastTrixPrev1 = 0m;
		_fastTrixPrev2 = 0m;
		_slowTrixPrev = 0m;
		_prevFastTema = 0m;
		_prevSlowTema = 0m;
		_fastTema = new TripleExponentialMovingAverage { Length = FastPeriod };
		_slowTema = new TripleExponentialMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(_fastTema, _slowTema, ProcessCandle)
			.Start();

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

		StartProtection(new Unit(TakeProfit, UnitTypes.Absolute), new Unit(StopLoss, UnitTypes.Absolute));
	}

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

		if (_prevFastTema == 0m || _prevSlowTema == 0m)
		{
			_prevFastTema = fastTemaValue;
			_prevSlowTema = slowTemaValue;
			return;
		}

		var fastTrix = (fastTemaValue - _prevFastTema) / _prevFastTema;
		var slowTrix = (slowTemaValue - _prevSlowTema) / _prevSlowTema;

		_prevFastTema = fastTemaValue;
		_prevSlowTema = slowTemaValue;

		var prevFastTrix = _fastTrixPrev1;
		_fastTrixPrev2 = _fastTrixPrev1;
		_fastTrixPrev1 = fastTrix;

		var slowTrixPrev = _slowTrixPrev;
		_slowTrixPrev = slowTrix;

		if (_fastTrixPrev2 == 0m || slowTrixPrev == 0m)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var crossUp = prevFastTrix <= 0 && fastTrix > 0;
		var crossDown = prevFastTrix >= 0 && fastTrix < 0;

		if (crossUp && slowTrix > MinTrix && Position <= 0)
			BuyMarket();
		else if (crossDown && slowTrix < -MinTrix && Position >= 0)
			SellMarket();
	}
}