Parabolic SAR Fibo Limits is a StockSharp port of the MetaTrader 4 expert advisor FT_0tk80i9uw4ep_Parabolic. The original robot combines a dual Parabolic SAR stack with Fibonacci retracement levels to stage limit entries at key pullback zones. The C# strategy preserves the staged order placement, the built-in break-even and trailing protections, and the optional trading session filter so that the behaviour matches the source EA when it is attached to a chart with finished candles.
Strategy logic
Signal preparation
Dual Parabolic SAR alignment – two Parabolic SAR indicators are calculated on the same timeframe. The fast SAR is used as an early warning, while the slow SAR confirms the state change. When the fast SAR jumps above the price while the slow SAR remains below it, the strategy arms a potential long setup. When the fast SAR dips below the price while the slow SAR stays above it, a potential short setup is armed. The setups are cleared as soon as the slow SAR crosses the price in the respective direction.
Swing detection – the strategy queries the highest high and lowest low over the configurable Bar Search window to replicate the MaximumMinimum helper from the EA. The previous finished candle provides the opposing extreme (High[1] or Low[1]) that anchors the Fibonacci calculations.
Order placement and management
Fibonacci pending orders – once both SARs sit on the same side of the price and a setup is armed, the strategy submits a limit order at the 50% Fibonacci level (Entry Fibonacci %) of the detected swing. The protective stop is offset from the swing extreme by the configured number of points, and the take profit is placed at the extended Fibonacci projection (Target Fibonacci %). Orders are only accepted when the current price, the planned stop, and the target are all at least five price steps away from each other, mirroring the EA’s Point*5 safety filter.
Automatic order cleanup – whenever the fast SAR crosses back over the price, the pending limit order for that direction is cancelled to avoid entering in the wrong market phase. Filling a limit order automatically cancels the opposite pending order.
Risk management
Initial stop and target – the EA’s pending order stop-loss and take-profit parameters are emulated by applying the calculated stop and target levels as soon as the limit order is filled.
Break-even shift – if Break Even (points) is greater than zero, the stop moves to the entry price plus one price step (or minus one step for shorts) once the trade gains the specified number of points, reproducing the original BBU routine.
Trailing stop – when Trailing Stop (points) is enabled, the stop follows the price by the chosen distance. The stop is only updated when the new stop improves the previous one by at least Trailing Step (points), matching the EA’s TrailingShag behaviour.
Manual exit triggers – if price touches the calculated stop or target levels on a finished candle, the position is closed with a market order to simulate MT4’s automatic order execution.
Time filter
Optional session control – enabling Use Time Filter restricts new entries to the inclusive window between Start Hour and Stop Hour in exchange time. Protective logic (break-even, trailing, exits) continues to operate even outside the session, just like in the MQL implementation.
Parameters
Use Time Filter – toggles the trading session filter.
Start Hour / Stop Hour – inclusive session hours used when the time filter is enabled.
Fast SAR Step / Fast SAR Max – acceleration factor and maximum acceleration for the fast Parabolic SAR.
Slow SAR Step / Slow SAR Max – acceleration factor and maximum acceleration for the slow Parabolic SAR.
Bar Search – number of bars included in the swing high/low calculation.
Offset (points) – number of price steps added beyond the swing extreme when computing the stop-loss.
Entry Fibonacci % – Fibonacci percentage (expressed as 0–200+) used for the limit order price.
Target Fibonacci % – Fibonacci percentage applied to compute the take-profit projection.
Break Even (points) – profit in points required before the stop jumps to the entry price (+/- one step). Set to 0 to disable.
Trailing Stop (points) – distance between price and trailing stop. Set to 0 to disable trailing.
Trailing Step (points) – minimum improvement (in points) before the trailing stop is advanced.
Candle Type – timeframe that drives the indicator and swing calculations.
Volume – base order volume inherited from the StockSharp Strategy class (default 0.1).
Additional notes
All point-based parameters are automatically converted into price offsets using the instrument’s price step. Five-digit FX symbols, indices, and other assets therefore reuse the EA settings without manual scaling.
The strategy processes only finished candles supplied by the configured subscription, exactly matching the EA’s bar-by-bar execution.
There is no Python version of this strategy; only the C# implementation is available in the API package.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Parabolic SAR strategy with Fibonacci retracement-based targets.
/// Enters on SAR flip, uses Highest/Lowest range for Fibonacci levels.
/// </summary>
public class ParabolicSarFiboLimitsStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _lookback;
private decimal _prevSar;
private bool _hasPrevSar;
private decimal _entryPrice;
public ParabolicSarFiboLimitsStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(3).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis.", "General");
_lookback = Param(nameof(Lookback), 20)
.SetDisplay("Lookback", "Period for Highest/Lowest range.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int Lookback
{
get => _lookback.Value;
set => _lookback.Value = value;
}
/// <inheritdoc />
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevSar = 0;
_hasPrevSar = false;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevSar = 0;
_hasPrevSar = false;
_entryPrice = 0;
var sar = new ParabolicSar();
var highest = new Highest { Length = Lookback };
var lowest = new Lowest { Length = Lookback };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sar, highest, lowest, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sar);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal sarValue, decimal highestValue, decimal lowestValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var range = highestValue - lowestValue;
// SAR flip detection
var sarBelow = sarValue < close;
var prevSarBelow = _hasPrevSar && _prevSar < close;
var sarAbove = sarValue > close;
var prevSarAbove = _hasPrevSar && _prevSar > close;
// Fibonacci levels from the range
var fib382 = lowestValue + range * 0.382m;
var fib618 = lowestValue + range * 0.618m;
// Position management
if (Position > 0)
{
// Exit at 61.8% Fibonacci or SAR flip above
if (close >= fib618 || sarAbove)
{
SellMarket();
}
}
else if (Position < 0)
{
// Exit at 38.2% Fibonacci or SAR flip below
if (close <= fib382 || sarBelow)
{
BuyMarket();
}
}
// Entry on SAR flip with range confirmation
if (Position == 0 && _hasPrevSar && range > 0)
{
if (sarBelow && !prevSarBelow && close > fib382)
{
// SAR flipped below price - bullish
_entryPrice = close;
BuyMarket();
}
else if (sarAbove && !prevSarAbove && close < fib618)
{
// SAR flipped above price - bearish
_entryPrice = close;
SellMarket();
}
}
_prevSar = sarValue;
_hasPrevSar = true;
}
}
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, Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class parabolic_sar_fibo_limits_strategy(Strategy):
def __init__(self):
super(parabolic_sar_fibo_limits_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(3))).SetDisplay("Candle Type", "Timeframe", "General")
self._lookback = self.Param("Lookback", 20).SetDisplay("Lookback", "Period for Highest/Lowest range", "Indicators")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(parabolic_sar_fibo_limits_strategy, self).OnReseted()
self._prev_sar = 0
self._has_prev_sar = False
self._entry_price = 0
def OnStarted2(self, time):
super(parabolic_sar_fibo_limits_strategy, self).OnStarted2(time)
self._prev_sar = 0
self._has_prev_sar = False
self._entry_price = 0
sar = ParabolicSar()
highest = Highest()
highest.Length = self._lookback.Value
lowest = Lowest()
lowest.Length = self._lookback.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(sar, highest, lowest, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, sar)
self.DrawOwnTrades(area)
def OnProcess(self, candle, sar_value, highest_value, lowest_value):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
rng = highest_value - lowest_value
sar_below = sar_value < close
prev_sar_below = self._has_prev_sar and self._prev_sar < close
sar_above = sar_value > close
prev_sar_above = self._has_prev_sar and self._prev_sar > close
fib382 = lowest_value + rng * 0.382
fib618 = lowest_value + rng * 0.618
if self.Position > 0:
if close >= fib618 or sar_above:
self.SellMarket()
elif self.Position < 0:
if close <= fib382 or sar_below:
self.BuyMarket()
if self.Position == 0 and self._has_prev_sar and rng > 0:
if sar_below and not prev_sar_below and close > fib382:
self._entry_price = close
self.BuyMarket()
elif sar_above and not prev_sar_above and close < fib618:
self._entry_price = close
self.SellMarket()
self._prev_sar = sar_value
self._has_prev_sar = True
def CreateClone(self):
return parabolic_sar_fibo_limits_strategy()