Auf GitHub ansehen

PROphet-Strategie

Überblick

Diese Strategie ist eine StockSharp-Portierung des MetaTrader 4-Expertenberaters „PROphet“. Das Original EA wertet den letzten Handelsdurchgang aus g über vier historische Kerzen und nutzt diese gewichteten Bereiche, um neue Trades auszulösen. Es hält Positionen nur zwischen den offen Europäische und US-amerikanische Sitzungen und folgt dem Stop-Loss, wenn sich der Preis um eine festgelegte Distanz zugunsten des Handels bewegt. Der StockSharp Die Implementierung behält alle diese Mechanismen bei und passt sie gleichzeitig an das Netting-Modell an, das von StockSharp-Portfolios verwendet wird.

Handelslogik

  • Abonnieren Sie den konfigurierten Zeitrahmen (CandleType, Standard M5) und verarbeiten Sie nur fertige Kerzen.
  • Behalten Sie die drei zuletzt abgeschlossenen Kerzen bei, um die von der Version MQL verwendete Indexierung High[i] und Low[i] zu reproduzieren.
  • Berechnen Sie den langen Trigger Qu(X1, X2, X3, X4) und den kurzen Trigger Qu(Y1, Y2, Y3, Y4) für jeden Balken. Jeder Term multipliziert a gewichteter Bereich (zum Beispiel |High[1] - Low[2]|) durch die entsprechende Gewichtung minus einhundert, genau wie im Originalcode.
  • Erlauben Sie neue Einträge nur, wenn die aktuelle Stunde zwischen TradeStartHour und TradeEndHour (einschließlich) liegt. Dies ahmt den Mann nach Aktuelles Handelsfenster vom MQL-Experten (standardmäßig 10:00 bis 18:00 Uhr).
  • Verwenden Sie eine einzelne Marktorder, deren Volumen jegliches gegenteilige Risiko neutralisiert, bevor Sie die neue Position eröffnen. Dies spiegelt das Mag wider IC-Nummernfilter aus der MetaTrader-Implementierung.

Risikomanagement und Trailing

  • Die Strategie rechnet die MetaTrader punktbasierten Stoppdistanzen über das Instrument PriceStep in Preiseinheiten um. Die Standardeinstellungen („B uyStopLossPoints = 68, SellStopLossPoints = 72`) entsprechen den externen Variablen MQL.
  • Sobald sich der Bid (für Long-Trades) oder der Ask (für Short-Trades) um spread + 2 * stopDistance über den bestehenden Stop hinausbewegt, th Der Trailing Stop wird auf currentPrice ± stopDistance vorgezogen, wobei Live-Level-1-Daten verwendet werden, sofern verfügbar.
  • Offene Geschäfte werden nach ExitHour zwangsweise geschlossen. Der Standardwert (18) reproduziert das ursprüngliche Verhalten beim Schließen der Position s nach 18:00 Uhr Serverzeit.
  • Bei Schutzausstiegen werden Market Orders verwendet, da die High-Level-Orders API von StockSharp nicht automatisch Stop-Orders generieren. Das hält Verhalten bei allen Brokern deterministisch.

Parameter

Parameter Beschreibung
AllowBuy Ermöglicht lange Trades.
AllowSell Ermöglicht Short-Trades.
X1, X2, X3, X4 Gewichtungen, die auf die Long-Side-Range-Komponenten innerhalb der Qu-Formel angewendet werden.
BuyStopLossPoints Stop-Loss-Distanz für Long-Trades, ausgedrückt in MetaTrader Punkten.
Y1, Y2, Y3, Y4 Gewichtungen, die auf die Short-Side-Range-Komponenten innerhalb der Qu-Formel angewendet werden.
SellStopLossPoints Stop-Loss-Distanz für Short-Trades, ausgedrückt in MetaTrader Punkten.
TradeVolume Grundvolumen (Lots), das für neue Einträge verwendet wird. Zusätzliches Volumen wird automatisch hinzugefügt, um die gegenüberliegende Belichtung zu schließen.
TradeStartHour Erste Stunde des Handelsfensters (einschließlich).
TradeEndHour Letzte Stunde des Handelsfensters (einschließlich).
ExitHour Stunde, nach der alle offenen Geschäfte geschlossen werden.
CandleType Zeitrahmen der zur Analyse verwendeten Kerzen.

Notizen

  • StockSharp Portfolios nutzen standardmäßig ein Netting. Wenn ein neues Signal erscheint, fügt die Strategie das erforderliche Volumen hinzu, um den Ex abzuflachen Ist-Position vor dem Öffnen des neuen Handels, der das Einzelpositions-pro-Richtungs-Design aus dem MetaTrader-Expe reproduziert rt.
  • Das MQL-Skript verwendete die von MarketInfo gemeldete Symbolverteilung. Der Port ruft die Spanne aus Level-1-Daten ab, sofern verfügbar andernfalls fällt er auf eine einzelne Preisstufe zurück.
  • Da der Trailing-Stop am Ende jeder fertigen Kerze ausgewertet wird, kann es im Vergleich zum Tick-Level-Stop zu einem Slippage kommen Aktualisierungen, die vom ursprünglichen EA durchgeführt wurden.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Translation of the MetaTrader "PROphet" expert advisor.
/// Uses a range-weighted signal from previous candles to enter trades.
/// </summary>
public class ProphetStrategy : Strategy
{
	private readonly StrategyParam<int> _x1;
	private readonly StrategyParam<int> _x2;
	private readonly StrategyParam<int> _x3;
	private readonly StrategyParam<int> _x4;
	private readonly StrategyParam<DataType> _candleType;

	private ICandleMessage _candle1;
	private ICandleMessage _candle2;
	private ICandleMessage _candle3;
	private decimal _entryPrice;

	public ProphetStrategy()
	{
		_x1 = Param(nameof(X1), 9)
			.SetDisplay("X1", "Weight applied to |High[1] - Low[2]|.", "Signal");

		_x2 = Param(nameof(X2), 29)
			.SetDisplay("X2", "Weight applied to |High[3] - Low[2]|.", "Signal");

		_x3 = Param(nameof(X3), 94)
			.SetDisplay("X3", "Weight applied to |High[2] - Low[1]|.", "Signal");

		_x4 = Param(nameof(X4), 125)
			.SetDisplay("X4", "Weight applied to |High[2] - Low[3]|.", "Signal");

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

	public int X1 { get => _x1.Value; set => _x1.Value = value; }
	public int X2 { get => _x2.Value; set => _x2.Value = value; }
	public int X3 { get => _x3.Value; set => _x3.Value = value; }
	public int X4 { get => _x4.Value; set => _x4.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

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

		_candle1 = null;
		_candle2 = null;
		_candle3 = null;
		_entryPrice = 0;
	}

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

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

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

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

		// Shift history
		_candle3 = _candle2;
		_candle2 = _candle1;
		_candle1 = candle;

		if (_candle1 == null || _candle2 == null || _candle3 == null)
			return;

		// Manage position - simple exit on reversal signal
		if (Position > 0)
		{
			var sellSignal = CalculateSignal(true);
			if (sellSignal > 0)
			{
				SellMarket();
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			var buySignal = CalculateSignal(false);
			if (buySignal > 0)
			{
				BuyMarket();
				_entryPrice = 0;
			}
		}

		// Entry
		if (Position == 0)
		{
			var buySignal = CalculateSignal(false);
			var sellSignal = CalculateSignal(true);

			if (buySignal > 0 && buySignal > sellSignal)
			{
				BuyMarket();
				_entryPrice = candle.ClosePrice;
			}
			else if (sellSignal > 0 && sellSignal > buySignal)
			{
				SellMarket();
				_entryPrice = candle.ClosePrice;
			}
		}
	}

	private decimal CalculateSignal(bool isSell)
	{
		var term1 = Math.Abs(_candle1.HighPrice - _candle2.LowPrice);
		var term2 = Math.Abs(_candle3.HighPrice - _candle2.LowPrice);
		var term3 = Math.Abs(_candle2.HighPrice - _candle1.LowPrice);
		var term4 = Math.Abs(_candle2.HighPrice - _candle3.LowPrice);

		if (isSell)
		{
			// For sell, use inverted weights
			return (100 - X1) * term1 + (100 - X2) * term2 + (X3 - 100) * term3 + (X4 - 100) * term4;
		}

		// For buy, use standard weights
		return (X1 - 100) * term1 + (X2 - 100) * term2 + (100 - X3) * term3 + (100 - X4) * term4;
	}
}