La estrategia PSAR Trader actúa sobre los cambios en el indicador Parabolic SAR. Cuando el SAR se desplaza por debajo del precio se abre una posición larga, y cuando el SAR se desplaza por encima del precio se abre una posición corta. Un ajuste opcional "Close On Opposite" invierte la posición cuando aparece una señal contraria. El trading ocurre solo durante las horas de sesión configuradas. El stop-loss y take-profit son gestionados por el módulo de protección.
Detalles
Criterios de entrada: Precio cruzando el Parabolic SAR.
Largo/Corto: Ambas direcciones.
Criterios de salida: Cruce SAR contrario o inversión de posición.
Stops: Sí, fijos mediante parámetros.
Valores predeterminados:
SarStep = 0.001m
SarMaxStep = 0.2m
StartHour = 0
EndHour = 23
CloseOnOpposite = true
TakeValue = 50 (absolute)
StopValue = 50 (absolute)
CandleType = TimeSpan.FromMinutes(5)
Filtros:
Categoría: Tendencia
Dirección: Ambos
Indicadores: Parabolic SAR
Stops: Fijo
Complejidad: Básico
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 cross strategy.
/// Opens long when price moves above SAR and short when price moves below SAR.
/// </summary>
public class PsarTraderStrategy : Strategy
{
private readonly StrategyParam<decimal> _sarStep;
private readonly StrategyParam<decimal> _sarMaxStep;
private readonly StrategyParam<DataType> _candleType;
private bool _prevPriceAboveSar;
private bool _hasPrev;
public decimal SarStep { get => _sarStep.Value; set => _sarStep.Value = value; }
public decimal SarMaxStep { get => _sarMaxStep.Value; set => _sarMaxStep.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public PsarTraderStrategy()
{
_sarStep = Param(nameof(SarStep), 0.001m)
.SetGreaterThanZero()
.SetDisplay("SAR Step", "Acceleration factor for Parabolic SAR", "Parabolic SAR");
_sarMaxStep = Param(nameof(SarMaxStep), 0.2m)
.SetGreaterThanZero()
.SetDisplay("SAR Max Step", "Maximum acceleration factor", "Parabolic SAR");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevPriceAboveSar = false;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var parabolicSar = new ParabolicSar
{
AccelerationStep = SarStep,
AccelerationMax = SarMaxStep
};
SubscribeCandles(CandleType).Bind(parabolicSar, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal sarValue)
{
if (candle.State != CandleStates.Finished) return;
var isPriceAboveSar = candle.ClosePrice > sarValue;
if (!_hasPrev)
{
_prevPriceAboveSar = isPriceAboveSar;
_hasPrev = true;
return;
}
if (_prevPriceAboveSar != isPriceAboveSar)
{
if (isPriceAboveSar && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (!isPriceAboveSar && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
_prevPriceAboveSar = isPriceAboveSar;
}
}
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 psar_trader_strategy(Strategy):
def __init__(self):
super(psar_trader_strategy, self).__init__()
self._sar_step = self.Param("SarStep", 0.001) \
.SetDisplay("SAR Step", "Acceleration factor for Parabolic SAR", "Parabolic SAR")
self._sar_max_step = self.Param("SarMaxStep", 0.2) \
.SetDisplay("SAR Max Step", "Maximum acceleration factor", "Parabolic SAR")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_price_above_sar = False
self._has_prev = False
@property
def sar_step(self):
return self._sar_step.Value
@property
def sar_max_step(self):
return self._sar_max_step.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(psar_trader_strategy, self).OnReseted()
self._prev_price_above_sar = False
self._has_prev = False
def OnStarted2(self, time):
super(psar_trader_strategy, self).OnStarted2(time)
psar = ParabolicSar()
psar.AccelerationStep = self.sar_step
psar.AccelerationMax = self.sar_max_step
self.SubscribeCandles(self.candle_type).Bind(psar, self.process_candle).Start()
def process_candle(self, candle, sar_value):
if candle.State != CandleStates.Finished:
return
is_price_above_sar = float(candle.ClosePrice) > float(sar_value)
if not self._has_prev:
self._prev_price_above_sar = is_price_above_sar
self._has_prev = True
return
if self._prev_price_above_sar != is_price_above_sar:
if is_price_above_sar and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif not is_price_above_sar and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_price_above_sar = is_price_above_sar
def CreateClone(self):
return psar_trader_strategy()