GitHub で見る

セッションブレイクアウト戦略

概要

セッション ブレークアウト戦略は、MetaTrader エキスパート アドバイザー「セッション ブレークアウト」を複製します。ヨーロッパの朝セッシを眺める をオンにしてその価格帯を測定します。そのレンジが十分に狭い場合、戦略は米国中にブレイクアウトをトレードする準備をします。 StockSharp のハイレベルな API を使用した午後のセッション。この実装では、1 日に最大 1 つのロングエントリーと 1 つのショートエントリーが強制されます。 すべてのポジションに保護注文 (ストップロスとテイクプロフィット) が自動的に付けられます。

取引ロジック

  • 各取引日の開始時に状態をリセットし、週末をスキップします。月曜日はオプションであり、パラメータによって制御されます。
  • ヨーロッパセッション(デフォルト06:00~12:00)中に終了したローソク足を追跡し、最高値と最低値を記録します。
  • 米国セッションの開始時に、キャプチャされた範囲の幅が「SmallSessionThreshol」より小さい場合、その範囲は「小さい」として分類されます。 dピップス`。
  • 範囲が狭い場合は、米国セッションのローソク足 (デフォルトは 12:00 ~ 16:00) を監視し、少なくとも 1 本の米国バーが閉じるまで待ちます (Eu) ropeSessionStartHour + 5 to EuropeSessionStartHour + 10)。
  • ロングブレイクアウトは、ローソク足全体がヨーロッパの高値と設定可能なバッファー (BreakoutBuffer) を上回ったときにトリガーされます。 ピップス)。短いブレイクアウトには、ローソク足がヨーロッパの安値からバッファーを引いた値を下回ることが必要です。
  • ポジションを入力した後、この戦略はピップで表されるストップロスとテイクプロフィットのレベルを設定し、追加の利益を防ぎます。 残りの日は同じ方向に努力します。

パラメーター

パラメータ 説明
Volume ロングブレイクアウトとショートブレイクアウトの両方に使用される注文量。
EuropeSessionStartHour ヨーロッパの範囲追跡が開始される時間。
EuropeSessionEndHour ヨーロッパの範囲追跡が停止する時間。
UsSessionStartHour 米国のセッションウィンドウの開始を示す時間。
UsSessionEndHour 米国のセッションウィンドウの終了を示す時間。
SmallSessionThresholdPips ヨーロッパ範囲のスクイーズとして認定される最大幅 (ピップ単位)。
BreakoutBufferPips ブレイクアウトをトリガーする前に、範囲の上/下に追加のバッファーが追加されます。
TradeOnMonday 月曜日の取引が可能になります。週末はいつもスキップされます。
TakeProfitPips エントリー価格とテイクプロフィットレベルの間の距離。
StopLossPips エントリー価格とストップロスレベルの間の距離。
CandleType すべての計算に使用されるローソク足シリーズ (デフォルトでは 15 分のローソク足)。

注意事項

  • pip サイズは商品 PriceStep から導出されます。コントラクト仕様に一致するように pip ベースのパラメータを調整します 選択した証券の 。
  • 注文は適格なローソク足が閉じるときに生成されるため、バックテストではそのローソク足の終値で約定が発生します。リヴ 約定率は市場状況に応じて異なる場合があります。
  • 1 日にオープンできるロング取引とショート取引は 1 つだけです。このロジックは、S を使用する際の元の Expert Advisor の動作を反映しています。 tockSharp のポジションベースのリスク管理ヘルパー。
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>
/// Session breakout strategy that tracks a range during first hours and trades breakouts later.
/// Accumulates high/low during range hours (0-8), then trades breakouts during active hours (8-20).
/// </summary>
public class SessionBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _rangeStartHour;
	private readonly StrategyParam<int> _rangeEndHour;
	private readonly StrategyParam<int> _tradeEndHour;
	private readonly StrategyParam<DataType> _candleType;

	private DateTime _currentDate;
	private decimal? _rangeHigh;
	private decimal? _rangeLow;
	private bool _rangeComplete;
	private bool _tradedToday;

	public int RangeStartHour { get => _rangeStartHour.Value; set => _rangeStartHour.Value = value; }
	public int RangeEndHour { get => _rangeEndHour.Value; set => _rangeEndHour.Value = value; }
	public int TradeEndHour { get => _tradeEndHour.Value; set => _tradeEndHour.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public SessionBreakoutStrategy()
	{
		_rangeStartHour = Param(nameof(RangeStartHour), 0)
			.SetDisplay("Range Start", "Hour to start tracking range", "Sessions");

		_rangeEndHour = Param(nameof(RangeEndHour), 8)
			.SetDisplay("Range End", "Hour to stop tracking range", "Sessions");

		_tradeEndHour = Param(nameof(TradeEndHour), 20)
			.SetDisplay("Trade End", "Hour to stop trading", "Sessions");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).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();

		_currentDate = default;
		_rangeHigh = null;
		_rangeLow = null;
		_rangeComplete = false;
		_tradedToday = false;
	}

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

		_currentDate = default;
		_rangeHigh = null;
		_rangeLow = null;
		_rangeComplete = false;
		_tradedToday = false;

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

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

		var candleDate = candle.OpenTime.Date;
		var hour = candle.OpenTime.Hour;

		// Reset on new day
		if (candleDate != _currentDate)
		{
			_currentDate = candleDate;
			_rangeHigh = null;
			_rangeLow = null;
			_rangeComplete = false;
			_tradedToday = false;
		}

		// Build range during accumulation hours
		if (hour >= RangeStartHour && hour < RangeEndHour)
		{
			if (_rangeHigh == null || candle.HighPrice > _rangeHigh)
				_rangeHigh = candle.HighPrice;
			if (_rangeLow == null || candle.LowPrice < _rangeLow)
				_rangeLow = candle.LowPrice;
			return;
		}

		// Mark range as complete
		if (!_rangeComplete && hour >= RangeEndHour && _rangeHigh != null && _rangeLow != null)
			_rangeComplete = true;

		if (!_rangeComplete || _rangeHigh == null || _rangeLow == null)
			return;

		// Trade during active hours
		if (hour >= RangeEndHour && hour < TradeEndHour)
		{
			// Breakout above range high - buy
			if (Position <= 0 && candle.ClosePrice > _rangeHigh.Value && !_tradedToday)
			{
				if (Position < 0)
					BuyMarket();
				BuyMarket();
				_tradedToday = true;
			}
			// Breakout below range low - sell
			else if (Position >= 0 && candle.ClosePrice < _rangeLow.Value && !_tradedToday)
			{
				if (Position > 0)
					SellMarket();
				SellMarket();
				_tradedToday = true;
			}
		}

		// Close at end of day
		if (hour >= TradeEndHour && Position != 0)
		{
			if (Position > 0)
				SellMarket();
			else
				BuyMarket();
		}
	}
}