GitHub で見る

サイダス EMA RSI 戦略

この戦略は、MetaTrader 4 Expert Advisor Exp_Sidus.mq4 の StockSharp 移植です。元のロジックを再現します。 高速/低速の EMA クロスオーバーと 50 レベルの RSI フィルターを組み合わせます。シグナルは完了したローソク足でのみ評価され、各ローソク足は ソース ロボットのタイミング規則に合わせて、最大 1 つのオーダーを生成します。

取引ロジック

  • インジケータースタック
    • 高速指数移動平均 (デフォルト期間 5)
    • 遅い指数移動平均 (デフォルトの期間 12)
    • 相対強度指数 (デフォルト期間 21)
  • 強気のセットアップ
    1. 前のシグナルローソクの速い EMA は遅い EMA 以下でした。
    2. 現在のシグナルローソク足では、速い EMA が遅い EMA を上回っています。
    3. 同じローソク足の RSI は厳密に 50 を超えています。
  • 弱気のセットアップ
    1. 前のシグナルローソクの速い EMA は遅い EMA 以上でした。
    2. 現在のシグナルローソク足では、速い EMA が遅い EMA を下回っています。
    3. 同じローソクの RSI は厳密に 50 より小さいです。
  • シグナル シフトSignalShift パラメーター (デフォルトは 1) は、どの閉じたローソク足を「現在の」シグナル バーとみなすかを定義します。 値 1 は最後に閉じたローソク足を使用し、0 は直前に閉じたローソク足を使用し、2 は 2 バー分遡ります。などです。前回の クロスオーバー検出のローソク足は、SignalShift + 1 として自動的に計算されます。
  • 重複保護 — この戦略はシグナルローソクの開始時間を保存し、シグナルローソクに関連付けられた別のポジションをオープンすることはありません。 同じバーで、オリジナルの EA の LastTime チェックを忠実に模倣しています。

ポジション管理

  • 常に 1 つのポジションのみが存在します。
  • ポジションがオープンしている間に反対のシグナルが現れると、ストラテジーはまず既存のポジションをクローズし、その後、ポジションがオープンするのを待ちます。 次の処理パスは、MQL バージョンとまったく同じように、新しい方向で取引を開始します。
  • StartProtection は、価格ポイント (価格ステップ) で表されるオプションのテイクプロフィットおよびストップロスブラケットを付加します。距離は 元の EA の入力から導出されます: デフォルトのテイクプロフィット 80 ポイントとストップロス 20 ポイント。

パラメーター

名前 説明 デフォルト 注意事項
TakeProfitPoints 価格ステップでの利食い距離。 80 ターゲットを無効にするには、0 を設定します。
StopLossPoints 価格ステップのストップロス距離。 20 保護を無効にするには、0 を設定します。
TradeVolume 注文量 (ロット/契約)。 0.1 開始時にベースの Volume プロパティに割り当てられます。
FastPeriod 高速な EMA の長さ。 5 最適化可能。
SlowPeriod EMA の長さが遅いです。 12 最適化可能。
RsiPeriod RSI の長さ。 21 最適化可能。
SignalShift 信号の計算に使用される閉じたキャンドルの数。 1 MT4 EA の shif 入力をミラーリングします。
CandleType サブスクリプション用のキャンドルソース。 1h 時間枠 環境でサポートされている任意の DataType に設定できます。

実装メモ

  • ローソク足データは SubscribeCandles(CandleType) 経由でサブスクライブされ、ローソク足が到達した後にのみ ProcessCandle 内で処理されます。 Finished 状態。
  • インジケーターの値は短いキューにキャッシュされるため、ストラテジーは、によって指定された現在および前のバーにアクセスできます。 GetValue のようなインジケーター メソッドを呼び出さずに、リポジトリ ガイドラインに準拠した SignalShift を実行します。
  • 戦略がフラットになると、取引実行は BuyMarket/SellMarket を使用します。逆方向のポジションが存在する場合、 ClosePosition が最初に発行され、注文フローは元のロボットと同じになります。
  • 明確な監査証跡を維持するために、すべての実行時ログは英語で書き込まれます。

変換メモ

  • テイクプロフィットとストップロスの距離は商品 PriceStep を乗算し、MetaTrader Point の動作を再現します。
  • 音量のデフォルトは 0.1 で、これは MQL ソースの Lots 入力と同じです。
  • RSI のしきい値は、元の実装を反映するために 50 にハードコーディングされています。
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Sidus EMA + RSI strategy: fast EMA crosses slow EMA confirmed by RSI above/below 50.
/// </summary>
public class SidusEmaRsiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rsiPeriod;

	private decimal _prevFast;
	private decimal _prevSlow;

	public SidusEmaRsiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_fastPeriod = Param(nameof(FastPeriod), 5)
			.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 12)
			.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 21)
			.SetDisplay("RSI Period", "RSI period.", "Indicators");
	}

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

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

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

		_prevFast = 0;
		_prevSlow = 0;
	}

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

		var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

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

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

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

		if (_prevFast == 0 || _prevSlow == 0)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		var bullishCross = _prevFast <= _prevSlow && fastValue > slowValue;
		var bearishCross = _prevFast >= _prevSlow && fastValue < slowValue;

		// Exit existing positions on opposite cross
		if (Position > 0 && bearishCross)
		{
			SellMarket();
		}
		else if (Position < 0 && bullishCross)
		{
			BuyMarket();
		}

		// Entry on crossover confirmed by RSI
		if (Position == 0)
		{
			if (bullishCross && rsiValue > 50)
			{
				BuyMarket();
			}
			else if (bearishCross && rsiValue < 50)
			{
				SellMarket();
			}
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}
}