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();
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class session_breakout_strategy(Strategy):
def __init__(self):
super(session_breakout_strategy, self).__init__()
self._range_start = self.Param("RangeStartHour", 0).SetDisplay("Range Start", "Hour to start tracking range", "Sessions")
self._range_end = self.Param("RangeEndHour", 8).SetDisplay("Range End", "Hour to stop tracking range", "Sessions")
self._trade_end = self.Param("TradeEndHour", 20).SetDisplay("Trade End", "Hour to stop trading", "Sessions")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))).SetDisplay("Candle Type", "Candle timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(session_breakout_strategy, self).OnReseted()
self._current_date = None
self._range_high = None
self._range_low = None
self._range_complete = False
self._traded_today = False
def OnStarted2(self, time):
super(session_breakout_strategy, self).OnStarted2(time)
self._current_date = None
self._range_high = None
self._range_low = None
self._range_complete = False
self._traded_today = False
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(self.OnProcess).Start()
def OnProcess(self, candle):
if candle.State != CandleStates.Finished:
return
candle_date = candle.OpenTime.Date
hour = candle.OpenTime.Hour
if self._current_date is None or candle_date != self._current_date:
self._current_date = candle_date
self._range_high = None
self._range_low = None
self._range_complete = False
self._traded_today = False
high = float(candle.HighPrice)
low = float(candle.LowPrice)
close = float(candle.ClosePrice)
if hour >= self._range_start.Value and hour < self._range_end.Value:
if self._range_high is None or high > self._range_high:
self._range_high = high
if self._range_low is None or low < self._range_low:
self._range_low = low
return
if not self._range_complete and hour >= self._range_end.Value and self._range_high is not None and self._range_low is not None:
self._range_complete = True
if not self._range_complete or self._range_high is None or self._range_low is None:
return
if hour >= self._range_end.Value and hour < self._trade_end.Value:
if self.Position <= 0 and close > self._range_high and not self._traded_today:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._traded_today = True
elif self.Position >= 0 and close < self._range_low and not self._traded_today:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._traded_today = True
if hour >= self._trade_end.Value and self.Position != 0:
if self.Position > 0:
self.SellMarket()
else:
self.BuyMarket()
def CreateClone(self):
return session_breakout_strategy()