Открыть на GitHub

Стратегия AMS ES RSI

Краткое описание

Стратегия AMS ES RSI переносит логику советника MetaTrader Expert_AMS_ES_RSI в StockSharp. Она сочетает свечные модели «утренняя/вечерняя звезда» с подтверждением по индикатору RSI. Покупки выполняются при появлении бычьей утренней звезды в зоне перепроданности RSI, продажи — при возникновении медвежьей вечерней звезды вместе с сигналом перекупленности. Выход из позиций осуществляется при обратном пересечении RSI заданных уровней.

Предпосылки рынка

  • Подходит для любых инструментов, формирующих стандартные свечи OHLC. Изначально советник предназначался для рынка Forex и индексных фьючерсов.
  • Предполагается наличие читаемых свечных формаций. На сверхшумных тиковых данных сигналы могут быть недостоверными.

Логика входа

  1. Подписаться на выбранный таймфрейм (по умолчанию 1 час) и дождаться формирования трёх закрытых свечей.
  2. Рассчитать средний размер тела за последние BodyAveragePeriod свечей (по умолчанию 3).
  3. Определить утреннюю звезду, если выполняются условия:
    • Свеча 3 — выраженно медвежья (Open - Close больше среднего тела).
    • Свеча 2 имеет маленькое тело (менее половины среднего) и формирует гэп вниз относительно свечи 3.
    • Свеча 1 закрывается выше середины тела свечи 3.
  4. Аналогично выявить вечернюю звезду для медвежьего сигнала.
  5. Подтвердить длинный вход, когда текущее значение RSI ниже LongEntryRsi (по умолчанию 40). Для коротких позиций RSI должен быть выше ShortEntryRsi (по умолчанию 60).
  6. Размещать рыночные ордера, используя параметр Volume стратегии.

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

  • Закрывать длинные позиции при нисходящем пересечении RSI уровней UpperExitRsi (по умолчанию 70) или LowerExitRsi (по умолчанию 30).
  • Закрывать короткие позиции при восходящем пересечении этих же границ.
  • Жёсткие стоп-лосс/тейк-профит не применяются. Управление риском следует реализовывать внешними средствами либо корректировкой порогов.

Параметры

Имя Описание Значение по умолчанию Диапазон
CandleType Тип свечей для подписки. Часовой таймфрейм Любые поддерживаемые свечи
RsiPeriod Период расчёта RSI. 47 Оптимизация (10–70)
BodyAveragePeriod Количество свечей для среднего размера тела. 3 Оптимизация (2–6)
LongEntryRsi Максимум RSI для входа в лонг. 40 Оптимизация (20–50)
ShortEntryRsi Минимум RSI для входа в шорт. 60 Оптимизация (50–80)
LowerExitRsi Нижняя граница выхода при пересечении вверх. 30 Оптимизация (20–40)
UpperExitRsi Верхняя граница выхода при пересечении вниз. 70 Оптимизация (60–80)

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

  • Используется высокоуровневый API StockSharp с автоматической подпиской на свечи.
  • Индикаторные значения поступают через Bind; обращения к GetValue не требуются.
  • Хранится только небольшой буфер из трёх свечей для проверки паттерна.
  • В OnStarted вызывается StartProtection() для активации встроенных механизмов защиты.

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

  1. Запустите стратегию на выбранном инструменте и убедитесь, что коннектор предоставляет свечной ряд.
  2. Подбирайте уровни RSI с учётом волатильности актива: более широкие пороги снижают частоту сделок, но повышают качество сигналов.
  3. При необходимости подключите внешние модули управления объёмом, чтобы имитировать фиксированный лот оригинального советника.
  4. Для тестирования убедитесь, что исторические данные содержат гэпы — они важны для корректного распознавания звёзд.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Morning/Evening Star + RSI strategy.
/// Buys on morning star with low RSI, sells on evening star with high RSI.
/// </summary>
public class AmsEsRsiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiLow;
	private readonly StrategyParam<decimal> _rsiHigh;

	private ICandleMessage _prevCandle;
	private ICandleMessage _prevPrevCandle;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal RsiLow { get => _rsiLow.Value; set => _rsiLow.Value = value; }
	public decimal RsiHigh { get => _rsiHigh.Value; set => _rsiHigh.Value = value; }

	public AmsEsRsiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
		_rsiLow = Param(nameof(RsiLow), 40m)
			.SetDisplay("RSI Low", "RSI oversold threshold", "Signals");
		_rsiHigh = Param(nameof(RsiHigh), 60m)
			.SetDisplay("RSI High", "RSI overbought threshold", "Signals");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevCandle = null;
		_prevPrevCandle = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCandle = null;
		_prevPrevCandle = null;
		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 (_prevCandle != null && _prevPrevCandle != null)
		{
			var prevBody = Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice);
			var prevRange = _prevCandle.HighPrice - _prevCandle.LowPrice;
			var isSmallBody = prevRange > 0 && prevBody < prevRange * 0.3m;

			var firstBearish = _prevPrevCandle.OpenPrice > _prevPrevCandle.ClosePrice;
			var currBullish = candle.ClosePrice > candle.OpenPrice;
			var isMorningStar = firstBearish && isSmallBody && currBullish;

			var firstBullish = _prevPrevCandle.ClosePrice > _prevPrevCandle.OpenPrice;
			var currBearish = candle.OpenPrice > candle.ClosePrice;
			var isEveningStar = firstBullish && isSmallBody && currBearish;

			if (isMorningStar && rsiValue < RsiLow && Position <= 0)
				BuyMarket();
			else if (isEveningStar && rsiValue > RsiHigh && Position >= 0)
				SellMarket();
		}

		_prevPrevCandle = _prevCandle;
		_prevCandle = candle;
	}
}