Ver en GitHub

Estrategia PROfeta

Descripción general

Esta estrategia es una versión StockSharp del MetaTrader 4 asesor experto "PROphet". El EA original evalúa la ejecución comercial reciente recorre cuatro velas históricas y utiliza esos rangos ponderados para activar nuevas operaciones. Mantiene posiciones abiertas sólo entre los sesiones europeas y estadounidenses y sigue el stop-loss cada vez que el precio se mueve una distancia fija a favor de la operación. El StockSharp La implementación mantiene todos esos mecanismos mientras los adapta al modelo de compensación utilizado por las carteras StockSharp.

Lógica comercial

  • Suscríbase al período de tiempo configurado (CandleType, predeterminado M5) y procese solo velas terminadas.
  • Mantenga las tres velas completadas más recientes para reproducir la indexación High[i] y Low[i] utilizada por la versión MQL.
  • Calcule el disparador largo Qu(X1, X2, X3, X4) y el disparador corto Qu(Y1, Y2, Y3, Y4) en cada barra. Cada término multiplica un rango ponderado (por ejemplo |High[1] - Low[2]|) por el peso correspondiente menos cien, exactamente como en el código original.
  • Permita nuevas entradas solo cuando la hora actual caiga entre TradeStartHour y TradeEndHour (inclusive). Esto imita al hombre. ventana de negociación dual del experto MQL (de 10:00 a 18:00 de forma predeterminada).
  • Utilice una orden de mercado única cuyo volumen neutralice cualquier exposición opuesta antes de abrir la nueva posición. Esto refleja el Mag ic Número de filtros de la implementación MetaTrader.

Gestión de riesgos y seguimiento

  • La estrategia convierte las MetaTrader distancias de parada basadas en puntos en unidades de precio a través del instrumento PriceStep. Los valores predeterminados (B uyStopLossPoints = 68, SellStopLossPoints = 72) coinciden con las MQL variables externas.
  • Una vez que la oferta (para operaciones largas) o la demanda (para operaciones cortas) supera el límite existente en spread + 2 * stopDistance, El trailing stop avanza hasta currentPrice ± stopDistance, utilizando datos de Nivel 1 en vivo cuando estén disponibles.
  • Las operaciones abiertas se cierran a la fuerza después de ExitHour. El valor predeterminado (18) reproduce el comportamiento original de cerrar la posición. s después de las 18:00 hora del servidor.
  • Las salidas protectoras utilizan órdenes de mercado porque el nivel alto de StockSharp API no genera automáticamente órdenes de parada. Esto mantiene comportamiento determinista entre corredores.

Parámetros

Parámetro Descripción
AllowBuy Permite operaciones largas.
AllowSell Permite operaciones cortas.
X1, X2, X3, X4 Pesos aplicados a los componentes del rango del lado largo dentro de la fórmula Qu.
BuyStopLossPoints Distancia de stop-loss para operaciones largas expresada en MetaTrader puntos.
Y1, Y2, Y3, Y4 Pesos aplicados a los componentes del rango del lado corto dentro de la fórmula Qu.
SellStopLossPoints Distancia de stop-loss para operaciones cortas expresada en MetaTrader puntos.
TradeVolume Volumen base (lotes) utilizado para nuevas entradas. Se agrega volumen adicional automáticamente para cerrar la exposición opuesta.
TradeStartHour Primera hora de la ventana de negociación (inclusive).
TradeEndHour Última hora de la ventana de negociación (inclusive).
ExitHour Hora tras la cual se cierran todas las operaciones abiertas.
CandleType Periodo de tiempo de las velas utilizadas para el análisis.

Notas

  • Las carteras StockSharp se compensan de forma predeterminada. Cuando aparece una nueva señal, la estrategia agrega el volumen necesario para aplanar el ex. posición actual antes de abrir la nueva operación, que reproduce el diseño de posición única por dirección de la experiencia MetaTrader rt.
  • El script MQL utilizó la extensión de símbolo informada por MarketInfo. El puerto recupera el diferencial de los datos de Nivel 1 cuando están disponibles y, de lo contrario, vuelve a caer a un único escalón de precio.
  • Debido a que el trailing stop se evalúa al cierre de cada vela terminada, puede ocurrir un deslizamiento en comparación con el stop a nivel de tick. actualizaciones realizadas por el EA original.
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;
	}
}