A L3H3 Pivot Strategy é uma versão StockSharp do MetaTrader especialista "L3_H3_Expert". O script original constrói uma estrutura dinâmica diária e implanta duas ordens pendentes para negociar possíveis rompimentos ou retrocessos em torno da máxima e da mínima da sessão anterior. A versão StockSharp mantém a mesma ideia: ela recalcula os níveis de pivô após cada vela de período superior concluída (diariamente por padrão) e decide entre entradas de stop ou limite com base em onde o mercado atualmente negocia em relação ao intervalo de ontem.
Lógica de negociação
Estatísticas da sessão
Após cada vela pivô concluída (padrão: diariamente), a estratégia captura os valores de abertura, máximo, mínimo e fechamento da sessão anterior.
O nível de pivô clássico é calculado como (High + Low + Close) / 3.
Esses níveis permanecem ativos durante toda a próxima sessão.
Configuração de entrada
O preço de entrada de compra está ancorado ligeiramente acima da mínima anterior. O deslocamento é igual ao parâmetro EntryOffsetPips expresso em múltiplos de tamanho pip.
Um preço de entrada de venda está ancorado na máxima anterior (espelhando o especialista original que usou a máxima bruta sem qualquer buffer adicional).
Para cada novo dia de negociação (detectado através da assinatura da vela principal), a estratégia coloca novas ordens pendentes:
Se o mercado for negociado abaixo da mínima de ontem, um stop de compra será colocado para capturar um rompimento de alta.
Se o mercado for negociado acima da máxima de ontem, um stop de venda será colocado para negociar uma reversão negativa.
Caso contrário, o algoritmo prefere ordens de limite nos mesmos níveis de preço para comprar quedas ou vender altas de volta ao intervalo.
As ordens de stop loss são posicionadas StopLossPips longe da referência mínima/máxima, exatamente como a versão MQL fixou um buffer de stop de 16 pontos.
O take-profit de ambas as ordens pendentes está alinhado com o nível pivô, replicando o posicionamento alvo encontrado no código-fonte.
Gerenciamento de pedidos
Cada vez que um novo pivô é calculado, quaisquer ordens pendentes em funcionamento são canceladas e recalculadas com os novos níveis.
A estratégia também cancela ordens pendentes desatualizadas quando uma nova sessão começa, evitando o acúmulo de ordens inativas.
Quando um pedido é atendido, sua referência interna é apagada automaticamente para evitar cancelamentos duplicados.
Parâmetros
Nome
Descrição
Padrão
EntryCandleType
Série de velas usada para monitorar a sessão atual e acionar a colocação de pedidos.
Período de 5 minutos
PivotCandleType
Vela de prazo mais alto usada para medir as estatísticas da sessão anterior.
Período diário
EntryOffsetPips
Distância (em pips) adicionada acima da mínima anterior para entradas longas.
2
StopLossPips
Distância (em pips) aplicada além da referência baixa/máxima para posicionar stop loss.
16
Diferenças do especialista MQL
O script MetaTrader selecionou diferentes sessões de negociação (Ásia, Londres, Nova York) por meio de números mágicos e janelas de tempo. A versão StockSharp consolida o comportamento usando uma vela configurável de prazo mais alto (diariamente por padrão) para derivar os níveis de pivô, o que torna a lógica mais fácil de auditar e adaptar entre corretores.
MetaTrader confiou no bid/ask atual para decidir entre ordens stop e limit. A implementação StockSharp usa a vela finalizada mais recente da série EntryCandleType para essa comparação para manter o fluxo de trabalho orientado a eventos.
Os comentários dos pedidos e os números mágicos eram específicos da plataforma no MT4. Eles são omitidos intencionalmente aqui; em vez disso, a estratégia mantém referências diretas às suas ordens pendentes.
Notas de uso
Certifique-se de que a segurança subjacente exponha um PriceStep válido. A estratégia lança uma exceção no início se a conexão do corretor não fornecer informações sobre o tamanho do pip.
Para replicar o comportamento original mais de perto, defina PivotCandleType para uma série de velas horárias agregadas na sessão desejada e ajuste os parâmetros de deslocamento/parada de acordo.
Como acontece com qualquer estratégia de ordem pendente, considere a distância mínima da corretora e as políticas de expiração de ordem pendente ao implantar ao vivo.
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>
/// L3/H3 Pivot strategy - trades around Highest/Lowest channel midpoint.
/// Buys when close crosses above the midpoint, sells when below.
/// Uses a longer lookback to simulate daily pivot levels.
/// </summary>
public class L3H3PivotStrategy : 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 L3H3PivotStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 48)
.SetDisplay("Channel Period", "Lookback for pivot channel", "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();
_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 high, decimal low)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var mid = (high + low) / 2m;
if (!_hasPrev)
{
_prevClose = close;
_prevMid = mid;
_hasPrev = true;
return;
}
// Cross above midpoint
if (_prevClose <= _prevMid && close > mid && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Cross below midpoint
else if (_prevClose >= _prevMid && close < mid && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevClose = close;
_prevMid = mid;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class l3_h3_pivot_strategy(Strategy):
"""L3/H3 Pivot strategy - trades around Highest/Lowest channel midpoint.
Buys when close crosses above the midpoint, sells when below.
Uses a longer lookback to simulate daily pivot levels."""
def __init__(self):
super(l3_h3_pivot_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 48) \
.SetDisplay("Channel Period", "Lookback for pivot channel", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def ChannelPeriod(self):
return self._channel_period.Value
def OnReseted(self):
super(l3_h3_pivot_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(l3_h3_pivot_strategy, self).OnStarted2(time)
self._has_prev = False
highest = Highest()
highest.Length = self.ChannelPeriod
lowest = Lowest()
lowest.Length = self.ChannelPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(highest, lowest, self._process_candle).Start()
def _process_candle(self, candle, high, low):
if candle.State != CandleStates.Finished:
return
high_val = float(high)
low_val = float(low)
close = float(candle.ClosePrice)
mid = (high_val + low_val) / 2.0
if not self._has_prev:
self._prev_close = close
self._prev_mid = mid
self._has_prev = True
return
# Cross above midpoint
if self._prev_close <= self._prev_mid and close > mid and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Cross below midpoint
elif self._prev_close >= self._prev_mid and close < mid and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_mid = mid
def CreateClone(self):
return l3_h3_pivot_strategy()