Estrategia Parabolic SAR de Compra Anticipada con Salida Basada en MA
Esta estrategia utiliza el indicador Parabolic SAR para entrar en operaciones cuando el indicador cambia de lado respecto al precio. Una media móvil simple proporciona una regla de salida adicional: las posiciones largas se cierran cuando el precio cae por debajo de la media móvil mientras el SAR está por encima del precio.
Detalles
- Criterios de entrada: El SAR cambia de lado respecto al precio.
- Largo/Corto: Ambos.
- Criterios de salida: Para posiciones largas, salir cuando SAR > precio y precio < MA.
- Stops: No definidos.
- Valores predeterminados:
Acceleration= 0.02AccelerationStep= 0.02MaxAcceleration= 0.2MaPeriod= 11CandleType= 5 minutos
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Ambos
- Indicadores: Parabolic SAR, SMA
- Stops: Ninguno
- Complejidad: Básico
- Marco temporal: Intradía
- 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 early buy with moving average exit.
/// A close crossing above the Parabolic SAR goes long and a close crossing below it goes short, reversing an opposite position.
/// A long is also closed early when the SAR is above the close and the close is below the MaPeriod simple moving average.
/// </summary>
public class ParabolicSarEarlyBuyMaBasedExitStrategy : Strategy
{
private readonly StrategyParam<decimal> _acceleration;
private readonly StrategyParam<decimal> _accelerationStep;
private readonly StrategyParam<decimal> _maxAcceleration;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevClose;
private decimal? _prevSar;
/// <summary>
/// Initial SAR acceleration factor.
/// </summary>
public decimal Acceleration
{
get => _acceleration.Value;
set => _acceleration.Value = value;
}
/// <summary>
/// SAR acceleration factor increment.
/// </summary>
public decimal AccelerationStep
{
get => _accelerationStep.Value;
set => _accelerationStep.Value = value;
}
/// <summary>
/// Maximum SAR acceleration factor.
/// </summary>
public decimal MaxAcceleration
{
get => _maxAcceleration.Value;
set => _maxAcceleration.Value = value;
}
/// <summary>
/// Period of the exit moving average.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public ParabolicSarEarlyBuyMaBasedExitStrategy()
{
_acceleration = Param(nameof(Acceleration), 0.02m)
.SetGreaterThanZero()
.SetDisplay("Acceleration", "Initial SAR acceleration factor", "Indicators");
_accelerationStep = Param(nameof(AccelerationStep), 0.02m)
.SetGreaterThanZero()
.SetDisplay("Acceleration Step", "SAR acceleration factor increment", "Indicators");
_maxAcceleration = Param(nameof(MaxAcceleration), 0.2m)
.SetGreaterThanZero()
.SetDisplay("Max Acceleration", "Maximum SAR acceleration factor", "Indicators");
_maPeriod = Param(nameof(MaPeriod), 11)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Period of the exit moving average", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = null;
_prevSar = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null;
_prevSar = null;
var sar = new ParabolicSar
{
Acceleration = this.Acceleration,
AccelerationStep = this.AccelerationStep,
AccelerationMax = MaxAcceleration
};
var ma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sar, ma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sar);
DrawIndicator(area, ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal sar, decimal ma)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var prevClose = _prevClose;
var prevSar = _prevSar;
_prevClose = close;
_prevSar = sar;
if (prevClose is not decimal pc || prevSar is not decimal ps)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var crossUp = pc <= ps && close > sar;
var crossDown = pc >= ps && close < sar;
if (crossUp && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (crossDown && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
else if (Position > 0 && sar > close && close < ma)
SellMarket(Position);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ParabolicSar, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class parabolic_sar_early_buy_ma_based_exit_strategy(Strategy):
"""
Parabolic SAR early buy with moving average exit.
A close crossing above the Parabolic SAR goes long and a close crossing below it goes short, reversing an opposite position.
A long is also closed early when the SAR is above the close and the close is below the MaPeriod simple moving average.
"""
def __init__(self):
super(parabolic_sar_early_buy_ma_based_exit_strategy, self).__init__()
self._acceleration = self.Param("Acceleration", 0.02).SetGreaterThanZero().SetDisplay("Acceleration", "Initial SAR acceleration factor", "Indicators")
self._acceleration_step = self.Param("AccelerationStep", 0.02).SetGreaterThanZero().SetDisplay("Acceleration Step", "SAR acceleration factor increment", "Indicators")
self._max_acceleration = self.Param("MaxAcceleration", 0.2).SetGreaterThanZero().SetDisplay("Max Acceleration", "Maximum SAR acceleration factor", "Indicators")
self._ma_period = self.Param("MaPeriod", 11).SetGreaterThanZero().SetDisplay("MA Period", "Period of the exit moving average", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_close = None
self._prev_sar = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(parabolic_sar_early_buy_ma_based_exit_strategy, self).OnReseted()
self._prev_close = None
self._prev_sar = None
def OnStarted2(self, time):
super(parabolic_sar_early_buy_ma_based_exit_strategy, self).OnStarted2(time)
self._prev_close = None
self._prev_sar = None
sar = ParabolicSar()
sar.Acceleration = Decimal(self._acceleration.Value)
sar.AccelerationStep = Decimal(self._acceleration_step.Value)
sar.AccelerationMax = Decimal(self._max_acceleration.Value)
ma = SimpleMovingAverage()
ma.Length = self._ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sar, ma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sar)
self.DrawIndicator(area, ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sar, ma):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
prev_close = self._prev_close
prev_sar = self._prev_sar
self._prev_close = close
self._prev_sar = sar
if prev_close is None or prev_sar is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
cross_up = prev_close <= prev_sar and close > sar
cross_down = prev_close >= prev_sar and close < sar
if cross_up and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif cross_down and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
elif self.Position > 0 and sar > close and close < ma:
self.SellMarket(self.Position)
def CreateClone(self):
return parabolic_sar_early_buy_ma_based_exit_strategy()