Открыть на GitHub

Стратегия Elite eFibo Trader v2.1

Обзор

Elite eFibo Trader v2.1 воспроизводит советник MetaTrader, который наращивает позицию по числам Фибоначчи в одном направлении и использует общий защитный стоп. В версии для StockSharp сохранена исходная логика: стартовая рыночная заявка активирует цепочку отложенных стоп-заявок с интервалом LevelDistancePips, а каждая новая сделка увеличивает объём согласно прогрессии Фибоначчи. Как только общий стоп достигается либо плавающая прибыль превышает MoneyTakeProfit, стратегия полностью закрывает корзину.

Алгоритм намеренно однонаправленный. Установите OpenBuy = trueOpenSell = false), чтобы торговать в сторону роста, либо поменяйте флаги местами для медвежьей версии. Одновременно может быть активна только одна лестница, что повторяет одноцикловую схему оригинального скрипта MQL4.

Требования к данным

  • Стратегия подписывается на поток сделок, чтобы использовать последнюю цену для постановки уровней, подтяжки стопа и проверки денежного тейк-профита.
  • Информация о инструменте (PriceStep, StepPrice, VolumeStep) необходима для перевода метатрейдеровских пунктов и лотов в биржевые цены и объёмы.

Построение лестницы

  1. При отсутствии позиции и разрешении на торговлю проверяются флаги направления. Должен быть активен ровно один флаг (OpenBuy или OpenSell), иначе лестница не запускается.
  2. Первый уровень открывается рыночной сделкой. Остальные уровни выставляются как стоп-заявки, смещённые на LevelDistancePips * pipSize от опорной цены, зафиксированной при запуске лестницы.
  3. Объёмы задаются параметрами Level1VolumeLevel14Volume и нормализуются по VolumeStep инструмента.
  4. Все уровни получают общий сдвиг стопа StopLossPips * pipSize. Для каждой сделки фиксируется собственная цена стопа, после чего значения синхронизируются — все активные заявки используют наиболее близкий защитный уровень.

Управление стопом

  • Для каждого исполненного уровня сохраняется цена входа и исходный стоп, рассчитанный в пунктах.
  • На каждом тике сделки происходит перерасчёт и выравнивание стопов: для покупок берётся максимальный стоп, для продаж — минимальный, что имитирует многократные вызовы OrderModify в MetaTrader.
  • При пересечении любой из общих стоп-цен стратегия отменяет оставшиеся отложенные заявки и закрывает корзину рыночными ордерами.

Управление капиталом

  • Нереализованная прибыль вычисляется через PriceStep и StepPrice, что позволяет точно повторить значения OrderProfit() из MetaTrader.
  • Если плавающая прибыль достигает MoneyTakeProfit, стратегия немедленно закрывает позицию и отменяет отложенные заявки.
  • При TradeAgainAfterProfit = false после достижения денежного тейк-профита торговля не возобновляется до ручного перезапуска.

Параметры

Название Описание
OpenBuy Разрешает построение бычьей лестницы (взаимоисключается с OpenSell).
OpenSell Разрешает построение медвежьей лестницы (взаимоисключается с OpenBuy).
TradeAgainAfterProfit Возобновлять ли торговлю после срабатывания денежного тейк-профита.
LevelDistancePips Расстояние в пунктах MetaTrader между последовательными стоп-заявками.
StopLossPips Пунктовый отступ защитного стопа для каждого исполненного уровня.
MoneyTakeProfit Денежный тейк-профит, при достижении которого закрывается вся корзина.
Level1VolumeLevel14Volume Объём каждого уровня Фибоначчи; значение 0 отключает уровень.

Особенности реализации

  • Пересчёт пунктов соответствует MetaTrader: при 3 или 5 знаках после запятой эффективный пункт равен PriceStep * 10.
  • При запуске вызывается StartProtection(), включая встроенные механизмы безопасности StockSharp.
  • Логика общего стопа держит все ордера синхронизированными; как только появляется более строгий стоп, он применяется ко всем активным уровням.
  • Отложенные заявки автоматически снимаются, когда корзина пустая, что соответствует многократным вызовам subCloseAllPending() в MQL-коде.

Рекомендации по использованию

  • Проверьте настройки инструмента (PriceStep, StepPrice, VolumeStep); без них расчёт пунктов и денежного тейк-профита будет неточным.
  • Стратегии усреднения быстро наращивают объём. Убедитесь, что лимиты по объёму и требования к марже соответствуют вашим условиям.
  • Установите TradeAgainAfterProfit = false, если нужно повторить «одноразовый» режим оригинального советника, прекращающий торговлю после успешного цикла.
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;
	}
}