GitHub で見る

ADX システム DI クロス戦略

概要

ADX システム戦略は、MetaTrader 4 エキスパート ADX_System.mq4 の StockSharp の変換です。元の EA は、 最近完了した 2 つのローソク足の +DI コンポーネントと -DI コンポーネントを含む平均方向性インデックス (ADX)。 +DIラインの場合 システムが長くする必要がある ADX 値を超える。 -DI ラインが ADX 値を超えると、短くする必要があります。の StockSharp ポートは、前の 2 つの終了したローソク足からのインジケーター値を保存することでこの動作を再現します。 MetaTrader コードで使用される iADX(..., shift=1/2) 呼び出しをミラーリングします。

いつでもオープンできるポジションは 1 つだけです。この戦略は、シングルチケットに一致するエントリーとエグジットの成行注文を送信します。 MetaTrader ネッティング アカウントのロジック。リスク管理はオリジナルのエキスパートアドバイザーを反映しています: 固定テイクプロフィットとストップロス レベルは平均エントリー価格に対するポイントで表され、オプションのトレーリングストップにより利益を確定させることができます。 ポジションが有利に動きます。

取引ロジック

  1. 設定されたタイムフレーム (CandleType) をサブスクライブし、バー内での決定を避けるために終了したローソク足のみを処理します。
  2. AverageDirectionalIndex インジケーターにローソク足データを供給し、インジケーターがその ADX、+DI、および -DI を提供するまで待ちます 価値観。
  3. 戦略が「現在」と 「以前」の値は MetaTrader 実装とまったく同じです。
  4. 長いエントリ: 古い ADX (shift = 2) が新しい ADX (shift = 1) よりも下にある場合、古い +DI はそれよりも下になります。 ADX で、より最近の +DI がより最近の ADX を上回っている場合は、成行買い注文を送信します。
  5. 簡単なエントリ: -DI コンポーネントに同じ条件が発生した場合 (古い -DI は古い ADX の下にあり、新しい -DI は新しい ADX の上にある)、 市場の売り注文。
  6. ロングイグジット: ADX が下落し始め、+DI がその下をクロスバックしたときにロングポジションを閉じます。 テイクプロフィットまたはストップロスがヒットしたとき、またはトレーリングストップを突破したとき。
  7. 短期離脱: -DI をリスク制御とともに使用して、長期離脱ロジックを反映します。
  8. 次のシグナルで最新の shift = 1/2 ペアが使用されるように、キャンドルごとにキャッシュされたインジケーター履歴を更新します。

リスク管理

  • TakeProfitPointsStopLossPoints は、MetaTrader スタイルのポイントで距離を表します。実際の価格単位に変換されます 利用可能な場合は Security.PriceStep を使用します。それ以外の場合、生の値は絶対価格デルタとして扱われます。
  • トレーリングストップ (TrailingStopPoints) は、位置が少なくとも設定された距離を超えた後にのみ有効になります。 エントリー価格。アクティブになると、利益の方向に移動し、価格がトレーリングレベルを横切ったときにポジションを閉じます。
  • すべてのエグジット(インジケーターの反転、テイクプロフィット、ストップロス、トレーリングストップ)は成行注文を使用するため、ポジションはフラットになります。 すぐに、ソース EA の OrderClose の動作を模倣します。

パラメーター

名前 種類 デフォルト 説明
CandleType DataType 1分の時間枠 戦略によって処理される主な時間枠。
AdxPeriod int 14 ADX と DI コンポーネントの計算に使用されるローソク足の数。
TradeVolume decimal 1 すべての成行注文に使用されるロットサイズ。
TakeProfitPoints decimal 100 エントリー価格に対するポイント単位の利食い距離。
StopLossPoints decimal 30 エントリー価格に対するポイント単位のストップロス距離。
TrailingStopPoints decimal 0 オプションのトレーリングストップ距離 (ポイント単位)。末尾を無効にするには、ゼロに設定します。

元の MetaTrader 専門家との違い

  • MetaTrader は個別のチケットを管理し、StockSharp は単一のネット ポジションを処理します。したがって、変換により、 信号が反転したときに新しいエントリー命令を発行する前に現在位置を確認します。
  • オリジナルの EA は、ポイントを価格距離に変換するために Point に依存していました。 StockSharp ポートは、次の場合に Security.PriceStep を使用します。 知られています。それ以外の場合、距離は未処理の価格単位として扱われるため、商品のデフォルトを調整する必要がある場合があります。 型破りな価格設定。
  • MetaTrader は、既存の順序を変更してトレーリング ストップを適用します。 StockSharp は、次の時点で成行注文でポジションを決済します。 トレーリング ストップに違反しています。これは機能的には同等ですが、ネッティング モデル内ではより単純です。

使い方のヒント

  • ストラテジーボリューム (TradeVolume) が商品のロットステップと一致していることを確認してください。コンストラクターはこの値を次にも割り当てます。 Strategy.Volume したがって、ヘルパー メソッドは予想される取引サイズを使用します。
  • より大きな平均範囲またはより小さな価格ステップで商品を取引する場合は、TakeProfitPointsStopLossPoints を増やします。
  • 戦略をチャートに追加して、ローソク足、ADX インジケーター、および実行された取引を視覚化します。これは、シグナルを確認するのに役立ちます。 +DI または -DI が ADX ラインを超えたときに発生します。

インジケーター

  • AverageDirectionalIndex (ADX を +DI および -DI コンポーネントとともに提供します)。
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// ADX System DI Cross: trend-following using dual EMA crossover
/// (proxy for +DI/-DI cross) with ATR-based volatility filter.
/// </summary>
public class AdxSystemDiCrossStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<int> _atrLength;
	private readonly StrategyParam<decimal> _atrThreshold;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;

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

		_fastLength = Param(nameof(FastLength), 10)
			.SetDisplay("Fast EMA", "Fast EMA period (proxy for +DI).", "Indicators");

		_slowLength = Param(nameof(SlowLength), 20)
			.SetDisplay("Slow EMA", "Slow EMA period (proxy for -DI).", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period for trend strength.", "Indicators");

		_atrThreshold = Param(nameof(AtrThreshold), 50m)
			.SetDisplay("ATR Threshold", "Min ATR value for entry.", "Indicators");
	}

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

	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	public decimal AtrThreshold
	{
		get => _atrThreshold.Value;
		set => _atrThreshold.Value = value;
	}

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

		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;
	}

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

		var fast = new ExponentialMovingAverage { Length = FastLength };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, atr, ProcessCandle)
			.Start();

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

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

		if (_prevFast == 0 || _prevSlow == 0)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		var bullishCross = _prevFast <= _prevSlow && fastVal > slowVal;
		var bearishCross = _prevFast >= _prevSlow && fastVal < slowVal;

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

		// Entry on cross + volatility filter
		if (Position == 0 && atrVal >= AtrThreshold)
		{
			if (bullishCross)
			{
				_entryPrice = candle.ClosePrice;
				BuyMarket();
			}
			else if (bearishCross)
			{
				_entryPrice = candle.ClosePrice;
				SellMarket();
			}
		}

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}