Открыть на GitHub

Стратегия ABE BE RSI

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

ABE BE RSI — порт советника MetaTrader Expert_ABE_BE_RSI. Стратегия сочетает японские свечные модели «бычье/медвежье поглощение» с подтверждением импульса через индекс относительной силы (RSI). Для формирования сигнала требуется две подряд завершённые свечи с паттерном поглощения, а также значение RSI последней закрытой свечи в заданном диапазоне. Дополнительно отслеживаются пересечения RSI с ключевыми уровнями, что позволяет вовремя закрывать или переворачивать позицию. Такое поведение максимально повторяет исходный механизм голосов в MQL-версии.

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

  1. Определение паттерна поглощения
    После закрытия каждой свечи анализируются две предыдущие:

    • Для бычьего сигнала свеча t-2 должна быть медвежьей, свеча t-1 — бычьей.
    • Тело свечи t-1 должно превышать средний размер тел за последние MovingAveragePeriod свечей.
    • Свеча t-1 закрывается выше открытия свечи t-2 и открывается ниже её закрытия, что обеспечивает полное поглощение.
    • Средняя точка свечи t-2 расположена ниже скользящей средней по закрытиям, подтверждая локальный нисходящий тренд.

    Для медвежьего сигнала условия зеркальны: более старая свеча бычья, новая — медвежья с крупным телом, полностью покрывающим тело предыдущей свечи, при этом средняя точка старой свечи находится выше скользящей средней закрытий.

  2. Фильтрация по RSI

    • Покупка разрешена, если RSI последней закрытой свечи ниже BullishEntryLevel (по умолчанию 40).
    • Продажа разрешена, если RSI последней закрытой свечи выше BearishEntryLevel (по умолчанию 60).
  3. Управление выходами
    Пересечения RSI с двумя уровнями управляют закрытием позиций:

    • Короткие позиции закрываются, когда RSI поднимается выше ExitLowerLevel (30) или ExitUpperLevel (70) после нахождения ниже этих уровней.
    • Длинные позиции закрываются при обратном пересечении сверху вниз.
  4. Исполнение заявок
    Все операции выполняются рыночными заявками. При смене направления текущая позиция закрывается, затем открывается новая с базовым объёмом Volume, что соответствует фиксированному лоту в оригинальном советнике.

Параметры

Параметр Описание Значение по умолчанию
Volume Объём сделки в контрактах. 0.1
RsiPeriod Период расчёта RSI. 11
MovingAveragePeriod Период скользящих средних по телам и закрытиям свечей. 5
BullishEntryLevel Максимальное значение RSI для подтверждения бычьего сигнала. 40
BearishEntryLevel Минимальное значение RSI для подтверждения медвежьего сигнала. 60
ExitLowerLevel Нижний уровень RSI, используемый для фиксации прибыли/убытка. 30
ExitUpperLevel Верхний уровень RSI для закрытия позиций. 70
CandleType Тип/период свечей, с которыми работает стратегия. 1 час

Все параметры реализованы через StrategyParam, поэтому поддерживают оптимизацию в Designer и Runner.

Набор индикаторов

  • Relative Strength Index — основной фильтр импульса, задаёт входные и выходные уровни.
  • Простая скользящая средняя закрытий — оценивает локальный тренд и помогает отфильтровать ложные поглощения.
  • Простая скользящая средняя тел свечей — проверяет, что новая свеча действительно крупнее типичных баров.

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

  • Обработка выполняется только по завершённым свечам (CandleStates.Finished), чтобы избежать преждевременных сигналов.
  • Внутри стратегии хранится лишь минимально необходимый набор значений (две последние свечи и их индикаторы), что соответствует требованиям репозитория по эффективности.
  • В OnStarted вызывается StartProtection(), что активирует стандартные защитные механизмы StockSharp при появлении позиции.

Отличия от оригинального советника

  • Система голосов MetaTrader заменена на прямые торговые действия с теми же условиями.
  • Управление капиталом сведено к одному параметру Volume, аналогичному фиксированному лоту Money_FixLot_Lots.
  • Модуль трейлинг-стопа отсутствует, как и в исходном наборе модулей (TrailingNone).

Рекомендации по тестированию

  1. Запустите стратегию в Designer или Runner на инструментах, где свечные разворотные модели показывают устойчивые результаты (например, основные валютные пары).
  2. Перед запуском уточните значения RSI и скользящих средних для вашего инструмента; дефолтные настройки совпадают с MetaTrader-версией.
  3. Используйте оптимизацию, чтобы подобрать иные пороги или период усреднения под конкретный рынок.
namespace StockSharp.Samples.Strategies;

using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// ABE BE RSI strategy: Engulfing pattern with RSI confirmation.
/// Bullish engulfing + oversold RSI for long, bearish engulfing + overbought RSI for short.
/// </summary>
public class AbeBeRsiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _oversold;
	private readonly StrategyParam<decimal> _overbought;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private readonly List<ICandleMessage> _candles = new();
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
	public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public AbeBeRsiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
		_oversold = Param(nameof(Oversold), 40m)
			.SetDisplay("Oversold", "RSI oversold level", "Signals");
		_overbought = Param(nameof(Overbought), 60m)
			.SetDisplay("Overbought", "RSI overbought level", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_candles.Clear();
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candles.Clear();
		_candlesSinceTrade = SignalCooldownCandles;
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		_candles.Add(candle);
		if (_candles.Count > 5)
			_candles.RemoveAt(0);

		if (_candles.Count >= 2)
		{
			var curr = _candles[^1];
			var prev = _candles[^2];

			var bullishEngulfing = prev.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice > curr.OpenPrice
				&& curr.OpenPrice <= prev.ClosePrice
				&& curr.ClosePrice >= prev.OpenPrice;

			var bearishEngulfing = prev.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice > curr.ClosePrice
				&& curr.OpenPrice >= prev.ClosePrice
				&& curr.ClosePrice <= prev.OpenPrice;

			if (bullishEngulfing && rsiValue < Oversold && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (bearishEngulfing && rsiValue > Overbought && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}
	}
}