Parabolic SAR MultiTimeframe uses four different Parabolic SAR indicators from higher timeframes
to confirm a trend before entering a trade. The strategy processes 15-minute candles and checks the
state of SAR on 30-minute, 1-hour and 4-hour charts. A long position is opened only when price is
above all SAR values; a short position is opened when price is below all SARs.
The method attempts to filter out noise by requiring alignment across multiple timeframes. Position
is closed when the opposite condition appears.
Details
Entry Criteria: Price relative to Parabolic SAR on 15m/30m/1h/4h timeframes.
Long/Short: Both directions.
Exit Criteria: Opposite signal from all SAR indicators.
Stops: Uses StartProtection for basic protection, no explicit stop values.
Default Values:
Step15 = 0.062
Step30 = 0.058
Step60 = 0.058
Step240 = 0.058
MaxStep = 0.1
Filters:
Category: Trend
Direction: Both
Indicators: Parabolic SAR
Stops: No
Complexity: Intermediate
Timeframe: Intraday (15m base with higher confirmations)
Seasonality: No
Neural Networks: No
Divergence: No
Risk Level: Medium
Usage
Attach the strategy to a security.
Adjust SAR step parameters if needed.
Start the strategy; it will subscribe to 15m, 30m, 1h and 4h candles automatically.
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 trend-following strategy with EMA confirmation.
/// </summary>
public class ParabolicSarMultiTimeframeStrategy : Strategy
{
private readonly StrategyParam<decimal> _sarAcceleration;
private readonly StrategyParam<decimal> _sarMaxAcceleration;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<DataType> _candleType;
public decimal SarAcceleration { get => _sarAcceleration.Value; set => _sarAcceleration.Value = value; }
public decimal SarMaxAcceleration { get => _sarMaxAcceleration.Value; set => _sarMaxAcceleration.Value = value; }
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ParabolicSarMultiTimeframeStrategy()
{
_sarAcceleration = Param(nameof(SarAcceleration), 0.02m)
.SetDisplay("SAR Accel", "SAR acceleration factor", "Indicators");
_sarMaxAcceleration = Param(nameof(SarMaxAcceleration), 0.2m)
.SetDisplay("SAR Max", "SAR max acceleration", "Indicators");
_emaLength = Param(nameof(EmaLength), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "EMA trend filter period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle Type", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sar = new ParabolicSar { Acceleration = SarAcceleration, AccelerationMax = SarMaxAcceleration };
var ema = new ExponentialMovingAverage { Length = EmaLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(sar, ema, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sar);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal sarValue, decimal emaValue)
{
if (candle.State != CandleStates.Finished)
return;
var price = candle.ClosePrice;
// Buy when price is above both SAR and EMA
if (price > sarValue && price > emaValue && Position <= 0)
BuyMarket();
// Sell when price is below both SAR and EMA
else if (price < sarValue && price < emaValue && Position >= 0)
SellMarket();
// Exit on SAR flip
if (Position > 0 && price < sarValue)
SellMarket();
else if (Position < 0 && price > sarValue)
BuyMarket();
}
}
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, ParabolicSar
from StockSharp.Algo.Strategies import Strategy
class parabolic_sar_multi_timeframe_strategy(Strategy):
def __init__(self):
super(parabolic_sar_multi_timeframe_strategy, self).__init__()
self._sar_acceleration = self.Param("SarAcceleration", 0.02) \
.SetDisplay("SAR Accel", "SAR acceleration factor", "Indicators")
self._sar_max_acceleration = self.Param("SarMaxAcceleration", 0.2) \
.SetDisplay("SAR Max", "SAR max acceleration", "Indicators")
self._ema_length = self.Param("EmaLength", 50) \
.SetDisplay("EMA Length", "EMA trend filter period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle Type", "General")
@property
def sar_acceleration(self):
return self._sar_acceleration.Value
@property
def sar_max_acceleration(self):
return self._sar_max_acceleration.Value
@property
def ema_length(self):
return self._ema_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(parabolic_sar_multi_timeframe_strategy, self).OnStarted2(time)
sar = ParabolicSar()
sar.Acceleration = self.sar_acceleration
sar.AccelerationMax = self.sar_max_acceleration
ema = ExponentialMovingAverage()
ema.Length = self.ema_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sar, ema, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sar)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def on_process(self, candle, sar_value, ema_value):
if candle.State != CandleStates.Finished:
return
price = candle.ClosePrice
# Buy when price is above both SAR and EMA
if price > sar_value and price > ema_value and self.Position <= 0:
self.BuyMarket()
# Sell when price is below both SAR and EMA
elif price < sar_value and price < ema_value and self.Position >= 0:
self.SellMarket()
# Exit on SAR flip
if self.Position > 0 and price < sar_value:
self.SellMarket()
elif self.Position < 0 and price > sar_value:
self.BuyMarket()
def CreateClone(self):
return parabolic_sar_multi_timeframe_strategy()