Ver en GitHub

Parabolic SAR Estrategia de alerta de volteo (4164)

Descripción general

Esta estrategia reproduce el asesor experto MetaTrader pSAR_alert2 dentro del marco StockSharp. Monitorea el indicador Parabolic SAR en el instrumento y el período de tiempo seleccionados. Cada vez que el valor SAR cambia de encima del precio de cierre a debajo de él (o viceversa), la estrategia genera una alerta informativa. Opcionalmente, puede enviar órdenes de mercado hacia el giro para transformar la alerta en una entrada automatizada.

Lógica de trading

  1. Suscríbase a la serie de velas configuradas y calcule el indicador Parabolic SAR con la configuración de aceleración proporcionada.
  2. Espere a que termine cada vela para emular el tiempo original EA.
  3. Compare el valor del indicador con el cierre de la vela:
    • SAR anterior por encima del cierre y SAR actual por debajo del cierre → giro alcista.
    • SAR anterior por debajo del cierre y SAR actual por encima del cierre → giro bajista.
  4. Registre una alerta detallada para cada giro. Cuando el comercio automático esté habilitado, reduzca cualquier exposición opuesta y abra una nueva posición en la dirección de la señal utilizando órdenes de mercado.

Parámetros

Parámetro Descripción
Candle Type Marco de tiempo utilizado para construir velas y evaluar el indicador Parabolic SAR.
SAR Step Factor de aceleración inicial pasado al Parabolic SAR.
SAR Max Factor de aceleración máximo del Parabolic SAR.
Enable Auto Trading Cuando true, se envían órdenes de mercado en cada alerta; cuando false, solo se generan registros.
Trade Volume El tamaño de la orden se aplica cuando el comercio automático está habilitado.

Notas de conversión

  • El script MetaTrader original dependía de Sleep para acelerar la ejecución. StockSharp se basa en eventos, por lo que la estrategia reacciona a nuevas velas inmediatamente sin demoras manuales.
  • Las alertas se generan a través de AddInfoLog, manteniendo el comportamiento original de las notificaciones emergentes sin requerir componentes de interfaz de usuario adicionales.
  • Se proporciona comercio automático opcional para integrar la lógica de alerta en flujos de trabajo automatizados. Deshabilite el parámetro Enable Auto Trading para que coincida exactamente con el comportamiento de MetaTrader.
  • La implementación de Python se omite intencionalmente según lo solicitado.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Parabolic SAR Flip: EMA trend following with ATR stops.
/// </summary>
public class ParabolicSarFlipAlertStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevClose;
	private decimal _entryPrice;

	public ParabolicSarFlipAlertStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_emaLength = Param(nameof(EmaLength), 20)
			.SetDisplay("EMA Length", "Trend filter.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

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

		_prevClose = 0; _entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = 0; _entryPrice = 0;
		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, atr, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		if (_prevClose == 0 || atrVal <= 0) { _prevClose = close; return; }

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || close < emaVal) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || close > emaVal) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (close > emaVal && _prevClose <= emaVal) { _entryPrice = close; BuyMarket(); }
			else if (close < emaVal && _prevClose >= emaVal) { _entryPrice = close; SellMarket(); }
		}

		_prevClose = close;
	}
}