GitHub で見る

RPM5 ブルズベアーズアイズ戦略

概要

RPM5 BullsBearsEyes 戦略 は、MetaTrader 4 エキスパート Rpm5_mt4v1 の C# ポートです。アドバイザーは、ブルズパワーとベアズパワーの測定値からカスタムのブルズベアーズアイズオシレーターを再構築し、一般的なバイアスに従う単一のポジションをオープンしました。この StockSharp バージョンは、元のリスク パラメーター、トレーリング ロジック、信号しきい値を維持しながら、高レベルの API を使用して同じ動作を再現します。

指標の再構築

  • 2 つの古典的なオシレーター – 強気パワー弱気パワー – は、設定されたローソク足シリーズに基づいて計算されます。
  • それらの合計は、MT4 インジケーターで使用される同一の 4 段階 IIR スムーザーを通過します。平滑化係数 (Gamma) は、オシレーターの反応速度を制御します。
  • フィルター処理された出力は、0 から 1 までの値に変換されます。中央のしきい値を超える値は強気の支配を示し、それを下回る値は弱気のコントロールを示します。どちらかの側が完全に使い果たされた場合、正確な 0 または 1 が表示され、元のインジケーターのエッジ ケースと一致します。

取引ルール

  1. この戦略は、選択した時間枠 (デフォルトでは 5 分) をサブスクライブし、完了したローソク足のみを待ちます。
  2. フラットの場合、BullsBearsEyes 比率を評価します。
    • 長いエントリ – 現在の値は厳密に Threshold (デフォルトは 0.5) を上回ります。
    • 簡単なエントリ – 現在の値は厳密に Threshold を下回ります。
    • アルゴリズムは最大でも 1 つのオープンポジションを保持します。反対のシグナルは、リスク管理によってアクティブなポジションが完全にクローズされるまで無視されます。
  3. 取引が開始されると、ポジションはストップロス、テイクプロフィット、またはトレーリングストップイベントが発生するまで変更されません。

リスク管理

  • ストップロス / テイクプロフィット 距離は、元の 25 / 150 ピップ設定から再作成されます。新しいポジションがオープンされるたびに、商品 PriceStep (pip) を使用して再計算されます。
  • ATR トレーリング: 終了したローソク足ごとに、平均トゥルー レンジ (期間 AtrPeriod、デフォルトは 5) が評価されます。トレーリング距離は 1 ピップに AtrMultiplier × ATR を加えたものに等しくなります。クローズがその距離を超えて進むと、ギャップを維持するために保護停止が強化されます。これは、OrderModify を繰り返し呼び出す MQL ロジックと同じです。
  • 新しい信号を処理する前に保護レベルがチェックされ、ソース EA と同様に、出口が常に新しいエントリよりも優先されることが保証されます。

パラメーター

名前 デフォルト 説明
Bulls/Bears Period 13 ブルズパワーインジケーターとベアーズパワーインジケーターの平均期間。
Gamma 0.5 BullsBearsEyes オシレーターの 4 段階 IIR スムージング比。
Threshold 0.5 強気 (> しきい値) ゾーンと弱気 (< しきい値) ゾーンの境界線。
ATR Period 5 ATR ベースのトレーリング ストップに使用されるルックバック。
ATR Multiplier 1.5 後続距離を求めるときに ATR に適用される乗数。
Stop Loss (pips) 25 プロテクティブストップ距離。ピップから価格に変換されます。
Take Profit (pips) 150 利益目標距離。ピップから価格に変換されます。
Trade Volume 1 新しいポジションごとに使用される成行注文の量。
Candle Type 5分キャンドル 戦略によって処理されるタイムフレーム。

注意事項

  • このポートは、MT4 に存在していた視覚的なデイリー チャネル オブジェクトを描画しません。これは、それらが表面的なものであるためです。
  • コード内のすべてのコメントは、要求に応じて英語で書かれています。
  • テストは変更されません。検証が必要かどうか、既存のソリューション レベル チェックを実行します。
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>
/// RPM5 Bulls Bears Eyes strategy using Bull/Bear power with EMA filter.
/// Buy when bull power is positive and bear power crosses above threshold.
/// Sell when bear power is negative and bull power crosses below threshold.
/// </summary>
public class Rpm5BullsBearsEyesStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _powerPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevBull;
	private decimal _prevBear;
	private bool _hasPrev;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int PowerPeriod { get => _powerPeriod.Value; set => _powerPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public Rpm5BullsBearsEyesStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 13)
			.SetDisplay("EMA Period", "EMA trend period", "Indicators");

		_powerPeriod = Param(nameof(PowerPeriod), 13)
			.SetDisplay("Power Period", "Bulls/Bears power 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();

		_prevBull = 0m;
		_prevBear = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var bulls = new BullPower { Length = PowerPeriod };
		var bears = new BearPower { Length = PowerPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, bulls, bears, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevBull = bullValue;
			_prevBear = bearValue;
			_hasPrev = true;
			return;
		}

		// Long: price above EMA, bull power positive, bear power crossing from negative to less negative
		var longSignal = candle.ClosePrice > emaValue && bullValue > 0 && _prevBear < 0 && bearValue > _prevBear;
		// Short: price below EMA, bear power negative, bull power crossing from positive to less positive
		var shortSignal = candle.ClosePrice < emaValue && bearValue < 0 && _prevBull > 0 && bullValue < _prevBull;

		if (Position <= 0 && longSignal)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (Position >= 0 && shortSignal)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevBull = bullValue;
		_prevBear = bearValue;
	}
}