GitHub で見る

RSI Sign戦略

この戦略は、MQL5のオリジナルiRSISignエキスパートアドバイザーをStockSharpのハイレベルAPIに変換します。Relative Strength Index (RSI)とAverage True Range (ATR)を組み合わせてエントリーとエグジットのシグナルを生成します。

システムはユーザー定義の時間軸の完成したローソク足を待機します。RSIが下部閾値を上抜けすると、潜在的な強気の反転を示しロングポジションを開くかショートをクローズします。逆に、RSIが上部閾値を下抜けするとショートポジションを建てるかアクティブなロングをクローズします。ATRは計算されますが追加コンテキストとしてのみ使用され、ATRでオフセットされたシグナル矢印を表示したオリジナルインジケーターを反映しています。

詳細

  • エントリー条件:
    • ロング: 前回のRSI値がDownLevelを下回り、現在のRSIがそれを上抜け。
    • ショート: 前回のRSI値がUpLevelを上回り、現在のRSIがそれを下抜け。
  • ロング/ショート: 両方向が許可されており、独立して有効化できます。
  • エグジット条件:
    • 対応するクローズフラグが有効な場合、逆シグナルが現在のポジションをクローズ。
  • ストップ: 実装されていない。必要に応じて外部でリスク管理を追加可能。
  • デフォルト値:
    • RsiPeriod = 14
    • AtrPeriod = 14
    • UpLevel = 70
    • DownLevel = 30
    • CandleType = 1時間足
  • フィルター:
    • カテゴリ: モメンタム
    • 方向: 両方
    • インジケーター: RSI, ATR
    • ストップ: いいえ
    • 複雑さ: 基本
    • 時間軸: 柔軟
    • 季節性: いいえ
    • ニューラルネットワーク: いいえ
    • ダイバージェンス: いいえ
    • リスクレベル: 中

パラメーター

名前 説明
RsiPeriod RSIの長さ。
AtrPeriod ATRの長さ。
UpLevel 売りシグナルを生成するRSI上部閾値。
DownLevel 買いシグナルを生成するRSI下部閾値。
CandleType 計算に使用するローソク足の時間軸。
BuyOpen ロングポジションの開始を有効化。
SellOpen ショートポジションの開始を有効化。
BuyClose 逆シグナルで既存ロングのクローズを許可。
SellClose 逆シグナルで既存ショートのクローズを許可。

この戦略は、シンプルなMQL5ロジックをStockSharpのハイレベル戦略フレームワークに変換する方法を示す教育的なサンプルとして意図されています。

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 based signal strategy.
/// Opens long when RSI crosses above the down level.
/// Opens short when RSI crosses below the up level.
/// </summary>
public class RsiSignStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _upLevel;
	private readonly StrategyParam<decimal> _downLevel;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _previousRsi;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal UpLevel { get => _upLevel.Value; set => _upLevel.Value = value; }
	public decimal DownLevel { get => _downLevel.Value; set => _downLevel.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public RsiSignStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "Length of RSI indicator", "Indicator");

		_upLevel = Param(nameof(UpLevel), 70m)
			.SetDisplay("RSI Upper Level", "Sell when RSI falls below this value", "Indicator");

		_downLevel = Param(nameof(DownLevel), 30m)
			.SetDisplay("RSI Lower Level", "Buy when RSI rises above this value", "Indicator");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe used for indicator calculations", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_previousRsi = null;
	}

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

		_previousRsi = null;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

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

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, rsi);
			DrawOwnTrades(area);
		}
	}

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var prevRsi = _previousRsi;
		_previousRsi = rsiValue;

		if (prevRsi is null)
			return;

		// RSI crosses above lower level -> buy signal
		if (prevRsi <= DownLevel && rsiValue > DownLevel && Position <= 0)
			BuyMarket();
		// RSI crosses below upper level -> sell signal
		else if (prevRsi >= UpLevel && rsiValue < UpLevel && Position >= 0)
			SellMarket();
	}
}