Auf GitHub ansehen

TradePad-Beispielstrategie

Überblick

Die TradePad-Beispielstrategie ist eine Portierung des MetaTrader „TradePad“-Beispiels. Der ursprüngliche Fachberater hat ein Raster erstellt Schaltflächen, die den kurzfristigen Trend für mehrere Symbole anzeigten, indem sie jede Zelle mit dem aktuellen Stochastic-Oszillator einfärbten Lesen. Diese StockSharp-Implementierung behält den analytischen Kern der Stichprobe bei und konzentriert sich auf die Überwachung einer Liste von Instrumenten ohne die Benutzeroberfläche auf dem Diagramm zu replizieren. Die Strategie abonniert Kerzendaten für jedes konfigurierte Symbol und berechnet a Stochastic-Oszillator und klassifiziert jedes Instrument in die Zustände Aufwärtstrend, Abwärtstrend oder Flat. Jedes Mal, wenn die Klasse wechselt, Die Strategie schreibt eine Protokollmeldung, die der vom ursprünglichen TradePad durchgeführten Farbänderung ähnelt.

Die Strategie erteilt keine Aufträge. Ziel ist es, diskretionären Händlern dabei zu helfen, den Überblick über mehrere Märkte gleichzeitig und vor Ort zu behalten Momentumänderungen, die manuelle Maßnahmen erfordern (zum Beispiel das Wechseln von Charts oder das Vorbereiten von Trades).

Wie es funktioniert

  1. Symbolerkennung – der Parameter SymbolList akzeptiert eine durch Kommas getrennte Liste von Tickern. Wenn keine Liste angegeben wird, wird die Die Strategie greift auf die im Runner zugewiesene Hauptstrategie Security zurück.
  2. Kerzenabonnement – jedes Symbol verwendet denselben Zeitrahmen, der über CandleType konfiguriert wurde.
  3. Indikatorverarbeitung – eine dedizierte StochasticOscillator-Instanz ist an den Kerzenstream gebunden. Wenn die Kerze ist Wenn der Indikator fertig ist, erzeugt er den %K-Wert, der für die Trendklassifizierung verwendet wird.
  4. Trendklassifizierung – ein Messwert über UpperLevel wird Aufwärtstrend zugeordnet, ein Messwert unter LowerLevel wird Abwärtstrend zugeordnet, alles dazwischen ist Flach. Der letzte Oszillatorwert wird in LatestKValues gespeichert.
  5. Aktualisierungsintervall – Die Strategie ahmt das Timer-Verhalten des ursprünglichen TradePad nach. Eine Änderung wird höchstens einmal pro Protokoll protokolliert TimerPeriodSeconds für jedes Symbol, auch wenn innerhalb des Intervalls mehrere Kerzen eintreffen.

Parameter

Parameter Beschreibung
SymbolList Durch Kommas getrennte Liste der zu überwachenden Instrumente. Eine leere Zeichenfolge bedeutet „Hauptsicherheit verwenden“.
TimerPeriodSeconds Mindestanzahl von Sekunden zwischen Statusaktualisierungen pro Symbol. Verhindert Protokoll-Spam, wenn die Kerzen sehr kurz sind.
StochasticLength Lookback-Zeitraum, der zur Berechnung der Rohzeile %K verwendet wird.
StochasticKPeriod Auf die Linie %K angewendeter Glättungszeitraum.
StochasticDPeriod Auf die Zeile %D angewendeter Glättungszeitraum (wird der Vollständigkeit halber beibehalten, obwohl die Strategie nur %K lautet).
UpperLevel Schwellenwert, oberhalb dessen davon ausgegangen wird, dass sich das Symbol in einem Aufwärtstrend befindet.
LowerLevel Schwellenwert, unterhalb dessen davon ausgegangen wird, dass sich das Symbol in einem Abwärtstrend befindet.
CandleType Zeitrahmen der für die Indikatorberechnung verwendeten Kerzen.

Nutzungshinweise

  • Stellen Sie sicher, dass die angegebenen Ticker im Connector verfügbar sind. Fehlende Symbole werden im Protokoll gemeldet und übersprungen.
  • Die Eigenschaft TrendStates stellt die neueste Klassifizierung für externe Dashboards oder Designer-Blöcke bereit.
  • Verwenden Sie die Strategie in Designer oder Runner, um Ihre eigenen visuellen Elemente (Dashboards, Diagramme) anzuhängen, die auf die AddInfoLog reagieren. Nachrichten oder die öffentlichen Wörterbücher.
  • Da keine Orders gesendet werden, kann die Strategie sicher auf Live-Datenanbietern ausschließlich zu Überwachungszwecken angewendet werden.

Ursprüngliches MQL-Verhalten im Vergleich zur StockSharp-Version

MQL5 Funktion StockSharp Implementierung
Grafisches Raster von Schaltflächen Wird als Protokolleinträge und öffentliche Wörterbücher verfügbar gemacht, damit eine benutzerdefinierte Benutzeroberfläche in Designer erstellt werden kann.
Manuelle KAUF-/VERKAUF-Tasten Nicht implementiert; Die Strategie bleibt bewusst passiv.
Logik zum Ziehen von Diagrammen Nicht anwendbar in StockSharp und weggelassen.
Trendfarben-Updates Ersetzt durch Trendzustandsänderungen, die alle TimerPeriodSeconds pro Symbol ausgelöst werden.

Erweiterung der Strategie

  • Verbinden Sie das TrendStates-Wörterbuch mit Designer-Widgets, um das farbige Pad mithilfe von XAML-Steuerelementen neu zu erstellen.
  • Fügen Sie Warnungen oder Benachrichtigungen hinzu, wenn ein Symbol von Flat zu Uptrend oder Downtrend wechselt.
  • Kombinieren Sie die Klassifizierung mit der Bestelllogik, wenn Sie Eingaben automatisieren möchten, nachdem Sie eine starke Dynamik festgestellt haben.
namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// TradePad Sample strategy.
/// Classifies market state using Stochastic oscillator and trades on state transitions.
/// Buys when stochastic crosses up from oversold, sells when it crosses down from overbought.
/// </summary>
public class TradePadSampleStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _stochasticKPeriod;
	private readonly StrategyParam<int> _stochasticDPeriod;
	private readonly StrategyParam<decimal> _upperLevel;
	private readonly StrategyParam<decimal> _lowerLevel;

	private decimal _prevK;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int StochasticKPeriod { get => _stochasticKPeriod.Value; set => _stochasticKPeriod.Value = value; }
	public int StochasticDPeriod { get => _stochasticDPeriod.Value; set => _stochasticDPeriod.Value = value; }
	public decimal UpperLevel { get => _upperLevel.Value; set => _upperLevel.Value = value; }
	public decimal LowerLevel { get => _lowerLevel.Value; set => _lowerLevel.Value = value; }

	public TradePadSampleStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_stochasticKPeriod = Param(nameof(StochasticKPeriod), 10)
			.SetDisplay("Stochastic %K", "%K period", "Indicators");

		_stochasticDPeriod = Param(nameof(StochasticDPeriod), 3)
			.SetDisplay("Stochastic %D", "%D period", "Indicators");

		_upperLevel = Param(nameof(UpperLevel), 75m)
			.SetDisplay("Upper Threshold", "Overbought level", "Signals");

		_lowerLevel = Param(nameof(LowerLevel), 25m)
			.SetDisplay("Lower Threshold", "Oversold level", "Signals");
	}

	/// <inheritdoc />
	public override System.Collections.Generic.IEnumerable<(StockSharp.BusinessEntities.Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevK = 0;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var stochastic = new StochasticOscillator();
		stochastic.K.Length = StochasticKPeriod;
		stochastic.D.Length = StochasticDPeriod;

		var subscription = SubscribeCandles(CandleType);

		subscription
			.BindEx(stochastic, ProcessCandle)
			.Start();

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

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

		if (!stochVal.IsFinal || !stochVal.IsFormed)
			return;

		var stoch = (StochasticOscillatorValue)stochVal;
		if (stoch.K is not decimal kValue)
			return;

		if (!_hasPrev)
		{
			_prevK = kValue;
			_hasPrev = true;
			return;
		}

		// Buy: stochastic crosses up through lower level (leaving oversold)
		var crossUp = _prevK <= LowerLevel && kValue > LowerLevel;
		// Sell: stochastic crosses down through upper level (leaving overbought)
		var crossDown = _prevK >= UpperLevel && kValue < UpperLevel;

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

		_prevK = kValue;
	}
}