GitHub で見る

ADX MACD Deev戦略

概要

ADX MACD Deev戦略は、同名のMetaTraderエキスパートアドバイザーのStockSharpポートです。平均方向性指数(ADX)からのトレンド強度シグナルと、Moving Average Convergence Divergence(MACD)からのモメンタム確認を組み合わせています。この戦略は両方のインジケーターが市場の方向に一致している場合にのみ取引し、オプションでトレーリングストップと部分的なポジション出口を通じて利益を確保できます。

機能の説明

  1. インジケーターの準備
    • ADXは設定可能な平均化期間で計算されます。戦略は最新のADX値を追跡し、取引を許可する前に一貫して一方向に移動することを要求します。
    • MACDは設定可能な速い、遅い、シグナルの指数移動平均を使用します。ヒストグラムとシグナルラインは、ロングでは持続的な成長、ショートでは持続的な下落を共同で示す必要があります。
  2. エントリーロジック
    • ロングエントリー: MACDヒストグラムが MACD Minimum (pips) 閾値を超え、MACDヒストグラムとシグナルラインの両方が選択されたバー数にわたって増加し、ADXが必要な強度を上回りながら上昇している場合にトリガーされます。
    • ショートエントリー: MACDヒストグラムが負の閾値を下回り、MACDヒストグラムとシグナルラインの両方が選択された間隔にわたって下降し、ADXが最小値を上回りながら減少している場合にトリガーされます。
    • 一度に開けるポジションは1つだけです。
  3. リスク管理
    • 初期のストップロスとテイクプロフィットレベルは、楽器 PriceStep と選択したpip距離から導出された価格単位で設定されます。
    • トレーリングストップは、価格が Trailing Stop + Trailing Step pip前進した後、利益のあるポジションを追跡できます。
    • Take Half Profit が有効な場合、戦略はテイクプロフィットレベルで現在のポジションの半分を閉じ、残りをトレーリングストップで実行させます。

パラメーター

グループ 名前 説明
トレーディング Order Volume 各新規成行注文のボリューム。
リスク Stop Loss (pips) エントリーからの初期ストップロスオフセット。
リスク Take Profit (pips) エントリーからの初期テイクプロフィットオフセット。
リスク Trailing Stop (pips) トレーリングストップ距離。トレーリングを無効化するにはゼロに設定。
リスク Trailing Step (pips) トレーリングストップが再び動く前の追加価格移動。
リスク Take Half Profit テイクプロフィットレベルに達したときの部分出口を有効化。
インジケーター ADX Period ADX平均化期間。
インジケーター ADX Bars Interval 一方向にトレンドしなければならない最近のADXバーの数。
インジケーター ADX Minimum エントリーに必要な最小ADX値。
インジケーター MACD Fast EMA MACDが使用する速いEMAの長さ。
インジケーター MACD Slow EMA MACDが使用する遅いEMAの長さ。
インジケーター MACD Signal EMA MACDが使用するシグナルEMAの長さ。
インジケーター MACD Bars Interval 同じ方向に揃わなければならないMACDバーの数。
インジケーター MACD Minimum (pips) pipに変換されたMACDの最小マグニチュード。
一般 Candle Type 計算に使用するロウソク足タイプまたは時間軸。

使用上の注意

  • 戦略は有効な PriceStep を持つ楽器を必要とします。PriceStep がゼロの場合、pipベースの閾値は生のMACD値にフォールバックします。
  • 部分出口のボリューム丸めは楽器の VolumeStep に従います。
  • トレーリングストップの調整は閉じたロウソク足でのみ評価されます。
  • 戦略は高レベルAPIバインディング(SubscribeCandles().BindEx(...))を使用し、手動のインジケーター値ポーリングに依存しません。
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;

public class AdxMacdDeevStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

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

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public AdxMacdDeevStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA 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");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { 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;

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

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

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}