GitHub で見る

Exp RSIOMA V2 戦略

概要

Exp RSIOMA V2は、RSIOMAオシレーター(移動平均の相対力指数)でトレードするオリジナルのMetaTrader 5エキスパートアドバイザーのコンバージョンです。戦略はStockSharpの高レベルAPI内で同じアイデアを再現します:価格データが平滑化され、モメンタムシリーズに変換され、RSIスタイルのアキュムレーターに供給されます。オシレーターが方向を変えたり、事前に定義されたゾーンをクロスしたりするときにトレード決定が下されます。

トレードロジック

  1. 価格前処理 – 選択されたローソク足価格(デフォルトでクローズ)が4つの移動平均ファミリーの1つ(単純、指数、平滑化、または線形加重)で平滑化されます。
  2. モメンタム計算 – 平滑化された価格は MomentumPeriod バー前の値と比較されてモメンタムインパルスを得ます。
  3. RSIOMA計算 – 正と負のモメンタムコンポーネントが長さ RsiomaLength の指数平滑化で累積され、[0; 100] 範囲のRSIOMA値を生成します。
  4. シグナル評価 – 最新のクローズしたローソク足が選択された Mode に従って検査されます:
    • Breakdown – RSIOMAがメイントレンドレベル(MainTrendLong / MainTrendShort)を離れるときに反応します。オシレーターが上部ゾーンを出ると、ショートがクローズされロングエントリーが許可されます;下部ゾーンを出ると逆の動作が実行されます。
    • Twist – ターニングポイントを探します。RSIOMAの傾きが下降から上昇に切り替わると買いが発生し、上昇から下降への移行に売りが反応します。
    • CloudTwist – MT5インジケーターの色付きクラウドロジックをエミュレートします。RSIOMAが売られすぎ/買われすぎの極端な状態からチャンネル内に戻るときにトレードがオープンされ、同時に反対のポジションがクローズされます。

シグナルは SignalBar で指定されたバーで評価されます(デフォルト:前の完全にクローズしたローソク足)、確認されたデータのみが使用されることを保証します。

パラメーター

名前 説明 デフォルト値
OrderVolume 市場注文で使用されるデフォルト注文ボリューム。 1
CandleType 戦略によって処理されるローソク足データシリーズ。 4時間時間軸
EnableLongEntries / EnableShortEntries 新規ロング/ショートポジションのオープンを許可。 true
EnableLongExits / EnableShortExits 既存のロング/ショートポジションのクローズを許可。 true
Mode トレードロジック(Breakdown、Twist、またはCloudTwist)。 Breakdown
PriceSmoothing RSIOMA前に価格に適用される移動平均。 Exponential
RsiomaLength RSIOMA平均化期間。 14
MomentumPeriod モメンタム計算時のサンプル間の遅延。 1
AppliedPrice オシレーターに使用されるローソク足価格(クローズ、オープン、中央値、DeMark等)。 Close
MainTrendLong / MainTrendShort 買われすぎ/売られすぎゾーンを定義するRSIOMAレベル。 60 / 40
SignalBar 分析すべきクローズしたバーの数。 1

実装上の注意

  • StockSharpで利用可能な平滑化ファミリーのみがサポートされています(単純、指数、平滑化、線形加重)。MT5バージョンの高度なモード(JJMA、VIDYA、AMA、…)は含まれていません。
  • RSI平均はMetaTraderの初期化を反映するために最初の RsiomaLength モメンタム値を使用してシードされます。その後オリジナルのエキスパートアドバイザーの動作に合わせて指数更新が適用されます。
  • ポジションは反対のエントリーが発行される前に常にクローズされます。エントリー許可(EnableLongEntriesEnableShortEntries)と決済許可(EnableLongExitsEnableShortExits)が許可された方向の完全な制御を提供します。
  • SignalBar = 0 は現在の完成したローソク足に反応するために使用できます;より高い値は行動する前に複数のバーを待つMT5の機能を再現します。

使用方法

  1. 戦略をStockSharpプロジェクトに追加し、取引したい楽器を割り当てます。
  2. CandleType を通じてローソク足サブスクリプションを設定し(デフォルトは4時間ローソク足)、シンボルが異なるボラティリティ特性を使用している場合は閾値を調整します。
  3. ブレイクアウトスタイルのエントリー(Breakdown)、モメンタムの転換(Twist)、またはクラウドカラーの変化(CloudTwist)のいずれが必要かに応じて好みのシグナルモードを選択します。
  4. 戦略を開始します。実行中に戦略は選択されたローソク足シリーズをサブスクライブし、RIOMAチェーンを計算し、条件が満たされると市場注文を発行します。
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>
/// RSIOMA strategy using RSI with overbought/oversold levels.
/// Buys when RSI crosses above oversold, sells when crosses below overbought.
/// </summary>
public class ExpRsiomaV2Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _overbought;
	private readonly StrategyParam<decimal> _oversold;

	private decimal? _prevRsi;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public decimal Overbought
	{
		get => _overbought.Value;
		set => _overbought.Value = value;
	}

	public decimal Oversold
	{
		get => _oversold.Value;
		set => _oversold.Value = value;
	}

	public ExpRsiomaV2Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

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

		_overbought = Param(nameof(Overbought), 65m)
			.SetDisplay("Overbought", "Overbought RSI level", "Levels");

		_oversold = Param(nameof(Oversold), 35m)
			.SetDisplay("Oversold", "Oversold RSI level", "Levels");
	}

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

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

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

		_prevRsi = 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);
			DrawOwnTrades(area);
		}

		var indArea = CreateChartArea();
		if (indArea != null)
		{
			DrawIndicator(indArea, rsi);
		}
	}

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

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevRsi = rsiValue;
			return;
		}

		if (_prevRsi == null)
		{
			_prevRsi = rsiValue;
			return;
		}

		// RSI crosses above oversold → buy signal
		if (_prevRsi.Value <= Oversold && rsiValue > Oversold && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// RSI crosses below overbought → sell signal
		else if (_prevRsi.Value >= Overbought && rsiValue < Overbought && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevRsi = rsiValue;
	}
}