The Fibo Pivot MultiVal Strategy is a StockSharp port of the MetaTrader 4 expert advisor _Fibo_Pivot_multiVal.mq4. The
strategy combines daily pivot points with Fibonacci retracement and extension ratios to deploy limit orders inside each price
zone that surrounds the pivot. Trading sessions, position targets, and halting rules follow the original expert advisor so that
risk control and execution behaviour remain familiar to traders who used the MetaTrader version.
Core Logic
Daily reference levels are computed from the previous day's high, low, and close. Classic pivot levels (P, R1-R3, S1-S3)
are accompanied by Fibonacci-based internal levels that split the distance between the pivot and the neighbouring support or
resistance lines. Additional R3/S3 extensions project potential breakout targets.
Intraday price action is monitored on the configured candle timeframe (15 minutes by default). When the current close
resides inside a particular pivot zone (for example between R2 and R3), the strategy activates the corresponding limit orders.
Limit orders are placed at the Fibonacci sub-levels. Each zone maintains both long and short orders, with the direction
filtered by the MidZoneOrderMode parameter when the price oscillates between R1-R2 and S1-S2.
Targets adapt to market volatility. When UseReversalTargets is enabled, exits sit on the opposite side of the active
Fibonacci band to capture mean-reversion bounces. When disabled, the algorithm compares the previous day's range with the
LimitPointOut and LimitPointIn thresholds to decide whether to aim for extended breakouts (towards R3/S3 extensions) or
deeper reversals (towards the pivot).
Risk limits pause new trades once the configurable daily or per-symbol profit/trade thresholds are exceeded. All pending
orders are cancelled and trading resumes on the next session reset (before StartTime).
Session management mirrors the original EA: trading starts at StartTime, new entries stop after FinishTime, and all
open exposure is flattened after CloseAllTime.
Parameters
Name
Default
Description
CandleType
15-minute candles
Timeframe used to build the decision candles.
OrderVolume
0.1
Volume for each limit order registered by the strategy.
StartTime
00:01
Session time of day that enables trading and resets counters.
FinishTime
08:00
Session time that disables new entries while keeping existing positions.
CloseAllTime
12:00
Session time that cancels orders and closes all positions.
UseReversalTargets
true
When true, targets stay inside the Fibonacci zone. When false, breakout/pivot targets are used based on the daily range.
LimitPointIn
150
Daily range threshold (points) that enforces pivot reversion targets when exceeded.
LimitPointOut
50
Daily range threshold (points) that encourages breakout targets when price action is compressed.
LevelPf1
33
Percentage used to split the Pivot–R1 and Pivot–S1 distance.
LevelF1F2
50
Percentage used to compute the intermediate level between R1–R2 and S1–S2.
LevelF2F3
33
Percentage used to compute the intermediate level between R2–R3 and S2–S3.
LevelF3Out
40
Percentage used to extend R3/S3 for breakout targets.
MidZoneOrderMode
"bs"
Allowed directions inside the mid zones ("b"=buy only, "s"=sell only, "bs"=both).
DailyProfitTarget
50
Daily profit limit in points.
DailyTradeTarget
35
Maximum number of completed trades per day.
SymbolProfitTarget
150
Per-symbol profit target in points.
SymbolTradeTarget
15
Maximum completed trades per symbol per day.
Order Management
Each active zone keeps its own entry, take-profit, and optional stop orders. When an entry is filled, exit orders are
recreated using the target/stop levels derived from the Fibonacci configuration.
Filled exits update the daily and per-symbol statistics. Hitting any limit pauses trading until the next reset.
Session boundaries automatically cancel entry orders. The CloseAllTime boundary additionally closes any open positions via
market orders.
Practical Tips
The strategy expects instruments with well-defined price steps. Ensure the Security instance exposes PriceStep so that the
point-to-price conversion matches the original EA.
For assets with different volatility characteristics, adjust LimitPointIn and LimitPointOut so that breakout vs.
mean-reversion behaviours trigger at appropriate ranges.
If you prefer directional trades around the mid-zone (R1-R2 or S1-S2), set MidZoneOrderMode to "b" or "s" to allow only
long or short setups.
Use the built-in parameter optimisation support to backtest alternative Fibonacci ratios. All percentage parameters and
thresholds expose SetCanOptimize in the source code, enabling automated scans inside StockSharp Designer.
Differences from the Original Expert Advisor
The StockSharp version works on a single security per strategy instance. To trade multiple symbols as in the MetaTrader EA,
run separate strategy instances for each instrument.
Position sizing is expressed directly in volume units rather than MetaTrader lots. Configure OrderVolume to match your
broker's requirements.
Order execution relies on the StockSharp high level API (BuyLimit, SellLimit, etc.). Broker-specific behaviour (such as
pending order offsets) should be reviewed before deploying to production.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class FiboPivotMultiValStrategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevMid;
private bool _hasPrev;
private int _cooldownRemaining;
public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FiboPivotMultiValStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 48).SetDisplay("Channel Period", "Fibo channel lookback", "Indicators");
_emaPeriod = Param(nameof(EmaPeriod), 50).SetDisplay("EMA Period", "EMA filter", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 150).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = default;
_prevMid = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0;
_prevMid = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var highest = new Highest { Length = ChannelPeriod };
var lowest = new Lowest { Length = ChannelPeriod };
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(highest, lowest, ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest, decimal ema)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var mid = (highest + lowest) / 2;
if (!_hasPrev) { _prevClose = close; _prevMid = mid; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevClose = close;
_prevMid = mid;
return;
}
if (_prevClose <= _prevMid && close > mid && close > ema && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (_prevClose >= _prevMid && close < mid && close < ema && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevClose = close;
_prevMid = mid;
}
}
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 Highest, Lowest, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class fibo_pivot_multi_val_strategy(Strategy):
def __init__(self):
super(fibo_pivot_multi_val_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 48) \
.SetDisplay("Channel Period", "Fibo channel lookback", "Indicators")
self._ema_period = self.Param("EmaPeriod", 50) \
.SetDisplay("EMA Period", "EMA filter", "Indicators")
self._cooldown_candles = self.Param("CooldownCandles", 150) \
.SetDisplay("Cooldown", "Candles between signals", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown_remaining = 0
@property
def channel_period(self):
return self._channel_period.Value
@property
def ema_period(self):
return self._ema_period.Value
@property
def cooldown_candles(self):
return self._cooldown_candles.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(fibo_pivot_multi_val_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(fibo_pivot_multi_val_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown_remaining = 0
highest = Highest()
highest.Length = self.channel_period
lowest = Lowest()
lowest.Length = self.channel_period
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(highest, lowest, ema, self.process_candle).Start()
def process_candle(self, candle, highest, lowest, ema):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
mid = (float(highest) + float(lowest)) / 2.0
ema_val = float(ema)
if not self._has_prev:
self._prev_close = close
self._prev_mid = mid
self._has_prev = True
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_close = close
self._prev_mid = mid
return
if self._prev_close <= self._prev_mid and close > mid and close > ema_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown_remaining = self.cooldown_candles
elif self._prev_close >= self._prev_mid and close < mid and close < ema_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown_remaining = self.cooldown_candles
self._prev_close = close
self._prev_mid = mid
def CreateClone(self):
return fibo_pivot_multi_val_strategy()