GitHub で見る

プラン X ブレイクアウト戦略

プラン X ブレイクアウト戦略は、ピーター イングラムによる MetaTrader エキスパート アドバイザー「プラン X」を再現しています。ロンドンの午前中のセッションに焦点を当て、価格が基準ローソクから離れるのを待ってからエントリーします。一度にオープンできるネット ポジションは 1 つだけであり、リスクは有利に推移する取引の背後にあるピップベースのストップを通じて制御されます。

取引ロジック

  1. セッションアンカー

    • この戦略は 15 分足のローソク足を監視します。
    • 設定されたセッション開始時間 (デフォルトは 11:00) に、そのローソク足の終値を記録します。この終値は残りのセッションのアンカー価格として機能します。
    • 取引は、少なくとも 1 つの追加のローソク足が閉じた後、セッション終了時間 (デフォルトは 15:00) 前にのみ考慮されます。
  2. エントリー条件

    • ロング: 最後に終了したローソク足がアンカーの終値を LongTargetPips (デフォルト 25 ピップス) 以上上で閉じ、ポジションが開いていない場合。
    • ショート: 最後に終了したローソク足がアンカーのクローズよりも ShortTargetPips (デフォルト 20 ピップス) 以上下でクローズし、オープンなポジションがない場合。
    • すべての比較は、商品のティック サイズから派生したピップ単位で行われます。
  3. ポジション管理

    • InitialStopPips (デフォルトは 25 ピップス) に等しい固定の初期ストップロスは、エントリー価格に対して設定されます。
    • トレードが少なくとも TrailTriggerPips (デフォルトは 10 ピップス) を獲得すると、ストップはトレーリング ストップに変換されます。
    • 価格がさらに TrailTriggerPips 進むたびに、ストップは収益性の高い方向に TrailStepPips (デフォルトは 5 ピップス) だけ移動します。
    • 価格がストップに達すると、ポジションは市場でクローズされます。
  4. ボリューム

    • 注文には TradeVolume パラメータが使用されます (デフォルトは 0.1 ロット)。保障契約の規模に合わせて調整してください。

パラメーター

名前 説明 デフォルト
TradeVolume エントリーとエグジットに使用される成行注文の量。 0.1
LongTargetPips ロングエントリーに必要なアンカー上のブレイクアウト距離。 25
ShortTargetPips ショートエントリーに必要なアンカー下のブレイクアウト距離。 20
InitialStopPips エントリー価格から保護ストップロスまでの距離。 25
TrailTriggerPips トレーリングストップが有効化または前進する前に必要な利益 (pips)。 10
TrailStepPips トレーリングストップが移動するたびに適用されるピップ増分。 5
SessionStartHour アンカーローソクの開始時間を示す 10 進数の時間 (例: 11.011.5)。 11.0
SessionEndHour 10 進数の時間。それ以降は新しいエントリは取得されません。 SessionStartHour 以降である必要があります。 15.0
CandleType 評価に使用したキャンドルシリーズ。デフォルトは 15 分足のローソク足です。 15分

注意事項

  • ピップサイズは、商品の PriceStep と小数精度に基づいて自動的に調整されます (小数点以下 3 桁または 5 桁には 10 倍の乗数が適用されます)。
  • この戦略では、継続的な日中市場が予想されます。日次ギャップのある商品では、再アンカー動作が取引日ごとに発生します。
  • StockSharp 戦略はネット ポジションを使用するため、変換では一度に 1 つのオープン方向のみが想定されます。これは、ヘッジがアクティブでない場合の元のエキスパートのデフォルトの動作を反映しています。

ファイル

  • CS/PlanXBreakoutStrategy.cs – StockSharp のプラン X ブレークアウト ロジックの C# 実装。
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>
/// Plan X Breakout strategy using highest high / lowest low channel breakout.
/// Buy when price breaks above the highest high of the lookback period.
/// Sell when price breaks below the lowest low of the lookback period.
/// </summary>
public class PlanXBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _lookback;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevHigh;
	private decimal _prevLow;
	private bool _hasPrev;

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

	public PlanXBreakoutStrategy()
	{
		_lookback = Param(nameof(Lookback), 20)
			.SetDisplay("Lookback", "Channel lookback period", "Indicators");

		_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();

		_prevHigh = 0m;
		_prevLow = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var highestHigh = new Highest { Length = Lookback };
		var lowestLow = new Lowest { Length = Lookback };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(highestHigh, lowestLow, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevHigh = highest;
			_prevLow = lowest;
			_hasPrev = true;
			return;
		}

		// Breakout above previous highest high
		if (Position <= 0 && candle.ClosePrice > _prevHigh)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Breakout below previous lowest low
		else if (Position >= 0 && candle.ClosePrice < _prevLow)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevHigh = highest;
		_prevLow = lowest;
	}
}