Открыть на GitHub

Стратегия AH HM RSI

Обзор

Эта стратегия — порт MetaTrader-советника Expert_AH_HM_RSI на платформу StockSharp. Она ищет свечные модели «молот» и «повешенный» на закрытых барах и подтверждает их фильтром Relative Strength Index (RSI). Логика управления позициями повторяет оригинальный эксперт: при появлении противоположного сигнала позиция разворачивается сразу же.

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

  1. Фильтр тренда — короткая простая скользящая средняя (период по умолчанию 2) помогает определить, находится ли рынок в локальном восходящем или нисходящем движении.
  2. Свечная модель — анализируется последняя завершённая свеча.
    • Молот: тело находится в верхней трети диапазона свечи, текущая свеча открылась и закрылась ниже предыдущей, а её середина лежит ниже скользящей средней.
    • Повешенный: тело в верхней трети, открытие и закрытие выше предыдущей свечи, середина расположена выше скользящей средней.
  3. Фильтр RSI:
    • Для покупок RSI должен быть ниже порога для молота (по умолчанию 40).
    • Для продаж RSI должен быть выше порога для повешенного (по умолчанию 60).
  4. Исполнение сделок — при срабатывании сигнала стратегия выставляет заявку на объём Volume + |Position|, что обеспечивает мгновенный разворот при противоположном сигнале.
  5. Выход — позиции закрываются, когда RSI пробивает вниз верхний уровень (70) или пробивает вверх нижний уровень (30), что повторяет схему «голосов» в исходном коде.

Индикаторы

  • RelativeStrengthIndex (период 33).
  • SimpleMovingAverage (период 2, рассчитывается по ценам закрытия).

Параметры

Имя Описание Значение по умолчанию
Volume Базовый торговый объём. 1
RsiPeriod Период RSI. 33
MaPeriod Период скользящей средней. 2
HammerRsiThreshold Максимальное значение RSI для подтверждения молота. 40
HangingManRsiThreshold Минимальное значение RSI для подтверждения повешенного. 60
LowerExitLevel Уровень RSI для закрытия коротких позиций при росте. 30
UpperExitLevel Уровень RSI для закрытия длинных позиций при падении. 70
CandleType Используемый таймфрейм свечей. 1 час

Все параметры доступны для оптимизации через интерфейс StockSharp.

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

  • Стратегия работает только с завершёнными свечами — убедитесь, что источник данных отдаёт закрытые бары выбранного таймфрейма.
  • Благодаря подаче заявок на Volume + |Position| любая новая противоположная модель моментально разворачивает позицию.
  • Метод StartProtection() вызывается один раз при запуске, активируя встроенную защиту счёта.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Hammer/Hanging Man + RSI strategy.
/// Buys on hammer with low RSI, sells on hanging man with high RSI.
/// </summary>
public class AhHmRsiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiLow;
	private readonly StrategyParam<decimal> _rsiHigh;

	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 AhHmRsiStrategy()
	{
		_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 for buy", "Signals");
		_rsiHigh = Param(nameof(RsiHigh), 60m)
			.SetDisplay("RSI High", "RSI overbought threshold for sell", "Signals");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		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;

		var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
		var range = candle.HighPrice - candle.LowPrice;
		if (range <= 0 || body <= 0) return;

		var upperShadow = candle.HighPrice - Math.Max(candle.OpenPrice, candle.ClosePrice);
		var lowerShadow = Math.Min(candle.OpenPrice, candle.ClosePrice) - candle.LowPrice;

		var isHammer = lowerShadow > body * 2 && upperShadow < body;
		var isHangingMan = upperShadow > body * 2 && lowerShadow < body;

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