Auf GitHub ansehen

Exp TEMA-Strategie

Die Exp TEMA-Strategie ist eine StockSharp-Portierung des MetaTrader-Expertenberaters Exp_TEMA.mq5. Das ursprüngliche System scannt mehrere Forex-Paare und überwacht die Steigung des Triple Exponential Moving Average (TEMA). Immer wenn die Steigung ihr Vorzeichen umkehrt, betritt der Experte entweder eine neue Trendfolgeposition oder verlässt die entgegengesetzte. Diese C#-Konvertierung behält die gleiche Indikatorlogik bei und konzentriert sich dabei auf ein einzelnes Wertpapier, das der Strategie in StockSharp zugewiesen ist.

Handelslogik

Die Strategie arbeitet mit fertigen Kerzen, die durch den ausgewählten Parameter CandleType erzeugt wurden. Bei jedem Kerzenschluss wird ein TEMA mit der konfigurierbaren Länge TemaPeriod berechnet. Drei aufeinanderfolgende TEMA-Messwerte werden verglichen, um das Steigungserkennungsschema des MQL5-Experten zu reproduzieren:

  1. Sei tema[0] der letzte Kerzenwert, tema[1] der vorherige und tema[2] der Wert zwei Kerzen zurück.
  2. Die kurzfristige Steigung beträgt d1 = tema[1] - tema[2], während die ältere Steigung d2 = tema[2] - tema[3] beträgt.
  3. Ein bullischer Einstieg wird ausgelöst, wenn die Steigung ansteigt (d2 < 0 und d1 > 0). Jede Short-Position wird zuerst geschlossen, dann wird eine Long-Order von Volume + |Position| Lots platziert.
  4. Ein bärischer Einstieg wird ausgelöst, wenn die Steigung nach unten geht (d2 > 0 und d1 < 0). Jede Long-Position wird zuerst abgeflacht, dann wird eine Short-Order von Volume + |Position| Lots gesendet.
  5. Schutzausgänge ahmen die ursprünglichen Stop-Flags nach: Wenn die aktuelle Steigung negativ wird, wird die Long-Position geschlossen, während eine positive Steigung jede Short-Position schließt.

Dies reproduziert das gleiche Signaltiming wie die Quelle EA, ohne historischen Pufferzugriff zu verwenden, und bleibt innerhalb des High-Level-StockSharp API.

Parameter

Parameter Standard Beschreibung
TemaPeriod 15 Länge des dreifach exponentiellen gleitenden Durchschnitts.
TradeVolume 1 Grundauftragsvolumen. Die ausgeführte Größe wird zu „TradeVolume +“. Position ` beim Rückwärtsfahren.
StopLossPoints 1000 Stop-Loss-Distanz ausgedrückt in Preisschritten. Wird an StartProtection übergeben, wenn positiv.
TakeProfitPoints 2000 Take-Profit-Distanz, ausgedrückt in Preisschritten. Wird an StartProtection übergeben, wenn positiv.
CandleType 15-Minuten-Kerzen Kerzentyp, der den Indikator speist. Wählen Sie einen Zeitrahmen, der dem vom ursprünglichen Experten verwendeten Diagramm entspricht.

Alle Parameter werden mit StrategyParam<T> erstellt, sodass sie im Designer optimiert werden können.

Unterschiede zum MQL5 Expert

  • Die Version MQL verwaltet bis zu zwölf Symbole gleichzeitig. StockSharp-Strategien sind an einen bestimmten Security gebunden, daher handelt dieser Port mit dem Instrument, das beim Start der Strategie zugewiesen wurde. Führen Sie mehrere Strategieinstanzen aus, wenn eine Abdeckung mit mehreren Symbolen erforderlich ist.
  • Die Auftragsverwaltung basiert auf BuyMarket/SellMarket und StartProtection, die die ursprünglichen Marktaufträge, Stopps und Ziele dem übergeordneten API von StockSharp zuordnen.
  • Der Indikatorzugriff erfolgt über SubscribeCandles().Bind(...), wodurch manuelles Pufferkopieren vermieden wird und die Repository-Richtlinien eingehalten werden.

Nutzungstipps

  1. Hängen Sie die Strategie an das gewünschte Wertpapier an und legen Sie den CandleType fest, der Ihrem analytischen Zeitrahmen entspricht.
  2. Passen Sie die Stop- und Take-Profit-Abstände in Preisschritten entsprechend der Volatilität des Instruments an.
  3. Optional: Führen Sie die Optimierung für TemaPeriod, StopLossPoints und TakeProfitPoints aus, um die in MetaTrader durchgeführten Parameter-Sweeps zu replizieren.
  4. Überwachen Sie den enthaltenen Diagrammbereich, um Kerzen, die TEMA-Linie und die ausgeführten Trades zu visualisieren.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy that trades TEMA slope reversals from the original Exp_TEMA expert advisor.
/// Enters long when TEMA slope turns positive, short when negative.
/// </summary>
public class ExpTemaStrategy : Strategy
{
	private readonly StrategyParam<int> _temaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private ExponentialMovingAverage _tema;
	private decimal? _prev1;
	private decimal? _prev2;
	private decimal? _prev3;

	public int TemaPeriod
	{
		get => _temaPeriod.Value;
		set => _temaPeriod.Value = value;
	}

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

	public ExpTemaStrategy()
	{
		_temaPeriod = Param(nameof(TemaPeriod), 40)
			.SetGreaterThanZero()
			.SetDisplay("TEMA Period", "Length of Triple Exponential Moving Average", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for TEMA calculation", "General");
	}

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

		_tema = new ExponentialMovingAverage { Length = TemaPeriod };
		_prev1 = null;
		_prev2 = null;
		_prev3 = null;

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

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

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

		if (!_tema.IsFormed)
		{
			_prev1 = temaValue;
			return;
		}

		if (_prev1 is null)
		{
			_prev1 = temaValue;
			return;
		}

		if (_prev2 is null)
		{
			_prev2 = _prev1;
			_prev1 = temaValue;
			return;
		}

		if (_prev3 is null)
		{
			_prev3 = _prev2;
			_prev2 = _prev1;
			_prev1 = temaValue;
			return;
		}

		var volume = Volume;
		if (volume <= 0)
			volume = 1;

		var dtema1 = _prev1.Value - _prev2.Value;
		var dtema2 = _prev2.Value - _prev3.Value;

		// Entry on slope reversal
		var turnedUp = dtema2 < 0 && dtema1 > 0;
		var turnedDown = dtema2 > 0 && dtema1 < 0;

		if (turnedUp && Position <= 0)
		{
			BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
		}
		else if (turnedDown && Position >= 0)
		{
			SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
		}

		_prev3 = _prev2;
		_prev2 = _prev1;
		_prev1 = temaValue;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_tema = null;
		_prev1 = null;
		_prev2 = null;
		_prev3 = null;

		base.OnReseted();
	}
}