GitHub で見る

ダブルMAブレイクアウト戦略

概要

ダブル MA ブレイクアウト戦略 は、MetaTrader エキスパート アドバイザー DoubleMA_Breakout の StockSharp 移植です。この戦略は、完成したローソク足の高速移動平均と低速移動平均を監視します。高速平均が低速平均を上回った場合、最後の終値を超えた設定可能なブレイクアウト距離で買いストップ注文が発注されます。ファースト平均がスロー平均を下回ると、売りストップが市場の下に対称的に配置されます。クロスオーバーが反転するか取引ウィンドウが閉じると、未決注文はキャンセルされ、オープンポジションはフラットになります。

この変換により、コアのブレイクアウト ロジックが維持され、高レベルの注文管理が追加され、StrategyParam<T> パラメータを通じて広範な構成が公開されます。コード内のすべてのコメントは、要求に応じて英語で書き直されました。

パラメーター

パラメータ デフォルト 説明
FastMaPeriod 2 高速移動平均の期間。
SlowMaPeriod 5 ゆっくりとした移動平均の期間。
FastMaMode Simple 高速回線の移動平均タイプ (SMA、EMA、SMMA、LWMA、LSMA)。
SlowMaMode Simple 遅いラインの移動平均線タイプ。
FastAppliedPrice Close 高速平均に適用される価格 (終値、始値、高値、安値、中央値、標準値、加重値)。
SlowAppliedPrice Close 遅い平均に適用される価格。
SignalShift 1 クロスオーバーを評価するときに振り返る完了したキャンドルの数。 0 は現在のローソク足を意味します。
BreakoutDistancePoints 45 最新の終値から離れて逆指値注文を行うために使用される価格ステップのブレイクアウト距離。
UseTimeWindow true 開始時間/終了時間フィルターを有効にします。
StartHour 11 新しい取引が許可される最初の 1 時間 (両端を含む)。
StopHour 16 取引が許可されている最後の 1 時間 (含む)。
UseFridayCloseAll true 金曜日の終了時間に達したらポジションを閉じ、未決注文をすべてキャンセルします。
FridayCloseTime 21:30 ストラテジーがハードフラットを実行する金曜日の時間帯。
UseFridayStopTrading false 既存のポジションを維持したまま、構成された金曜日の停止時刻の後に新しいエントリを無効にします。
FridayStopTradingTime 19:00 新しいエントリがブロックされる金曜日の時間帯 (有効な場合)。
CandleType 1時間 インジケーターとシグナルの両方に使用されるローソク足のデータ型。

取引ロジック

  1. CandleType で定義された完成したローソク足をサブスクライブし、選択したモードと適用された価格に従って 2 つの移動平均を計算します。
  2. 「GetValue なし」ガイドラインに違反することなく、戦略が SignalShift によって選択されたローソク足を参照できるように、インジケーター値の短いローリング履歴を維持します。
  3. 強気のセットアップ: シグナルローソク足の速い MA が遅い MA を上回っている場合、売りストップをキャンセルし、ショートポジションを閉じ、注文やポジションが残っていない場合は最後の終値より上に買いストップ注文 BreakoutDistancePoints × PriceStep を出します。
  4. 弱気のセットアップ: シグナルキャンドルの速い MA が遅い MA を下回っている場合、買いストップをキャンセルし、ロングポジションを閉じ、市場より同じ距離下に売りストップ注文を出します。
  5. 時間管理: 取引ウィンドウが無効または閉じられている場合、すべての保留中の注文はキャンセルされます。金曜日には、週末の前にオプションのストップ取引時間とハードフラット時間が尊重されます。
  6. 逆指値注文が実行されると、複数の同時取引を避けるために反対の未決注文がキャンセルされます。

MetaTrader EA との違い

  • 元のスクリプトの資金管理スイッチとカスタム トレーリング ストップ スキームは移植されません。 StockSharp の Volume プロパティは取引サイズを定義し、標準の保護モジュールを通じてリスク管理を追加できます。
  • エラーの再試行と低レベルの順序ループは、高レベルの StockSharp ヘルパー (BuyStopSellStopClosePositionCancelOrder) に置き換えられます。
  • マージンカットオフやスリッページ修正などのブローカー固有の概念は省略されています。これらは必要に応じて個別に実装できます。
  • LSMA モードは、StockSharp の LinearRegression インジケーターを使用して、MetaTrader で使用される最小二乗移動平均を近似します。

使用上の注意

  • 戦略を開始する前に Volume を構成します。デフォルトでは、StockSharp は単一のロット/契約を使用します。
  • 必要に応じて、戦略を StartProtection (コード内ですでに呼び出されている) と組み合わせて、プラットフォーム レベルのストップロス モジュールまたはテイクプロフィット モジュールをアタッチします。
  • 最適化ワークフローの場合は、コンストラクターで提供される .SetCanOptimize 設定を介して必要なパラメーターを有効にします。
  • 機器に有効な PriceStep があることを確認してください。それ以外の場合、ブレイクアウト距離はゼロ オフセットを避けるために 1 に戻ります。
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>
/// Double MA breakout strategy.
/// Buys on fast/slow EMA bullish crossover.
/// Sells on bearish crossover.
/// </summary>
public class DoubleMaBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public DoubleMaBreakoutStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 25)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

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

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fast > slow;
		var crossDown = _prevFast >= _prevSlow && fast < slow;

		if (crossUp && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}