Elite eFibo Trader v2.1 recreates the MetaTrader expert advisor that stacks Fibonacci-sized orders in one direction while sharing a common protective stop. The StockSharp port keeps the original behaviour: a single market order launches a sequence of stop orders spaced by LevelDistancePips, and every filled tier increases the exposure according to the Fibonacci progression. The strategy immediately closes the entire basket once the shared stop is touched or when the floating profit reaches MoneyTakeProfit.
The algorithm is intentionally directional. Set OpenBuy to true (and OpenSell to false) to trade bullish pullbacks, or flip the switches to run the bearish variant. Only one ladder is active at a time, mirroring the single-cycle logic from the MQL4 script.
Data requirements
Subscribes to the trade stream to retrieve the latest execution price used for ladder placement, trailing logic, and money take-profit evaluation.
Relies on the security metadata (PriceStep, StepPrice, VolumeStep) to translate MetaTrader-style pip inputs into exchange prices and lot sizes.
Ladder construction
When there is no exposure and trading is allowed, the strategy checks the direction switches. Exactly one of OpenBuy or OpenSell must be true; otherwise no ladder is started.
The first Fibonacci level is opened at market. Subsequent levels are scheduled as stop orders offset by LevelDistancePips * pipSize from the reference price recorded when the ladder starts.
Volumes come from the Level1Volume … Level14Volume parameters and are normalised to the security VolumeStep.
All levels inherit the same stop offset: StopLossPips * pipSize. The stop price is computed per fill and later tightened so that every active order shares the closest protective level.
Stop management
Each filled order stores its entry price and initial stop derived from the pip offset.
On every trade tick the strategy re-evaluates all open stops and aligns them to the tightest value across the ladder (highest stop for longs, lowest stop for shorts) to mimic the repeated OrderModify calls from MetaTrader.
When the last trade price crosses any shared stop the strategy cancels remaining pending orders and closes the whole basket with market orders.
Money management
Unrealised profit is calculated from the instrument PriceStep and StepPrice so that the cash target mirrors the OrderProfit() readings from MetaTrader.
If the floating profit reaches or exceeds MoneyTakeProfit, all positions are closed and pending orders are cancelled immediately.
When TradeAgainAfterProfit is false, the strategy remains idle after hitting the money target until it is restarted manually.
Parameters
Name
Description
OpenBuy
Allow the strategy to build a bullish ladder (must be exclusive with OpenSell).
OpenSell
Allow the strategy to build a bearish ladder (must be exclusive with OpenBuy).
TradeAgainAfterProfit
Resume trading after the basket closes on the money take-profit.
LevelDistancePips
Distance in MetaTrader pips between consecutive stop orders.
StopLossPips
Distance in MetaTrader pips used to derive the protective stop for every filled level.
MoneyTakeProfit
Cash profit target that closes the entire basket.
Level1Volume … Level14Volume
Volumes used for each Fibonacci level; set to zero to skip a tier.
Implementation notes
The pip conversion follows the MetaTrader convention: if the symbol has 3 or 5 decimals the effective pip equals PriceStep * 10.
StartProtection() is called once during start-up to enable the built-in StockSharp safety checks.
The shared stop logic intentionally keeps all orders in sync; once a tighter stop appears it is propagated to every active level.
Pending orders are cleaned automatically whenever the ladder is flat, replicating the multiple subCloseAllPending() calls found in the MQL code.
Usage tips
Ensure that PriceStep, StepPrice, and VolumeStep are configured on the instrument; otherwise pip conversions or money targets may be inaccurate.
Averaging systems can accumulate large exposure quickly. Verify the volume limits and margin requirements before running the strategy live.
Disable TradeAgainAfterProfit to reproduce the one-shot behaviour where the EA stops trading after closing a profitable basket.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class EliteEfiboTraderV21Strategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevEma;
private bool _hasPrev;
private int _cooldownRemaining;
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 EliteEfiboTraderV21Strategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 50).SetDisplay("EMA Period", "EMA lookback", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 200).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;
_prevEma = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0;
_prevEma = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ema)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (!_hasPrev) { _prevClose = close; _prevEma = ema; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevClose = close;
_prevEma = ema;
return;
}
if (_prevClose <= _prevEma && close > ema && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (_prevClose >= _prevEma && close < ema && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevClose = close;
_prevEma = ema;
}
}
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
from StockSharp.Algo.Strategies import Strategy
class elite_efibo_trader_v21_strategy(Strategy):
def __init__(self):
super(elite_efibo_trader_v21_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 50) \
.SetDisplay("EMA Period", "EMA lookback", "Indicators")
self._cooldown_candles = self.Param("CooldownCandles", 200) \
.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_ema = 0.0
self._has_prev = False
self._cooldown_remaining = 0
@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(elite_efibo_trader_v21_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_ema = 0.0
self._has_prev = False
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(elite_efibo_trader_v21_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_ema = 0.0
self._has_prev = False
self._cooldown_remaining = 0
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self.process_candle).Start()
def process_candle(self, candle, ema):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
ema_val = float(ema)
if not self._has_prev:
self._prev_close = close
self._prev_ema = ema_val
self._has_prev = True
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_close = close
self._prev_ema = ema_val
return
if self._prev_close <= self._prev_ema 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_ema 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_ema = ema_val
def CreateClone(self):
return elite_efibo_trader_v21_strategy()