Esta estrategia replica el asesor experto PZ Parabolic SAR. Emplea dos indicadores Parabolic SAR con diferentes configuraciones de paso y aceleración máxima. El SAR de "operación" detecta la dirección de la tendencia para las entradas, mientras que el SAR de "stop" sigue el precio más de cerca y activa las salidas cuando la tendencia se revierte.
El control del riesgo se gestiona mediante el Average True Range (ATR). Se establece un stop inicial basado en ATR cuando se abre una posición. Opcionalmente, un trailing stop basado en ATR puede ajustar el stop a medida que el precio se mueve a favor de la operación. La estrategia también admite cierre parcial: una vez que el beneficio supera la distancia del stop inicial, se cierra la mitad de la posición y el stop se mueve a break-even.
La estrategia opera en dirección larga y corta y solo funciona con velas completadas. Utiliza órdenes de mercado sin colocar órdenes de stop reales.
Detalles
Criterios de entrada: Precio por encima/debajo del SAR de operación y del SAR de stop en la misma dirección.
Largo/Corto: Ambas direcciones.
Criterios de salida: SAR de stop cruzando el precio o trailing stop ATR alcanzado.
Stops: Stop basado en ATR con trailing y break-even opcionales.
Valores predeterminados:
TradeStep = 0.002
TradeMax = 0.2
StopStep = 0.004
StopMax = 0.4
AtrPeriod = 30
AtrMultiplier = 2.5
UseTrailing = false
TrailingAtrPeriod = 30
TrailingAtrMultiplier = 1.75
PartialClosing = true
PercentageToClose = 0.5
BreakEven = true
LotSize = 0.1
CandleType = TimeFrame(5m)
Filtros:
Categoría: Tendencia
Dirección: Ambos
Indicadores: Parabolic SAR, ATR
Stops: ATR, Trailing
Complejidad: Intermedio
Marco temporal: Intradía (5m)
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Parabolic SAR crossover strategy.
/// </summary>
public class PzParabolicSarEaStrategy : Strategy
{
private readonly StrategyParam<decimal> _sarStep;
private readonly StrategyParam<decimal> _sarMax;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevSar;
private bool _hasPrev;
public decimal SarStep { get => _sarStep.Value; set => _sarStep.Value = value; }
public decimal SarMax { get => _sarMax.Value; set => _sarMax.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public PzParabolicSarEaStrategy()
{
_sarStep = Param(nameof(SarStep), 0.02m)
.SetDisplay("SAR Step", "Acceleration step", "Indicators");
_sarMax = Param(nameof(SarMax), 0.2m)
.SetDisplay("SAR Max", "Maximum acceleration", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0;
_prevSar = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sar = new ParabolicSar { AccelerationStep = SarStep, AccelerationMax = SarMax };
SubscribeCandles(CandleType)
.Bind(sar, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal sarVal)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (!_hasPrev)
{
_prevClose = close;
_prevSar = sarVal;
_hasPrev = true;
return;
}
var crossUp = _prevClose <= _prevSar && close > sarVal;
var crossDown = _prevClose >= _prevSar && close < sarVal;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevClose = close;
_prevSar = sarVal;
}
}
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 ParabolicSar
from StockSharp.Algo.Strategies import Strategy
class pz_parabolic_sar_ea_strategy(Strategy):
def __init__(self):
super(pz_parabolic_sar_ea_strategy, self).__init__()
self._sar_step = self.Param("SarStep", 0.02) .SetDisplay("SAR Step", "Acceleration step", "Indicators")
self._sar_max = self.Param("SarMax", 0.2) .SetDisplay("SAR Max", "Maximum acceleration", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) .SetDisplay("Candle Type", "Candle type", "General")
self._prev_close = 0.0
self._prev_sar = 0.0
self._has_prev = False
@property
def sar_step(self):
return self._sar_step.Value
@property
def sar_max(self):
return self._sar_max.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(pz_parabolic_sar_ea_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_sar = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(pz_parabolic_sar_ea_strategy, self).OnStarted2(time)
sar = ParabolicSar()
sar.AccelerationStep = self.sar_step
sar.AccelerationMax = self.sar_max
self.SubscribeCandles(self.candle_type).Bind(sar, self.process_candle).Start()
def process_candle(self, candle, sar_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
sv = float(sar_val)
if not self._has_prev:
self._prev_close = close
self._prev_sar = sv
self._has_prev = True
return
cross_up = self._prev_close <= self._prev_sar and close > sv
cross_down = self._prev_close >= self._prev_sar and close < sv
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_sar = sv
def CreateClone(self):
return pz_parabolic_sar_ea_strategy()