The Parabolic SAR Bug strategy trades trend reversals using the Parabolic SAR indicator. When the SAR flips below price the strategy enters long, and when the SAR flips above price it enters short. Optional reverse mode inverts signals. Protective stop loss, take profit, and trailing stop are supported through the built-in position protection module.
Details
Entry Criteria: Parabolic SAR direction change.
Long/Short: Both directions.
Exit Criteria: Opposite SAR signal or protective stop.
Stops: Stop loss, take profit, optional trailing stop.
Default Values:
Step = 0.02
MaxStep = 0.2
StopLossPercent = 2
TakeProfitPercent = 1
UseTrailingStop = false
Reverse = false
CloseOnSar = true
CandleType = TimeSpan.FromMinutes(5)
Filters:
Category: Trend
Direction: Both
Indicators: Parabolic SAR
Stops: Stop loss, take profit
Complexity: Basic
Timeframe: Intraday (5m)
Seasonality: No
Neural Networks: No
Divergence: No
Risk Level: Medium
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.
/// Buys when price crosses above SAR, sells when price crosses below.
/// </summary>
public class ParabolicSarBugStrategy : Strategy
{
private readonly StrategyParam<decimal> _step;
private readonly StrategyParam<decimal> _maxStep;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevSar;
private decimal _prevClose;
private bool _initialized;
public decimal Step { get => _step.Value; set => _step.Value = value; }
public decimal MaxStep { get => _maxStep.Value; set => _maxStep.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ParabolicSarBugStrategy()
{
_step = Param(nameof(Step), 0.02m)
.SetDisplay("Step", "Acceleration factor", "Indicator");
_maxStep = Param(nameof(MaxStep), 0.2m)
.SetDisplay("Max Step", "Maximum acceleration", "Indicator");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevSar = 0;
_prevClose = 0;
_initialized = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sar = new ParabolicSar
{
Acceleration = Step,
AccelerationMax = MaxStep
};
SubscribeCandles(CandleType).Bind(sar, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal sarValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
if (!_initialized)
{
_prevSar = sarValue;
_prevClose = close;
_initialized = true;
return;
}
var crossUp = close > sarValue && _prevClose <= _prevSar;
var crossDown = close < sarValue && _prevClose >= _prevSar;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevSar = sarValue;
_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 ParabolicSar
from StockSharp.Algo.Strategies import Strategy
class parabolic_sar_bug_strategy(Strategy):
def __init__(self):
super(parabolic_sar_bug_strategy, self).__init__()
self._step = self.Param("Step", 0.02) \
.SetDisplay("Step", "Acceleration factor", "Indicator")
self._max_step = self.Param("MaxStep", 0.2) \
.SetDisplay("Max Step", "Maximum acceleration", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_sar = 0.0
self._prev_close = 0.0
self._initialized = False
@property
def step(self):
return self._step.Value
@property
def max_step(self):
return self._max_step.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(parabolic_sar_bug_strategy, self).OnReseted()
self._prev_sar = 0.0
self._prev_close = 0.0
self._initialized = False
def OnStarted2(self, time):
super(parabolic_sar_bug_strategy, self).OnStarted2(time)
sar = ParabolicSar()
sar.Acceleration = self.step
sar.AccelerationMax = self.max_step
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sar, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, sar_value):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
if not self._initialized:
self._prev_sar = sar_value
self._prev_close = close
self._initialized = True
return
cross_up = close > sar_value and self._prev_close <= self._prev_sar
cross_down = close < sar_value and self._prev_close >= self._prev_sar
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_sar = sar_value
self._prev_close = close
def CreateClone(self):
return parabolic_sar_bug_strategy()