GitHub で見る

GBP 午前 9 時の指値注文戦略

この戦略は、MQL/7687/Gbp9am.mq4 にある元の MetaTrader 4 エキスパートを StockSharp に変換したものです。これは、現在の価格付近で 2 つの未決注文を準備し、セッション中に最大 1 つのアクティブな取引を維持するロンドン午前 9 時のブレイクアウト ルーチンを再現します。

取引アイデア

  1. 設定された時間およびで、戦略は最新のローソク足の終値を価格スナップショットとして取得します。
  2. 買いストップはスナップショット価格の上に配置され、売りストップはスナップショット価格の下に配置されます。両方の注文は同じボリュームを共有し、共有のテイクプロフィットディスタンスとともに個別のストップロスレベルを運びます。
  3. 注文の 1 つが約定されると、もう 1 つは直ちにキャンセルされ、1 つのポジションのみがアクティブになります。
  4. オープンポジションは、完了したローソク足ごとにチェックされる合成ストップロスとテイクプロフィットのレベルで管理されます。
  5. 毎日のクローズアウト時間を有効にすると、ロンドンセッション後に残りのエクスポージャーを平坦化し、未決注文を削除できます。
  6. 両方の未決注文が取引なしで削除された場合、または市場時間が観測時間から離れた場合、戦略は MetaTrader バージョンとまったく同じように翌日に再準備されます。

ピップオフセットは、商品の価格ステップを使用して近似されます。ブローカーが小数ピップ (10 進数 3 桁または 5 桁) を提供する場合、ロジックは通常の 0.1 ピップ増分に自動的にスケールされます。

パラメータリファレンス

パラメータ 説明
Volume 両方の未決注文で共有される注文量 (ロット)。
LookHour ロンドン時間の午前 9 時を表す為替時間。
LookMinute スナップショットが取得されたときのルックアワー内の分。
CloseHour すべてのポジションと未決注文が強制的にクローズされる時間。
UseCloseHour 毎日の決済手順を有効または無効にします。
TakeProfitPips ピップ単位のターゲット距離。両方向に対称的に適用されます。
BuyDistancePips スナップショット価格と買いストップエントリーの間のオフセット(ピップ単位)。
SellDistancePips スナップショット価格と売りストップエントリーの間のオフセット(ピップ単位)。
BuyStopLossPips ロングトレードのピップス単位のストップロス距離。
SellStopLossPips ショートトレードのストップロス距離(pips)。
CandleType タイミングと停止の管理に使用されるキャンドル シリーズ (デフォルトは 1 分)。

行動メモ

  • この戦略では、同じバー内で複数のトリガーが発生するのを避けるために、未完成のローソク足を無視します。
  • 注文価格は、証券価格ステップを使用して最も近い有効なティックに四捨五入されます。
  • 再装備ゲートは、MQL エキスパートの clear_to_send フラグを反映しています。日次ストラドルが設定されると、市場がルックアワー外にある間に両方の未決注文が消えるか、時計が次のシグナルの前の時間に達するまで、新しい注文は送信されません。
  • UseCloseHour が有効な場合、この戦略は成行注文によるオープン取引を終了し、終了時間に達すると未決注文をクリアします。
  • ピップの計算は過去のローソク足に依存しているため、特にスプレッドが大きいシンボルでは、正確なストップ/ターゲット距離はティックベースの MetaTrader 環境とは若干異なる場合があります。

リスク管理

変換では、元の静的なストップとターゲットが維持されます。トレーリング ストップやスケーリング ロジックはありません。 OnStarted ではポジション保護が有効になっているため、予期せぬ切断によってアカウントが無防備になることはありません。

使用法

  1. データ フィードの交換タイムゾーンと一致するように、VolumeLookHour、および LookMinute の値を構成します。
  2. ブローカーのスプレッド構造を反映するように距離パラメータを調整します。
  3. この戦略を GBPUSD シンボル (または選択した別の FX ペア) に添付し、ロンドンセッションの前に開始します。
  4. 開始後に自動的に描画される StockSharp チャートで結果の取引を監視します。

この実装は、AGENTS.md のガイドラインに従っています。つまり、高レベルのキャンドル サブスクリプション API を使用し、UI メタデータを持つ戦略パラメータを採用し、低レベルの履歴ポーリングを回避します。

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>
/// GBP 9AM strategy - session high/low breakout.
/// Buys when close crosses above the Highest channel.
/// Sells when close crosses below the Lowest channel.
/// Uses midpoint crossing for exits.
/// </summary>
public class Gbp9AmStrategy : Strategy
{
	private readonly StrategyParam<int> _channelPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevMid;
	private bool _hasPrev;

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

	public Gbp9AmStrategy()
	{
		_channelPeriod = Param(nameof(ChannelPeriod), 12)
			.SetDisplay("Channel Period", "Highest/Lowest lookback", "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(); _prevClose = 0m; _prevMid = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var highest = new Highest { Length = ChannelPeriod };
		var lowest = new Lowest { Length = ChannelPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(highest, lowest, ProcessCandle)
			.Start();
	}

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

		var close = candle.ClosePrice;
		var mid = (highest + lowest) / 2;

		if (!_hasPrev)
		{
			_prevClose = close;
			_prevMid = mid;
			_hasPrev = true;
			return;
		}

		if (_prevClose <= _prevMid && close > mid && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (_prevClose >= _prevMid && close < mid && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevClose = close;
		_prevMid = mid;
	}
}