Открыть на GitHub

Стратегия Bago EA Classic

Порт на StockSharp повторяет советник MetaTrader из файла MQL/7656/Bago_ea.mq4. Вся логика трендовой торговли сохранена: входы появляются только при синхронных пробоях EMA и RSI в сторону тренда, а туннель Vegas (EMA 144/169) фильтрует ложные сигналы и служит основой для поэтапного трейлинг-стопа.

Подробная логика

  1. Набор индикаторов
    • Быстрая и медленная EMA (FastPeriod/SlowPeriod) с настраиваемым методом MaMethod и ценой MaAppliedPrice.
    • Пара EMA с периодами 144 и 169 формирует туннель Vegas и использует те же настройки, что и рабочие средние.
    • RSI (RsiPeriod, RsiAppliedPrice) отслеживает пересечения уровня 50.
    • Все индикаторы получают данные из свечного подписки CandleType через высокоуровневый метод Bind.
  2. Машина состояний пересечений
    • Пересечения EMA и RSI фиксируются флагами «вверх/вниз» и счётчиками баров. Состояние активно CrossEffectiveBars закрытых свечей либо до появления противоположного пересечения, как в MQL-версии.
    • Дополнительные флаги туннеля фиксируют, когда цена переходит на другую сторону Vegas, что определяет режим сопровождения позиции.
  3. Торговые сессии
    • Сделки разрешены только в выбранные периоды: Лондон (07–16), Нью-Йорк (12–21), Токио (00–08 плюс свеча 23:00). Переключатели соответствуют extern bool из оригинального кода.
  4. Фильтры входов
    • Покупка: нужны активные флаги EMA-up и RSI-up и либо закрытие выше туннеля минимум на TunnelBandWidthPips, но не дальше TunnelSafeZonePips, либо откат под туннель на TunnelBandWidthPips с последующим отбоем.
    • Продажа: зеркальная проверка для пересечений вниз и симметричных уровней туннеля.
    • При наличии противоположной позиции она закрывается рыночной заявкой перед открытием новой — полный аналог OrderClose из MetaTrader.
  5. Ведение позиции
    • Базовый стоп выставляется на StopLossPips от цены входа. При парковке около туннеля стоп переносится с учётом StopLossToFiboPips, что повторяет «фибо»-буфер советника.
    • Этапы трейлинга соответствуют уровням тейк-профита EA: стоп смещается к туннелю ±(TrailingStepX + StopLossToFiboPips) и постепенно переходит к жёсткому трейлингу TrailingStopPips.
    • Частичные фиксации (PartialClose1Volume, PartialClose2Volume) выполняются при достижении TrailingStep1Pips и TrailingStep2Pips. Остаток объёма сопровождается до третьего уровня TrailingStep3Pips.
    • Любое противоположное пересечение EMA/RSI немедленно закрывает всю позицию.
  6. Работа с ордерами
    • Защитные приказы создаются через SellStop/BuyStop. При каждом переносе стопа предыдущий ордер отменяется и ставится новый — аналог циклических OrderModify.
    • Пересчёт пунктов использует PriceStep инструмента и автоматически учитывает 3- и 5-значные котировки (умножение шага на десять), как в MetaTrader.

Параметры

Параметр Тип Значение по умолчанию Описание
TradeVolume decimal 3 Совокупный объём новой позиции.
StopLossPips decimal 30 Дистанция первоначального стоп-лосса в пунктах.
StopLossToFiboPips decimal 20 Дополнительный буфер при переносе стопа возле туннеля.
TrailingStopPips decimal 30 Шаг жёсткого трейлинга, когда цена вышла далеко от туннеля.
TrailingStep1Pips decimal 55 Первый уровень прибыли (TP1).
TrailingStep2Pips decimal 89 Второй уровень прибыли (TP2).
TrailingStep3Pips decimal 144 Третий уровень прибыли (TP3) перед переходом к чистому трейлингу.
PartialClose1Volume decimal 1 Объём частичного закрытия на первом уровне.
PartialClose2Volume decimal 1 Объём частичного закрытия на втором уровне.
CrossEffectiveBars int 2 Количество свечей, в течение которых флаги пересечений остаются актуальными.
TunnelBandWidthPips decimal 5 Нейтральная зона вокруг туннеля, где новые сделки не открываются.
TunnelSafeZonePips decimal 120 Максимальное удаление цены от туннеля для входа по пробою.
EnableLondonSession bool true Разрешить торговлю с 07:00 до 16:00.
EnableNewYorkSession bool true Разрешить торговлю с 12:00 до 21:00.
EnableTokyoSession bool false Разрешить торговлю с 00:00 до 08:00 и на свече 23:00.
FastPeriod int 5 Период быстрой EMA.
SlowPeriod int 12 Период медленной EMA.
MaShift int 0 Горизонтальный сдвиг средних.
MaMethod MovingAverageType Exponential Метод расчёта средних.
MaAppliedPrice AppliedPriceType Close Цена, подаваемая в EMA.
RsiPeriod int 21 Период сглаживания RSI.
RsiAppliedPrice AppliedPriceType Close Цена, подаваемая в RSI.
CandleType DataType H1 Свечной источник данных.

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

  • Используется только высокоуровневый API: подписка на свечи, Bind и торговые методы BuyMarket/SellMarket/BuyStop/SellStop.
  • Списки с историческими значениями имитируют индексацию баров (Close[1], Close[2]) из MQL и ограничиваются HistoryLimit.
  • Метод StartProtection() запускает встроенный механизм защиты позиций сразу после старта стратегии.
  • Все комментарии в коде даны на английском языке для единообразия репозитория.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Bago EA strategy - EMA crossover with RSI confirmation.
/// Buys when fast EMA crosses above slow EMA and RSI is above 50.
/// Sells when fast EMA crosses below slow EMA and RSI is below 50.
/// </summary>
public class BagoEaClassicStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiLevel;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal RsiLevel { get => _rsiLevel.Value; set => _rsiLevel.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BagoEaClassicStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 5)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 12)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI period", "Indicators");

		_rsiLevel = Param(nameof(RsiLevel), 50m)
			.SetDisplay("RSI Level", "RSI neutral level", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

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

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal rsi)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fast > slow;
		var crossDown = _prevFast >= _prevSlow && fast < slow;

		if (crossUp && rsi > RsiLevel && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (crossDown && rsi < RsiLevel && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}