GitHub で見る

RSI トレーダー調整平均戦略

概要

この戦略は「RSI トレーダー」MetaTrader エキスパートアドバイザーを再現します。価格移動平均と平滑化された RSI 平均という 2 つのトレンド フィルターを調整して、支配的なトレンドの方向にエントリーし、フィルターが発散したときに終了します (横方向レジーム)。 StockSharp ポートはローソク足データをサポートするあらゆる金融商品で動作し、元の説明のようにデフォルトで時間足ローソク足になります。

仕組み

  1. RSI 期間 (デフォルトは 14) で指定された期間で RSI を計算します。
  2. 2 つの単純な移動平均を使用して RSI ストリームを平滑化します。1 つは短い移動平均 (Short RSI MA)、もう 1 つは長い移動平均 (Long RSI MA) です。
  3. 2 つの移動平均によるスムーズな終値: 短い単純な MA (ショート価格 MA) と長い線形加重 MA (ロング価格 MA)。
  4. 完成したキャンドルに対してのみシグナルを生成します。
    • ロング – 両方のショート平均 (価格と RSI) がロング平均を上回っています。
    • ショート – 両方のショート平均が、ロング平均を下回っています。
    • 横向き – 平均値は一致しません (1 つは上昇傾向を示し、もう 1 つは下降傾向を示します)。これが発生すると、オープンポジションはクローズされます。
  5. 注文は BuyMarket / SellMarket で発行されます。反対のポジションは、新しい方向に入る前にフラット化されます。

パラメーター

名前 説明 デフォルト 最適化可能
RSI Period RSI の計算長。 14 はい (7…28、ステップ 1)
Short Price MA 価格の短い単純移動平均の長さ。 9 はい (5…20、ステップ 1)
Long Price MA 価格の長期線形加重移動平均の長さ。 45 はい (30…90、ステップ 5)
Short RSI MA RSI に適用される短い平滑化平均の長さ。 9 はい (5…20、ステップ 1)
Long RSI MA RSI に適用される長い平滑化平均の長さ。 45 はい (30…90、ステップ 5)
Candle Type ローソク足に使用されるデータ型。デフォルトは 1 時間の時間枠です。 H1 いいえ

注意事項

  • 取引はすべての指標が形成された場合にのみ実行されます。
  • 元の EA では、ロットとスリッページ設定が使用されていました。 StockSharp は、注文サイズの戦略 Volume プロパティを使用し、約定スリッページの管理を取引アダプターに任せます。
  • 組み込みのストップロスやテイクプロフィットは定義されていません。出口は横方向の検出に依存します。追加のリスク管理を外部から追加できます。
  • グラフ作成サービスが利用可能な場合、グラフでは価格と RSI 移動平均の両方が描画されます。
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RSI Trader strategy combining price SMA crossover with RSI trend confirmation.
/// Buy when short SMA crosses above long SMA with RSI above 50.
/// Sell when short SMA crosses below long SMA with RSI below 50.
/// </summary>
public class RsiTraderAlignedAveragesStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _shortMaPeriod;
	private readonly StrategyParam<int> _longMaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevShort;
	private decimal _prevLong;
	private bool _hasPrev;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int ShortMaPeriod { get => _shortMaPeriod.Value; set => _shortMaPeriod.Value = value; }
	public int LongMaPeriod { get => _longMaPeriod.Value; set => _longMaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public RsiTraderAlignedAveragesStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI calculation period", "Indicators");

		_shortMaPeriod = Param(nameof(ShortMaPeriod), 9)
			.SetDisplay("Short MA", "Short moving average period", "Indicators");

		_longMaPeriod = Param(nameof(LongMaPeriod), 26)
			.SetDisplay("Long MA", "Long moving average period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevShort = 0m;
		_prevLong = 0m;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_hasPrev = false;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var shortMa = new SimpleMovingAverage { Length = ShortMaPeriod };
		var longMa = new SimpleMovingAverage { Length = LongMaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, shortMa, longMa, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevShort = shortMa;
			_prevLong = longMa;
			_hasPrev = true;
			return;
		}

		var bullCross = _prevShort <= _prevLong && shortMa > longMa;
		var bearCross = _prevShort >= _prevLong && shortMa < longMa;

		if (Position <= 0 && bullCross && rsiValue > 50)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (Position >= 0 && bearCross && rsiValue < 50)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevShort = shortMa;
		_prevLong = longMa;
	}
}