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
Suscríbase a la serie de velas configuradas y calcule el indicador Parabolic SAR con la configuración de aceleración proporcionada.
Espere a que termine cada vela para emular el tiempo original EA.
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.
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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class parabolic_sar_flip_alert_strategy(Strategy):
def __init__(self):
super(parabolic_sar_flip_alert_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
self._ema_length = self.Param("EmaLength", 20).SetDisplay("EMA Length", "Trend filter", "Indicators")
self._atr_length = self.Param("AtrLength", 14).SetDisplay("ATR Length", "ATR period", "Indicators")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(parabolic_sar_flip_alert_strategy, self).OnReseted()
self._prev_close = 0
self._entry_price = 0
def OnStarted2(self, time):
super(parabolic_sar_flip_alert_strategy, self).OnStarted2(time)
self._prev_close = 0
self._entry_price = 0
ema = ExponentialMovingAverage()
ema.Length = self._ema_length.Value
atr = AverageTrueRange()
atr.Length = self._atr_length.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(ema, atr, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def OnProcess(self, candle, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
if self._prev_close == 0 or atr_val <= 0:
self._prev_close = close
return
if self.Position > 0:
if close >= self._entry_price + atr_val * 2.5 or close <= self._entry_price - atr_val * 1.5 or close < ema_val:
self.SellMarket()
self._entry_price = 0
elif self.Position < 0:
if close <= self._entry_price - atr_val * 2.5 or close >= self._entry_price + atr_val * 1.5 or close > ema_val:
self.BuyMarket()
self._entry_price = 0
if self.Position == 0:
if close > ema_val and self._prev_close <= ema_val:
self._entry_price = close
self.BuyMarket()
elif close < ema_val and self._prev_close >= ema_val:
self._entry_price = close
self.SellMarket()
self._prev_close = close
def CreateClone(self):
return parabolic_sar_flip_alert_strategy()