Открыть на GitHub

RSI Bollinger Bands EA (конверсия StockSharp)

Обзор

Стратегия представляет собой конвертацию советника MetaTrader 5 «RSI Bollinger Bands EA» на высокоуровневый API StockSharp. Работает на 15-минутных свечах и использует две независимые RSI-конфигурации:

  • Триггер 1 – жесткие уровни перекупленности/перепроданности RSI для M15, H1 и H4, дополненные фильтром стохастика и проверкой наклона RSI на M15.
  • Триггер 2 – адаптивные RSI-диапазоны, рассчитываемые по асимметричным стандартным отклонениям (отдельно для положительных и отрицательных отклонений) на всех трех таймфреймах.

Обе логики требуют сжатия цены на рабочем таймфрейме (узкий Bollinger на M15), одновременно расширенного диапазона на H4 и низкой волатильности по ATR на H4. Одновременно можно включить только один триггер.

Необходимые данные

  • Основные свечи исполнения: M15CandleType (по умолчанию 15 минут).
  • Подтверждающие свечи: H1CandleType (по умолчанию 1 час) для условий RSI и расчета статистики.
  • Старшие свечи: H4CandleType (по умолчанию 4 часа) для фильтров Bollinger и ATR.

Логика торговли

  1. Сессионные фильтры

    • Торговля ведется в окне, начинающемся в EntryHour и продолжающемся OpenHours часов. Если OpenHours = 0, окно действует ровно один час.
    • В пятницу торговля прекращается после наступления часа FridayEndHour.
    • Новые позиции открываются только при нулевой текущей позиции (Position == 0).
  2. Фильтры волатильности (для обоих триггеров)

    • Размах полос Боллинджера на H4 должен превышать BbSpreadH4MinX пунктов, чтобы подтвердить достаточную активность на старшем таймфрейме.
    • Размах полос на M15 должен быть меньше BbSpreadM15MaxX пунктов, показывая консолидацию.
    • ATR на H4, пересчитанный в пункты, должен быть ниже AtrLimit.
  3. Триггер 1 – фиксированные уровни RSI

    • Значения RSI для M15/H1/H4 должны находиться ниже порогов «Low», но выше защитных уровней «Low Limit» для лонгов.
    • Разница между текущим и предыдущим RSI M15 должна быть больше RDeltaM15Lim1 (по модулю) для подтверждения разворота.
    • Стохастик должен быть ниже StocLoM15_1 для покупок и выше StocHiM15_1 для продаж.
    • Для шортов RSI на всех таймфреймах должны превышать пороги «High», но оставаться ниже ограничений «High Limit».
  4. Триггер 2 – адаптивные сигма-диапазоны RSI

    • Для каждого таймфрейма хранится до NumRsi последних значений RSI. На их основе считаются среднее и отдельные стандартные отклонения для положительной и отрицательной частей распределения.
    • Нижние и верхние адаптивные границы строятся с учетом множителей Rsi*M*Sigma2, а «лимитные» границы – с коэффициентами Rsi*M*SigmaLim2.
    • Лонг возможен, когда RSI M15/H1/H4 ниже адаптивных нижних границ, но выше лимитных значений, стохастик < StocLoM15_2, а наклон RSI превышает RDeltaM15Lim2.
    • Шорт формируется зеркально относительно верхних границ и ограничений.
  5. Исполнение и выходы

    • При срабатывании триггера выставляется рыночная заявка объемом Volume (по умолчанию 0.1 лота).
    • Уровни стоп-лосса и тейк-профита рассчитываются на основе соответствующих параметров в пунктах и размера пункта инструмента.
    • Стоп и тейк имитируются: на каждой новой свече M15 проверяются экстремумы. При касании уровня позиция закрывается рыночной заявкой, а защитные уровни сбрасываются.

Параметры

Параметр Описание Значение по умолчанию
Volume Торговый объем в лотах. 0.1
TriggerOne Включить триггер с фиксированными уровнями RSI. true
TriggerTwo Включить адаптивный триггер (взаимоисключающий). false
BbSpreadH4Min1 Минимальный размах полос Боллинджера на H4 для триггера 1 (пункты). 84
BbSpreadM15Max1 Максимальный размах полос на M15 для триггера 1 (пункты). 64
RsiPeriod1 Период RSI для триггера 1. 10
RsiLoM15_1, RsiHiM15_1 Пороговые значения RSI для M15. 24, 66
RsiLoH1_1, RsiHiH1_1 Пороговые значения RSI для H1. 34, 54
RsiLoH4_1, RsiHiH4_1 Пороговые значения RSI для H4. 48, 56
RsiLoLim*, RsiHiLim* Ограничения для экстремальных значений RSI. 20–92
RDeltaM15Lim1 Минимальный наклон RSI на M15 (лонг – рост, шорт – падение). -3.5
StocLoM15_1, StocHiM15_1 Границы стохастика для триггера 1. 26, 64
BbSpreadH4Min2 Минимальный размах полос на H4 для триггера 2. 65
BbSpreadM15Max2 Максимальный размах полос на M15 для триггера 2. 75
RsiPeriod2 Период RSI для триггера 2. 20
NumRsi Размер очереди исторических значений RSI. 60
Rsi*M*Sigma2 Множители сигмы для основных адаптивных границ (M15/H1/H4). 1.20 / 0.95 / 0.9
Rsi*M*SigmaLim2 Множители сигмы для внешних ограничений. 1.85 / 2.55 / 2.7
RDeltaM15Lim2 Минимальный наклон RSI на M15 для триггера 2. -5.5
StocLoM15_2, StocHiM15_2 Пороговые значения стохастика для триггера 2. 24, 68
TakeProfitBuy1, StopLossBuy1 Тейк-профит / стоп-лосс (пункты) для лонгов триггера 1. 150, 70
TakeProfitSell1, StopLossSell1 Тейк-профит / стоп-лосс (пункты) для шортов триггера 1. 70, 35
TakeProfitBuy2, StopLossBuy2 Тейк-профит / стоп-лосс (пункты) для лонгов триггера 2. 140, 35
TakeProfitSell2, StopLossSell2 Тейк-профит / стоп-лосс (пункты) для шортов триггера 2. 60, 30
AtrPeriod Период ATR на H4. 60
BollingerPeriod Длина полос Боллинджера на M15 и H4. 20
AtrLimit Максимальное значение ATR (пункты). 90
EntryHour Час начала торговой сессии. 0
OpenHours Длительность торгового окна (0 = один час). 14
NumPositions Максимальное количество одновременно открытых позиций. 1
FridayEndHour Час пятницы, после которого входы запрещены. 4
StochasticK, StochasticD, StochasticSlowing Настройки стохастика. 12 / 5 / 5
M15CandleType, H1CandleType, H4CandleType Типы свечей для каждого таймфрейма. 15m / 1h / 4h

Примечания

  • В оригинальном советнике стопы оформлялись стоп-заявками. В конверсии они имитируются проверкой экстремумов свечей M15.
  • Для корректной работы необходимо, чтобы источник данных предоставлял все задействованные таймфреймы – иначе очереди RSI не заполнятся и сигналы не появятся.
  • Размер пункта вычисляется по шагу цены инструмента; для 5-значных и 3-значных символов применяется множитель 10, как в MetaTrader.
namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// RSI Bollinger Bands strategy.
/// Buys when RSI is oversold and price is near the lower Bollinger Band.
/// Sells when RSI is overbought and price is near the upper Bollinger Band.
/// </summary>
public class RsiBollingerBandsEaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _bbPeriod;
	private readonly StrategyParam<decimal> _rsiOversold;
	private readonly StrategyParam<decimal> _rsiOverbought;

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

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public int BbPeriod
	{
		get => _bbPeriod.Value;
		set => _bbPeriod.Value = value;
	}

	public decimal RsiOversold
	{
		get => _rsiOversold.Value;
		set => _rsiOversold.Value = value;
	}

	public decimal RsiOverbought
	{
		get => _rsiOverbought.Value;
		set => _rsiOverbought.Value = value;
	}

	public RsiBollingerBandsEaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for strategy", "General");

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

		_bbPeriod = Param(nameof(BbPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("BB Period", "Bollinger Bands length", "Indicators");

		_rsiOversold = Param(nameof(RsiOversold), 35m)
			.SetDisplay("RSI Oversold", "Oversold level for buy signal", "Signals");

		_rsiOverbought = Param(nameof(RsiOverbought), 65m)
			.SetDisplay("RSI Overbought", "Overbought level for sell signal", "Signals");
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var bb = new BollingerBands { Length = BbPeriod, Width = 2m };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(rsi, bb, (ICandleMessage candle, IIndicatorValue rsiValue, IIndicatorValue bbValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var rsiVal = rsiValue.ToDecimal();
				var bbTyped = (BollingerBandsValue)bbValue;
				var bbUpper = bbTyped.UpBand;
				var bbLower = bbTyped.LowBand;

				// Buy when RSI is oversold and price near lower band
				if (rsiVal < RsiOversold && candle.ClosePrice <= bbLower && Position <= 0)
				{
					BuyMarket();
				}
				// Sell when RSI is overbought and price near upper band
				else if (rsiVal > RsiOverbought && candle.ClosePrice >= bbUpper && Position >= 0)
				{
					SellMarket();
				}
			})
			.Start();

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