Открыть на GitHub

Стратегия Elite eFibo Trader

Общее описание

Elite eFibo Trader воспроизводит советника усреднения, который открывает серию ордеров по последовательности Фибоначчи и контролирует тренд с помощью пересечения скользящих средних и дополнительного фильтра RSI. Порт под StockSharp сохраняет корзинную механику: рыночный вход мгновенно сопровождается стоп-ордерами на следующих уровнях через заданное количество пунктов, а каждый новый сработавший уровень увеличивает позицию по схеме Фибоначчи. Корзина закрывается, когда плавающая прибыль достигает заданного денежного значения или когда фильтр тренда разворачивается против текущей позиции.

Рыночные данные

  • Подписка выполняется на один тип свечей, задаваемый параметром (по умолчанию 15‑минутные свечи).
  • Для расчёта индикаторов и проверки стопов используется цена закрытия свечи.

Логика входа

  1. Направление задаётся либо логикой пересечения скользящих средних (включена по умолчанию), либо ручными переключателями ManualOpenBuy/ManualOpenSell.
  2. При активной MA-логике бычье пересечение (быстрая SMA выше медленной) разрешает набор длинной корзины, а медвежье пересечение — короткой. На один бар генерируется только один сигнал.
  3. Если включён фильтр RSI, длинные корзины открываются лишь при RSI > RsiHigh, короткие — при RSI < RsiLow.
  4. Новая лестница запускается только при отсутствии активных ордеров и позиций стратегии и если разрешена торговля (TradeAgainAfterProfit).
  5. Первый уровень открывается рыночным ордером, остальные выставляются как стоп-ордера с отступом LevelDistancePips. Объёмы задаются для каждого уровня и по умолчанию соответствуют числам Фибоначчи.

Логика выхода

  • Каждый исполненный уровень получает стартовый стоп на расстоянии StopLossPips и участвует в тралении, когда MA-логика фиксирует неблагоприятное пересечение.
  • Траление смещает стоп до close - TrailingStopPips для длин и close + TrailingStopPips для коротких, не увеличивая изначальный риск.
  • При достижении стоп-уровня (по минимуму/максимуму свечи) оставшийся объём уровня закрывается рыночным ордером.
  • Если суммарная плавающая прибыль корзины (рассчитывается через PriceStep и StepPrice инструмента) превышает MoneyTakeProfit, стратегия закрывает все позиции и снимает отложенные ордера.
  • После полного выхода любые стоп-ордера удаляются автоматически. Если TradeAgainAfterProfit = false, стратегия остаётся в режиме ожидания до ручного сброса.

Параметры

Параметр Описание
UseMaLogic Включить/выключить логику пересечения скользящих средних.
MaSlowPeriod, MaFastPeriod Периоды медленной и быстрой SMA.
TrailingStopPips Дистанция тралящего стопа в пунктах при неблагоприятном сигнале.
UseRsiFilter, RsiPeriod, RsiHigh, RsiLow Настройки фильтра RSI. Лонги разрешены выше RsiHigh, шорты — ниже RsiLow.
ManualOpenBuy, ManualOpenSell Ручные переключатели направления при отключённой MA-логике.
TradeAgainAfterProfit Разрешить повторный запуск корзины после достижения денежной цели.
LevelDistancePips Расстояние между уровнями усреднения в пунктах.
StopLossPips Начальное смещение стопа для каждого уровня.
MoneyTakeProfit Денежная цель по плавающей прибыли корзины.
Level1VolumeLevel14Volume Объём каждого уровня. Значение 0 отключает уровень.
CandleType Тип свечей/таймфрейм для расчётов.

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

  • Преобразование «пунктов» выполнено как в оригинальном MQL: при количестве знаков котировки 3 или 5 используется PriceStep * 10, что соответствует переменной MyPoint в советнике.
  • Каждый уровень хранит собственные данные — цену входа, остаток объёма и стоп. Это позволяет корректно обрабатывать частичные исполнения и индивидуальные стоп-ауты.
  • Плавающая прибыль вычисляется через PriceStep и StepPrice. Убедитесь, что у инструмента эти свойства заданы, иначе MoneyTakeProfit не сработает.
  • StartProtection() вызывается один раз при запуске, включая встроенные защитные механизмы StockSharp.
  • При отсутствии открытых объёмов автоматически отменяются все отложенные ордера, что повторяет многократные вызовы subCloseAllPending() в оригинале.

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

  • Проверьте настройки брокера: PriceStep, StepPrice, VolumeStep, минимальный и максимальный лот, чтобы объёмы Фибоначчи соответствовали допустимым значениям.
  • Подбирайте таймфрейм свечей в соответствии с используемым в MetaTrader графиком.
  • Системы усреднения могут быстро накапливать позицию при затяжном тренде — сначала протестируйте стратегию на демо или исторических данных.
  • Отключите UseMaLogic, если нужно вручную фиксировать направление, либо оставьте включённым для автоматического определения тренда.
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Elite eFibo Trader: MA crossover with RSI filter and grid averaging.
/// Adds to winning positions on pullbacks using Fibonacci-style scaling.
/// </summary>
public class EliteEfiboTraderStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _addCount;

	public EliteEfiboTraderStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_fastLength = Param(nameof(FastLength), 10)
			.SetDisplay("Fast MA", "Fast SMA period.", "Indicators");

		_slowLength = Param(nameof(SlowLength), 30)
			.SetDisplay("Slow MA", "Slow SMA period.", "Indicators");

		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI filter period.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	public int RsiLength
	{
		get => _rsiLength.Value;
		set => _rsiLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;
		_addCount = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;
		_addCount = 0;

		var fast = new SimpleMovingAverage { Length = FastLength };
		var slow = new SimpleMovingAverage { Length = SlowLength };
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, rsi, atr, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fast);
			DrawIndicator(area, slow);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal, decimal rsiVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		var close = candle.ClosePrice;

		// Position management
		if (Position > 0)
		{
			// Take profit or stop
			if (close >= _entryPrice + atrVal * 3m)
			{
				SellMarket();
				_entryPrice = 0;
				_addCount = 0;
			}
			else if (close <= _entryPrice - atrVal * 2m)
			{
				SellMarket();
				_entryPrice = 0;
				_addCount = 0;
			}
			else if (_addCount < 2 && close <= _entryPrice - atrVal * 0.8m && rsiVal < 40)
			{
				// Fibonacci add: buy more on pullback
				_entryPrice = (_entryPrice + close) / 2m;
				_addCount++;
				BuyMarket();
			}
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 3m)
			{
				BuyMarket();
				_entryPrice = 0;
				_addCount = 0;
			}
			else if (close >= _entryPrice + atrVal * 2m)
			{
				BuyMarket();
				_entryPrice = 0;
				_addCount = 0;
			}
			else if (_addCount < 2 && close >= _entryPrice + atrVal * 0.8m && rsiVal > 60)
			{
				_entryPrice = (_entryPrice + close) / 2m;
				_addCount++;
				SellMarket();
			}
		}

		// Entry: MA crossover with RSI confirmation
		if (Position == 0)
		{
			if (_prevFast <= _prevSlow && fastVal > slowVal && rsiVal > 50)
			{
				_entryPrice = close;
				_addCount = 0;
				BuyMarket();
			}
			else if (_prevFast >= _prevSlow && fastVal < slowVal && rsiVal < 50)
			{
				_entryPrice = close;
				_addCount = 0;
				SellMarket();
			}
		}

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}