Parabolic SAR Fibo Limits — порт стратегии MetaTrader 4 FT_0tk80i9uw4ep_Parabolic на платформу StockSharp. Исходный эксперт сочетает две версии индикатора Parabolic SAR и уровни Фибоначчи, чтобы выставлять лимитные заявки в точках отката. Реализация на C# сохраняет поэтапную постановку заявок, встроенную защиту (перенос в безубыток и трейлинг-стоп) и опциональный фильтр торговой сессии, поэтому при работе на закрытых свечах поведение соответствует оригинальному советнику.
Логика стратегии
Подготовка сигналов
Согласование двух Parabolic SAR — на выбранном таймфрейме рассчитываются быстрый и медленный SAR. Быстрая кривая служит ранним предупреждением, медленная подтверждает смену состояния. Если быстрый SAR поднимается выше цены, пока медленный остается ниже, формируется потенциальная длинная настройка. Если быстрый SAR уходит ниже цены, а медленный выше, формируется короткая настройка. Как только медленный SAR пересекает цену, соответствующая настройка сбрасывается.
Поиск свингов — стратегия использует максимум и минимум за окно длиной Bar Search, что воспроизводит вспомогательную функцию MaximumMinimum из EA. Противоположный экстремум (High[1] или Low[1]) берётся из предыдущей завершённой свечи и служит базой для расчёта уровней Фибоначчи.
Постановка и сопровождение заявок
Лимитные заявки по Фибоначчи — когда обе кривые SAR оказываются по одну сторону от цены и настройка активирована, стратегия выставляет лимитную заявку на уровне 50% (Entry Fibonacci %) от найденного свинга. Защитный стоп размещается на заданное количество пунктов дальше экстремума, а тейк-профит — на расширении Фибоначчи (Target Fibonacci %). Заявка регистрируется только в том случае, если текущая цена, будущий стоп и цель находятся минимум в пяти шагах цены друг от друга, что повторяет фильтр Point*5 в MT4.
Автоматическое снятие заявок — если быстрый SAR возвращается на другую сторону от цены, активная лимитка по соответствующему направлению отменяется, чтобы не войти в рынок поздно. Исполнение лимитки автоматически отменяет противоположную отложенную заявку.
Управление рисками
Начальные стоп и цель — после исполнения лимитки стратегия закрепляет рассчитанные уровни стоп-лосса и тейк-профита, имитируя параметры SL/TP исходного эксперта.
Переход в безубыток — при ненулевом параметре Break Even (points) стоп переносится к цене входа (плюс или минус один шаг цены) после набора указанного количества пунктов прибыли, что соответствует функции BBU.
Трейлинг-стоп — если включён параметр Trailing Stop (points), стоп следует за ценой на фиксированном расстоянии. Обновление выполняется только при улучшении прежнего стопа минимум на Trailing Step (points), аналогично TrailingShag в MT4.
Принудительное закрытие — при касании рассчитанного стопа или цели на закрытой свече позиция закрывается рыночной заявкой, тем самым эмулируя автоматическое исполнение в MetaTrader.
Фильтр торговой сессии
Опциональное ограничение по времени — параметр Use Time Filter разрешает открывать новые сделки только между Start Hour и Stop Hour (включительно) во времени площадки. Защитные механизмы (безубыток, трейлинг, выходы) продолжают работать и вне торгового окна, как и в MQL-версии.
Параметры
Use Time Filter — включение фильтра торговой сессии.
Start Hour / Stop Hour — границы торгового окна при активном фильтре.
Fast SAR Step / Fast SAR Max — коэффициент ускорения и его максимум для быстрого Parabolic SAR.
Slow SAR Step / Slow SAR Max — коэффициент ускорения и его максимум для медленного Parabolic SAR.
Bar Search — количество свечей, используемых при поиске свинговых максимумов/минимумов.
Offset (points) — отступ в пунктах за пределы экстремума при расчёте стоп-лосса.
Entry Fibonacci % — процент Фибоначчи для цены лимитной заявки.
Target Fibonacci % — процент Фибоначчи для расчёта тейк-профита.
Break Even (points) — прибыль в пунктах, после которой стоп переносится в безубыток (± один шаг). Значение 0 отключает функцию.
Trailing Stop (points) — дистанция между ценой и трейлинг-стопом. Значение 0 отключает трейлинг.
Trailing Step (points) — минимальное улучшение (в пунктах) перед очередным сдвигом трейлинг-стопа.
Candle Type — таймфрейм, используемый для расчёта индикаторов и свингов.
Volume — базовый объём заявок, наследуемый от класса Strategy (по умолчанию 0.1).
Дополнительные сведения
Все параметры, выраженные в пунктах, автоматически переводятся в денежные величины через шаг цены инструмента, поэтому значения из MT4 можно применять без перерасчёта.
Стратегия обрабатывает только завершённые свечи выбранного таймфрейма, полностью повторяя баровое исполнение оригинального эксперта.
Python-реализация отсутствует, доступна только C# версия в составе каталога API.
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()