GitHub で見る

Macd Stochastic トレーリング戦略

MACD Stochastic トレーリング戦略

概要

  • MetaTrader 4 エキスパート アドバイザー MQL/7637/3_lccfpgubwykd__www_forex-instruments_info.mq4 から変換されました。
  • 3 つのタイムフレーム ワークフローを使用します。1 時間足のローソク足は両方の MACD フィルターを駆動し、15 分足のローソク足は Stochastic オシレーターを供給し、1 分足ローソク足は価格ブレイクアウトを確認し、後続の出口を管理します。
  • 手動データポーリングを行わずに、SubscribeCandles(...).Bind(...) / BindEx(...) を使用して高レベルの StockSharp 戦略を実装します。
  • ポジションは成行注文でオープンされ、完全に戦略内で管理されます (外部のテスト ハーネスの変更は必要ありません)。

インジケーターとパラメーター

名前 種類 デフォルト 説明
LongStopLoss decimal 17 ロングトレードの最初のストップ距離。商品ポイントで表されます。
ShortStopLoss decimal 40 ショートトレードの最初のストップ距離 (ポイント)。
LongTrailingStop decimal 88 ロングポジションのトレーリング距離。
ShortTrailingStop decimal 76 ショートポジションのトレーリング距離。
OrderVolume decimal 0.1 MQL 入力からミラーリングされた基本取引量 (ロット)。
MacdCandleType DataType H1 強気および弱気の MACD フィルター (22/27/9 および 19/77/9) の時間枠。
StochasticCandleType DataType M15 両方の Stochastic オシレーター (5/3/119/3/19) に使用されるタイムフレーム。
EntryCandleType DataType M1 ブレイクアウトの確認とトレーリングロジックを提供するタイムフレーム。

すべてのポイントベースの設定は商品 PriceStep を通じて絶対価格に変換され、MetaTrader Point 乗数を忠実に再現します。

取引ルール

ロングエントリー

  1. 1 時間ごとの MACD(22,27,9) メインラインは、ゼロ未満のままで前の値を上回ります。
  2. M15 Stochastic(%K=5,%D=3,slowing=11) は 26 を下回っており、前の値と比較して上昇しています。
  3. 現在の M1 終値は前の M1 高値を突き抜けます。
  4. すべての条件が一致し、オープンなポジションがない場合、この戦略は OrderVolume に加えて、既存のショートを反転するのに必要な数量を購入します。

ショートエントリー

  1. 1 時間ごとの MACD(19,77,9) メインラインは以前の値を下回り、以前の値はゼロを上回っています。
  2. M15 Stochastic(%K=9,%D=3,slowing=19) は 70 を超えています。
  3. 現在の M1 終値は前の M1 安値を下回ります。
  4. ショートは、元の EA と同じポジションフリップ ロジックでオープンされます。

イグジットとトレーリング

  • 最初の停止は、MQL StopLoss の距離をポイント単位で反映します。
  • トレーリングストップは、価格がポジションに有利に指定されたトレーリング距離を超えて動くとアクティブになり、完成した M1 キャンドルごとに再計算されます。
  • 価格がアクティブなストップレベル(初期またはトレーリング)に触れた場合、ポジションは成行注文でクローズされます。

実装メモ

  • ローソク足のサブスクリプションはタイムフレームごとに分割されるため、インジケーターの更新は独立したままとなり、EA のマルチタイムフレームの動作と正確に一致します。
  • MQL Bid/Ask の末尾比較は、完成した M1 ローソク足の高値/安値で近似されます。これは、ローソク足ベースの高レベル API 内で最も近い表現です。
  • コードはリポジトリのガイドラインに従っています: タブのインデント、名前空間 StockSharp.Samples.Strategies、英語のコメント、および Param(...) を介したコンストラクター内のパラメーター宣言。
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>
/// MACD + Stochastic trailing strategy.
/// Enters long when MACD histogram is positive and Stochastic K crosses above D from oversold.
/// Enters short when MACD histogram is negative and Stochastic K crosses below D from overbought.
/// </summary>
public class MacdStochasticTrailingStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevK;
	private decimal? _prevD;

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

	public MacdStochasticTrailingStrategy()
	{
		_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();
		_prevK = null;
		_prevD = null;
	}

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

		_prevK = null;
		_prevD = null;

		var macd = new MovingAverageConvergenceDivergenceSignal();
		var stoch = new StochasticOscillator();

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(macd, stoch, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue, IIndicatorValue stochValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!macdValue.IsFinal || !stochValue.IsFinal)
			return;

		var macdVal = (MovingAverageConvergenceDivergenceSignalValue)macdValue;
		var stochVal = (StochasticOscillatorValue)stochValue;

		if (macdVal.Macd is not decimal macd || macdVal.Signal is not decimal signal)
			return;
		if (stochVal.K is not decimal k || stochVal.D is not decimal d)
			return;

		if (_prevK is not decimal prevK || _prevD is not decimal prevD)
		{
			_prevK = k;
			_prevD = d;
			return;
		}

		var histogram = macd - signal;
		var kCrossUp = prevK <= prevD && k > d;
		var kCrossDown = prevK >= prevD && k < d;

		// Buy: MACD histogram positive + stochastic K crosses above D
		if (histogram > 0 && kCrossUp && k < 50 && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Sell: MACD histogram negative + stochastic K crosses below D
		else if (histogram < 0 && kCrossDown && k > 50 && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevK = k;
		_prevD = d;
	}
}