GitHub で見る

Exp RJTX 一致 平滑化 Duplex

概要

このストラテジーは MetaTrader 5 エキスパートアドバイザー Exp_RJTX_Matches_Smoothed_Duplex.mq5 の動作を再現します。2つの独立した RJTX シグナルブロックがそれぞれの時間軸で平滑化された始値と終値を分析します。各ブロックは、平滑化された終値が Period バー前の平滑化された始値を上回るかどうかに応じて、完了したローソク足を強気または弱気に分類します。強気の「一致」はロングモジュールへのエントリーをトリガーし、弱気の一致はショートモジュールを管理します。

シグナル生成

  1. 平滑化 – 両ブロックはローソク足の始値と終値を選択した平滑化アルゴリズムに入力します。始値と終値のストリームには同じメソッドが適用されますが、内部バッファを独立させるために別々のインスタンスが使用されます。
  2. 比較 – 十分な履歴が利用可能になると、現在の平滑化された終値が Period バー前に記録された平滑化された始値と比較されます。
  3. 一致検出 – 終値が大きい場合、ローソク足は強気の一致を受け取ります。そうでない場合は弱気になります。シグナルは MT5 のバッファアクセスと同様に、SignalBar 本の完了ローソク足をシフトした後に評価されます。

ポジション管理

  • ロングブロック は強気の一致が評価ウィンドウに達したとき(許可されている場合は既存のショートをカバーしながら)ロングポジションを開きます。弱気の一致はロングエグジットが有効な場合にロングポジションをクローズします。
  • ショートブロック はこのロジックをミラーします: 弱気の一致はショートトレードを開き(許可されている場合はロングエクスポージャーをクローズ)、強気の一致はショートをカバーします。
  • StockSharp のストラテジーはネット計算されます。したがって、反対のモジュールは MT5 バージョンのように2つの独立したヘッジドポジションを維持するのではなく、新しいポジションを開く前に現在のポジションをクローズします。自動カバーを禁止するには、対応する Allow ... Close パラメーターを無効にしてください。

リスク管理

ストップと利益目標は価格ステップで表されます(PriceStep × points)。完了した各ローソク足について、ストラテジーはバーレンジがアクティブなストップロスまたはテイクプロフィットレベルに触れるかどうかを確認し、対応するポジションを即座にクローズします。これはブローカー管理の注文に依存することなく MT5 の保護注文の動作をエミュレートします。

パラメーター

セクション パラメーター デフォルト 説明
Long LongCandleType H4 ロング RJTX ブロックで使用される時間軸。
Long LongVolume 0.1 ロングシグナル実行時に開かれるボリューム。
Long LongAllowOpen true ロングポジションの開設を有効にします。
Long LongAllowClose true 弱気の一致時にロングポジションのクローズを有効にします。
Long LongStopLossPoints 1000 ロングトレードのストップロス距離(価格ステップ、0は確認を無効にします)。
Long LongTakeProfitPoints 2000 ロングトレードのテイクプロフィット距離(価格ステップ、0は確認を無効にします)。
Long LongSignalBar 1 RJTX バッファを読み取る際に適用されるシフト(0 = 現在の完了ローソク足)。
Long LongPeriod 10 現在の平滑化された終値と過去の平滑化された始値の間のバー数。
Long LongMethod Sma ロングブロックに使用される平滑化アルゴリズム(Sma, Ema, Smma, Lwma, Jjma, Jurx, Parma, T3, Vidya, Ama)。
Long LongLength 12 始値/終値シリーズに適用される平滑化フィルターの長さ。
Long LongPhase 15 Jurik スタイルフィルターのフェーズパラメーター(互換性のために保持)。
Short ShortCandleType H4 ショート RJTX ブロックで使用される時間軸。
Short ShortVolume 0.1 ショートシグナル実行時に開かれるボリューム。
Short ShortAllowOpen true ショートポジションの開設を有効にします。
Short ShortAllowClose true 強気の一致時にショートポジションのクローズを有効にします。
Short ShortStopLossPoints 1000 ショートトレードのストップロス距離(価格ステップ、0は確認を無効にします)。
Short ShortTakeProfitPoints 2000 ショートトレードのテイクプロフィット距離(価格ステップ、0は確認を無効にします)。
Short ShortSignalBar 1 ショートブロックの RJTX バッファを読み取る際に適用されるシフト。
Short ShortPeriod 10 現在の平滑化された終値と過去の平滑化された始値の間のバー数。
Short ShortMethod Sma ショートブロックに使用される平滑化アルゴリズム。
Short ShortLength 12 ショートシグナルに適用される平滑化フィルターの長さ。
Short ShortPhase 15 ショートブロックの Jurik スタイルフィルターのフェーズパラメーター。

注意事項

  • Jjma は Jurik Moving Average に対応します。StockSharp が SmoothAlgorithms ライブラリから同一のフィルターを公開していないため、JurxParmaVidya はそれぞれ Zero-Lag EMA、Arnaud Legoux MA、EMA で近似されます。
  • ストップロス/テイクプロフィットのロジックはローソク足の極値で評価されます。ローソク足の高値/安値より短いイントラバーのスパイクはエグジットをトリガーしません。
  • シグナルは完了したローソク足のみで処理されます。イントラバーの一致は MT5 の IsNewBar 動作に沿って無視されます。
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>
/// Exp RJTX Matches Smoothed Duplex strategy using SmoothedMA crossover.
/// Buys when fast SmoothedMA crosses above slow SmoothedMA.
/// Sells on reverse crossover.
/// </summary>
public class ExpRjtxMatchesSmoothedDuplexStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private SmoothedMovingAverage _fast;
	private SmoothedMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	/// <summary>
	/// Fast smoothed MA period.
	/// </summary>
	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	/// <summary>
	/// Slow smoothed MA period.
	/// </summary>
	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	/// <summary>
	/// Stop-loss distance in price steps.
	/// </summary>
	public int StopLossPoints
	{
		get => _stopLossPoints.Value;
		set => _stopLossPoints.Value = value;
	}

	/// <summary>
	/// Take-profit distance in price steps.
	/// </summary>
	public int TakeProfitPoints
	{
		get => _takeProfitPoints.Value;
		set => _takeProfitPoints.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of the <see cref="ExpRjtxMatchesSmoothedDuplexStrategy"/> class.
	/// </summary>
	public ExpRjtxMatchesSmoothedDuplexStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast smoothed MA period", "Indicator");

		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow smoothed MA period", "Indicator");

		_stopLossPoints = Param(nameof(StopLossPoints), 200)
			.SetNotNegative()
			.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");

		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400)
			.SetNotNegative()
			.SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

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

		_fast = null;
		_slow = null;
		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;
		_cooldown = 0;
	}

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

		_fast = new SmoothedMovingAverage { Length = FastPeriod };
		_slow = new SmoothedMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

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

		if (!_fast.IsFormed || !_slow.IsFormed)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		if (_cooldown > 0)
		{
			_cooldown--;
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		// Check SL/TP
		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step)
			{
				SellMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}

			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step)
			{
				SellMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step)
			{
				BuyMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}

			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step)
			{
				BuyMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}
		}

		// SmoothedMA crossover
		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();

			BuyMarket();
			_entryPrice = close;
			_cooldown = 80;
		}
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{
			if (Position > 0)
				SellMarket();

			SellMarket();
			_entryPrice = close;
			_cooldown = 80;
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}
}