GitHub で見る

AH HM RSI Strategy

Overview

This strategy is a StockSharp port of the MetaTrader expert Expert_AH_HM_RSI. It looks for hammer or hanging man candlestick patterns and requires a confirming signal from the Relative Strength Index (RSI) before trading. The approach mirrors the original Expert Advisor, including its risk management philosophy of reversing positions when a fresh signal appears.

Trading Logic

  1. Trend Filter – A short Simple Moving Average (default length 2) is used to determine whether the market is in a micro downtrend or uptrend.
  2. Candlestick Pattern – The strategy analyses the most recent completed candle:
    • A hammer is detected when the body sits in the upper third of the range, the candle gaps lower than the previous bar, and the midpoint of the candle is below the moving-average trend.
    • A hanging man is detected when the body sits in the upper third, the candle gaps higher than the previous bar, and the midpoint of the candle is above the moving-average trend.
  3. RSI Filter
    • Long trades require the RSI to be below the configurable hammer threshold (default 40).
    • Short trades require the RSI to be above the hanging-man threshold (default 60).
  4. Trade Execution – On a valid signal the strategy enters with Volume + |Position|, so open positions are reversed immediately when the opposite setup arrives.
  5. Exit Rules – Positions are flattened when the RSI crosses the configurable lower (default 30) or upper (default 70) boundaries in the opposite direction, replicating the exit votes in the original code.

Indicators

  • RelativeStrengthIndex (length 33 by default).
  • SimpleMovingAverage (length 2 by default) applied to candle closes.

Parameters

Name Description Default
Volume Order size used for entries. 1
RsiPeriod RSI lookback period. 33
MaPeriod Moving-average period for the trend filter. 2
HammerRsiThreshold Maximum RSI value that allows a hammer long entry. 40
HangingManRsiThreshold Minimum RSI value that allows a hanging-man short entry. 60
LowerExitLevel RSI boundary used to close shorts after an upward cross. 30
UpperExitLevel RSI boundary used to close longs after a downward cross. 70
CandleType Timeframe processed by the strategy. 1 hour candles

All parameters can be optimised via the StockSharp parameter UI.

Usage Notes

  • The logic works exclusively on finished candles. Ensure the selected timeframe and data feed produce complete bars.
  • Because the reversal logic always trades Volume + |Position|, positions flip direction instantly on the opposite signal, matching the Expert Advisor.
  • Start the built-in risk management once at launch (StartProtection() is called in OnStarted).

Files

  • CS/AhHmRsiStrategy.cs – Strategy implementation.
  • README.md – English documentation.
  • README_zh.md – Chinese documentation.
  • README_ru.md – Russian documentation.
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();
	}
}