Ver no GitHub

Estratégia de intervalo de sessão

Visão geral

A estratégia Session Breakout replica o consultor especialista MetaTrader "Session Breakout". Ele assiste a sessão matinal européia e mede sua faixa de preço. Quando esse intervalo é suficientemente apertado, a estratégia prepara-se para romper as negociações durante os EUA. sessão da tarde usando StockSharp de alto nível API. A implementação impõe no máximo uma entrada longa e uma curta por dia por O nd anexa automaticamente ordens de proteção (stop loss e takeprofit) a cada posição.

Lógica de negociação

  • Redefina o estado no início de cada dia de negociação e pule os fins de semana. As segundas-feiras são opcionais e controladas por um parâmetro.
  • Acompanhe as velas finalizadas durante a sessão europeia (padrão 06h00-12h00) e registre a máxima mais alta e a mínima mais baixa.
  • No início da sessão dos EUA, o intervalo capturado é classificado como "pequeno" quando sua largura é menor que SmallSessionThreshol dPips.
  • Se o intervalo for pequeno, monitore as velas da sessão dos EUA (padrão 12h00-16h00) e espere até que pelo menos uma barra dos EUA feche (Eu cordaSessionStartHour + 5 to EuropeSessionStartHour + 10).
  • Um rompimento longo é acionado quando toda a vela permanece acima da máxima europeia, além de um buffer configurável (BreakoutBuffer Pips). Um pequeno rompimento exige que a vela fique abaixo da mínima europeia menos o buffer.
  • Depois de entrar em uma posição, a estratégia atribui níveis de stop-loss e take-profit expressos em pips e evita ganhos adicionais. tenta na mesma direção pelo resto do dia.

Parâmetros

Parâmetro Descrição
Volume Volume de pedidos usado para breakouts longos e curtos.
EuropeSessionStartHour Hora em que começa o rastreamento de alcance europeu.
EuropeSessionEndHour Hora em que o rastreamento de alcance europeu para.
UsSessionStartHour Hora que marca o início da janela da sessão dos EUA.
UsSessionEndHour Hora que marca o fim da janela da sessão dos EUA.
SmallSessionThresholdPips Largura máxima (em pips) para a faixa europeia ser qualificada como squeeze.
BreakoutBufferPips Buffer extra adicionado acima/abaixo do intervalo antes de acionar rompimentos.
TradeOnMonday Permite negociação às segundas-feiras. Fins de semana são sempre ignorados.
TakeProfitPips Distância entre o preço de entrada e o nível de lucro.
StopLossPips Distância entre o preço de entrada e o nível de stop loss.
CandleType Série de velas usada para todos os cálculos (velas de 15 minutos por padrão).

Notas

  • O tamanho do pip é derivado do instrumento PriceStep. Ajuste os parâmetros baseados em pip para corresponder à especificação do contrato s do título selecionado.
  • Como os pedidos são gerados quando uma vela qualificada fecha, os preenchimentos acontecem ao preço de fechamento dessa vela nos backtests. Liv Os preenchimentos podem variar dependendo das condições do mercado.
  • Apenas uma negociação longa e uma curta podem ser abertas por dia. A lógica reflete o comportamento original do consultor especialista ao usar S Ajudantes de gerenciamento de risco baseado em posição do 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();
		}
	}
}