GitHub で見る

Auto ADX戦略

概要

Auto ADX戦略は、MetaTraderエキスパートアドバイザーAuto ADX.mq5をStockSharpの高レベルAPIに直接移植したものです。平均方向性指数(ADX)の強度と+DI・-DI成分の関係を評価してトレード方向を決定します。ストップロス、テイクプロフィット、反転シグナル、ピップベースのトレーリングストップなど、元のリスク管理機能をすべて再現しながら、ローソク足サブスクリプションやインジケーターバインディングといったStockSharpの概念を採用しています。

トレードロジック

  • ローソク足ソース — 設定可能なローソク足タイプ(デフォルト:1時間足)をサブスクライブし、バー内ノイズを避けるため確定済みローソク足のみを処理します。
  • ADX計算 — 単一のAverageDirectionalIndexインジケーターをBindExでバインドし、平滑化ADX値および+DI・-DI線にアクセスします。
  • 買いエントリー — 以下の条件がすべて揃ったときに発動:
    • +DIが-DIより大きい(正の方向性モメンタム)、
    • ADXが設定可能なADXレベルを上回っている、かつ
    • ADXが前のローソク足と比べて上昇している。
  • 売りエントリー — 以下の条件がすべて揃ったときに発動:
    • -DIが+DIより大きい(負の方向性モメンタム)、
    • ADXが設定レベルを下回っている、かつ
    • ADXが前のローソク足と比べて下落している。
  • 反転モードReverseSignalsが有効(デフォルト動作)の場合、以下のときにオープンポジションをクローズ:
    • 買いポジション:+DIが-DIを下回る、またはADXが下落する。
    • 売りポジション:+DIが-DIを上回る、またはADXが上昇する。
  • ポジションサイジング — 戦略のVolumeで注文を発行。反転処理はClosePosition()でエクスポージャー全体を解消してから新しいシグナルを検討します。

リスク管理

  • ストップロス / テイクプロフィット — ピップ入力を、銘柄のPriceStepを使って絶対的な価格距離に換算します。StockSharpのStartProtectionヘルパーが任意のマーケット執行で保護注文を配置します。
  • トレーリングストップ — 元のピップベーストレーリングロジックを再現:
    • 未実現利益がトレーリング距離を超えた後にのみトレーリングが有効化されます。
    • ストップレベルはピップサイズ(TrailingStepPips)単位で移動します。
    • 買いポジションはトレーリングストップを下回ったときに撤退し、売りポジションはトレーリングストップを上回ったときに撤退します。
  • ピップ換算 — MQL実装を模倣するため、銘柄が3桁または5桁小数点の価格を使用する場合、ピップサイズはPriceStep×10となります。これにより外国為替銘柄間で動作が一貫します。

パラメーター

名前 デフォルト 説明
StopLossPips 50 ピップ単位の保護ストップ距離。ゼロに設定するとストップロスを無効化します。
TakeProfitPips 50 ピップ単位の利食い目標距離。ゼロに設定するとテイクプロフィットを無効化します。
TrailingStopPips 5 ピップ単位のトレーリングストップサイズ。ゼロに設定するとトレーリングを無効化します。
TrailingStepPips 5 トレーリングストップを移動させる前の最小増分利益(ピップ)。トレーリングが有効な場合は正の値でなければなりません。
AdxPeriod 14 ADXインジケーターの平均期間。
AdxLevel 30 エントリーをフィルタリングするADX強度しきい値。
ReverseSignals true DI関係またはADX傾きが変化した際に既存ポジションをクローズします。
CandleType 1時間 分析・取引に使用するローソク足タイプ。

実装上の注意

  • BindExを使ってAverageDirectionalIndexValue全体にアクセスし、インジケーター値の手動取得に依存しないようにしています。
  • トレーリングロジックは最後のストップレベルを追跡し、価格がポジション有利方向に少なくともTrailingStepPips進んだときのみ移動させます。これによりMQLのトレーリングステップ動作を再現しています。
  • C#ソースコード内のすべてのインラインコメントはリポジトリガイドラインに従って英語で記述されています。
  • 戦略はAPI/2908_Auto_ADX/CS/AutoAdxStrategy.cs内で完結しており、要件に従ってPython版はありません。

使用上のヒント

  1. ピップ換算が正確であるよう、正しいPriceStepメタデータを持つ銘柄に戦略をアタッチしてください。
  2. 取引する銘柄のボラティリティプロファイルに合わせてAdxLevelを調整してください — しきい値を高くするとシグナル頻度が下がります。
  3. トレーリングを無効化している場合(TrailingStopPips = 0)、TrailingStepPipsは無視され、元のエキスパートアドバイザーの動作が再現されます。
  4. 複数の市場でバックテストを行い、ピップベースの保護距離を検証し、ADX傾きフィルタリングが期待通りに機能することを確認してください。
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>
/// Auto ADX strategy (simplified). Uses RSI for trend strength detection
/// combined with EMA for direction, mimicking ADX directional movement logic.
/// </summary>
public class AutoAdxStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<decimal> _rsiHigh;
	private readonly StrategyParam<decimal> _rsiLow;

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

	public int RsiLength
	{
		get => _rsiLength.Value;
		set => _rsiLength.Value = value;
	}

	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

	public decimal RsiHigh
	{
		get => _rsiHigh.Value;
		set => _rsiHigh.Value = value;
	}

	public decimal RsiLow
	{
		get => _rsiLow.Value;
		set => _rsiLow.Value = value;
	}

	public AutoAdxStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");

		_rsiLength = Param(nameof(RsiLength), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Length", "RSI period", "Indicators");

		_emaLength = Param(nameof(EmaLength), 20)
			.SetGreaterThanZero()
			.SetDisplay("EMA Length", "EMA period for direction", "Indicators");

		_rsiHigh = Param(nameof(RsiHigh), 60m)
			.SetDisplay("RSI High", "RSI threshold for bullish strength", "Logic");

		_rsiLow = Param(nameof(RsiLow), 40m)
			.SetDisplay("RSI Low", "RSI threshold for bearish weakness", "Logic");
	}

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

		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var ema = new ExponentialMovingAverage { Length = EmaLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, ema, (ICandleMessage candle, decimal rsiVal, decimal emaVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var close = candle.ClosePrice;

				// Strong trend up: RSI above threshold and price above EMA
				if (rsiVal > RsiHigh && close > emaVal && Position <= 0)
					BuyMarket();
				// Weak trend / bearish: RSI below threshold and price below EMA
				else if (rsiVal < RsiLow && close < emaVal && Position >= 0)
					SellMarket();
			})
			.Start();

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

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