GitHub で見る

ああ、HM RSI 戦略

概要

この戦略は、MetaTrader エキスパート Expert_AH_HM_RSI の StockSharp 移植です。ハンマーまたはハンギングマンのローソク足パターンを探し、取引前に相対強度指数 (RSI) からの確認シグナルを必要とします。このアプローチは、新しいシグナルが現れたときにポジションを反転するというリスク管理哲学を含む、オリジナルの Expert Advisor を反映しています。

取引ロジック

  1. トレンド フィルター – 短い単純移動平均 (デフォルトの長さ 2) を使用して、市場が微下降トレンドにあるか上昇トレンドにあるかを判断します。
  2. ローソク足パターン – この戦略は、最後に完了したローソク足を分析します。
    • ハンマーは、実体がレンジの上位 3 分の 1 に位置し、ローソク足のギャップが前のバーよりも低く、ローソク足の中点が移動平均トレンドを下回っているときに検出されます。
    • ぶら下がっている男は、本体が上位 3 分の 1 に位置し、ローソク足のギャップが前のバーより高く、ローソク足の中点が移動平均トレンドより上にある場合に検出されます。
  3. RSI フィルター
    • ロングトレードでは、RSI が設定可能なハンマーしきい値 (デフォルトは 40) を下回る必要があります。
    • ショートトレードでは、RSI がハンギングマンのしきい値 (デフォルト 60) を超える必要があります。
  4. 取引執行 – 有効なシグナルでは、ストラテジーは Volume + |Position| でエントリーするため、オープンポジションは反対のセットアップが到着するとすぐに反転されます。
  5. Exit ルール – RSI が設定可能な下限 (デフォルト 30) または上限 (デフォルト 70) の境界を逆方向に横切ると、ポジションは平坦化され、元のコードの EXIT 投票が複製されます。

インジケーター

  • 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 hour キャンドル

すべてのパラメータは、StockSharp パラメータ UI を介して最適化できます。

使用上の注意

  • このロジックは完成したキャンドルに対してのみ機能します。選択した時間枠とデータ フィードで完全なバーが生成されていることを確認します。
  • 反転ロジックは常に Volume + |Position| をトレードするため、ポジションは反対のシグナルで瞬時に方向を反転し、エキスパートアドバイザーと一致します。
  • 組み込みのリスク管理を起動時に一度開始します (StartProtection()OnStarted で呼び出されます)。

ファイル

  • CS/AhHmRsiStrategy.cs – 戦略の実装。
  • README.md – 英語のドキュメント。
  • README_zh.md – 中国語のドキュメント。
  • README_ru.md – ロシア語のドキュメント。
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();
	}
}