GitHub で見る

MTF RSI SAR戦略

この戦略は4つの時間軸での**相対力指数(RSI)**の数値、Parabolic SARボリンジャーバンドを組み合わせて、短い押し目後のトレンド継続を捉えます。シグナルは5分足ローソク足で生成され、上位時間軸が確認フィルターとして機能します。

コンセプト

  1. RSIフィルター – ロングエントリーには5、15、30、60分のRSI値がすべて50を上回り、ショートエントリーにはすべて50を下回る必要があります。このマルチタイムフレーム確認は、取引を広いトレンドに合わせることを目的としています。
  2. Parabolic SARフィルター – 5、15、30分チャートのParabolic SAR値がロングには現在のローソク足の下に、ショートには上にある必要があります。これにより価格が希望する方向にトレンドしていることが確認されます。
  3. ボリンジャーバンドトリガー – 5分チャートでローソク足の終値がロングには上限バンドを、ショートには下限バンドを突破する必要があります。ボリンジャーバンドは買われすぎ/売られすぎのトリガーを提供します。
  4. エントリーとエグジット – すべてのアクティブフィルターが上を向いているときにロングポジションを建てます。すべてのアクティブフィルターが下を向いているときにショートポジションを建てます。反対のシグナルがオープンポジションをクローズします。

3つのフィルターはいずれもパラメーターで個別に無効にでき、RSIのみ、ボリンジャーバンドのみ、SARのみ、またはこれらの組み合わせで戦略を動作させることができます。

パラメーター

  • UseRsi – RSIフィルターを有効にする(デフォルト: true)。
  • UseBollinger – ボリンジャーバンドトリガーを有効にする(デフォルト: true)。
  • UseSar – Parabolic SARフィルターを有効にする(デフォルト: true)。
  • RsiPeriod – RSI計算期間(デフォルト: 14)。
  • BollingerPeriod – ボリンジャーバンドのバー数(デフォルト: 20)。
  • BollingerWidth – ボリンジャーバンドの幅(標準偏差の乗数)(デフォルト: 2)。
  • SarStep – Parabolic SARの加速因子(デフォルト: 0.02)。
  • SarMax – Parabolic SARの最大加速因子(デフォルト: 0.2)。
  • CandleType – ベースローソク足の時間軸、デフォルトは5分。

取引ルール

  • ロング: 有効なすべてのフィルターが強気シグナルを提供。
  • ショート: 有効なすべてのフィルターが弱気シグナルを提供。
  • エグジット: 反対のシグナルがポジションをクローズ。

注意事項

  • 戦略は1つの銘柄に対して4つのローソク足サブスクリプション(5、15、30、60分の時間軸)で動作します。
  • StockSharpの高レベルAPIを使用したマルチタイムフレーム確認の教育的サンプルとして設計されています。
  • 固定のストップロスや利益目標はありません。必要な場合はリスク管理を外部で追加する必要があります。
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RSI and Parabolic SAR strategy.
/// Buys when RSI below oversold and SAR below price; sells on opposite.
/// </summary>
public class MtfRsiSarStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiOversold;
	private readonly StrategyParam<decimal> _rsiOverbought;
	private readonly StrategyParam<DataType> _candleType;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal RsiOversold { get => _rsiOversold.Value; set => _rsiOversold.Value = value; }
	public decimal RsiOverbought { get => _rsiOverbought.Value; set => _rsiOverbought.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

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

		_rsiOversold = Param(nameof(RsiOversold), 35m)
			.SetDisplay("RSI Oversold", "RSI oversold level", "Indicators");

		_rsiOverbought = Param(nameof(RsiOverbought), 65m)
			.SetDisplay("RSI Overbought", "RSI overbought level", "Indicators");

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

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var sar = new ParabolicSar();

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

	private void ProcessCandle(ICandleMessage candle, decimal rsi, decimal sar)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var close = candle.ClosePrice;

		// Buy: RSI oversold + SAR below price
		if (rsi < RsiOversold && sar < close)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// Sell: RSI overbought + SAR above price
		else if (rsi > RsiOverbought && sar > close)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}
		// Exit long when RSI overbought
		else if (Position > 0 && rsi > RsiOverbought)
		{
			SellMarket();
		}
		// Exit short when RSI oversold
		else if (Position < 0 && rsi < RsiOversold)
		{
			BuyMarket();
		}
	}
}