Pipso é um sistema de breakout de sessão noturna convertido do MetaTrader consultor especialista Pipso.mq4. A estratégia mede o
preços mais altos e mais baixos das velas previamente concluídas e reage quando o mercado sai dessa faixa. Cada
o rompimento inverte a posição: as posições longas são fechadas e uma posição curta é aberta quando o preço ultrapassa as máximas recentes, enquanto
as posições curtas são cobertas e uma nova compra é estabelecida quando o preço ultrapassa os mínimos recentes. As paradas de proteção são derivadas de
a largura do intervalo para que a distância de parada se adapte automaticamente à volatilidade atual.
Como funciona
Assine o prazo configurado (15 minutos por padrão) e aguarde os indicadores construírem um histórico completo.
Para cada nova vela finalizada, calcule a máxima mais alta e a mínima mais baixa das velas BreakoutPeriod anteriores. O atual
vela não faz parte desse intervalo, exatamente como no EA original, onde iHighest(..., shift = 1) pula a barra de trabalho.
Recalcule a distância de parada como (high - low) * StopLossMultiplier enquanto aplica a distância mínima definida por
MinStopDistance.
Mantenha uma janela de negociação definida por SessionStartHour e SessionLengthHours. Quando a janela passa da meia-noite de sexta-feira
é prorrogado por dois dias para que as negociações abertas sobrevivam ao fim de semana, assim como em MetaTrader.
Quando a máxima da vela excede a máxima de fuga armazenada:
Feche qualquer posição longa existente e, se a negociação for permitida, abra uma posição curta com tamanho OrderVolume.
Anexe um stop loss acima do preço de entrada usando a distância de stop calculada.
Quando a mínima da vela cai abaixo da mínima de fuga armazenada:
Feche qualquer posição curta existente e, se a negociação for permitida, abra uma posição longa com tamanho OrderVolume.
Anexe um stop loss abaixo do preço de entrada usando a distância de stop calculada.
As paradas de proteção são avaliadas em cada vela acabada. Se a baixa tocar a parada longa ou a alta atingir a parada curta,
a posição é achatada imediatamente.
Lógica da Sessão de Negociação
SessionStartHour é expresso em horas de troca. O comprimento da janela é definido com SessionLengthHours.
Se a sessão se estender além de 24 horas e o dia atual for sexta-feira, o final da janela será adiantado em 48 horas para que
que a negociação recomeça na segunda-feira, correspondendo ao tratamento do fim de semana no código MQL4.
Fora da janela de negociação a estratégia apenas fecha as posições existentes; novas negociações são permitidas novamente assim que a janela for aberta.
Parâmetros
Nome
Descrição
Padrão
CandleType
Tipo de dados Candle usado para cálculo de sinal.
Período de 15 minutos
OrderVolume
Tamanho fixo da ordem para cada ordem de mercado.
1
SessionStartHour
Hora do dia em que a janela de breakout começa.
21
SessionLengthHours
Duração da janela de negociação em horas.
9
BreakoutPeriod
Número de velas concluídas que definem o intervalo de rompimento.
36
StopLossMultiplier
Multiplicador aplicado à largura do intervalo para derivar a distância de parada (o valor 3 corresponde ao SLpp = 300 original).
3
MinStopDistance
Distância mínima de stop-loss em unidades de preço absoluto, emulando a restrição de nível de stop MetaTrader.
0
Notas
A estratégia utiliza apenas ordens de mercado; não há lucro. O stop-loss protetor é o único mecanismo de saída além
o sinal de fuga oposto.
Ao mudar de compra para venda (ou vice-versa), a estratégia envia uma única ordem de mercado que fecha a anterior.
posição e abre a nova, espelhando o comportamento da fonte EA que chamou sequencialmente OrderClose e
OrderSend.
As linhas indicadoras para os máximos e mínimos de ruptura são traçadas automaticamente no gráfico de estratégia juntamente com as negociações executadas.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Range breakout strategy that uses Highest/Lowest channel.
/// Enters on breakouts above/below the channel and exits on reversion.
/// </summary>
public class PipsoNightBreakoutStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _breakoutPeriod;
private decimal _entryPrice;
private decimal _prevHighest;
private decimal _prevLowest;
private bool _hasPrev;
public PipsoNightBreakoutStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis.", "General");
_breakoutPeriod = Param(nameof(BreakoutPeriod), 36)
.SetDisplay("Breakout Period", "Period for Highest/Lowest channel.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int BreakoutPeriod
{
get => _breakoutPeriod.Value;
set => _breakoutPeriod.Value = value;
}
/// <inheritdoc />
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
_prevHighest = 0;
_prevLowest = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_entryPrice = 0;
_prevHighest = 0;
_prevLowest = 0;
_hasPrev = false;
var highest = new Highest { Length = BreakoutPeriod };
var lowest = new Lowest { Length = BreakoutPeriod };
var ema = new ExponentialMovingAverage { Length = BreakoutPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highest, lowest, ema, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal highestValue, decimal lowestValue, decimal emaValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var mid = (highestValue + lowestValue) / 2m;
// Exit conditions
if (Position > 0)
{
// Exit when price reverts to middle or stop-loss
if (close < mid || (_entryPrice > 0 && close < _entryPrice * 0.98m))
{
SellMarket();
}
}
else if (Position < 0)
{
if (close > mid || (_entryPrice > 0 && close > _entryPrice * 1.02m))
{
BuyMarket();
}
}
// Entry conditions: breakout above previous highest or below previous lowest
if (Position == 0 && _hasPrev)
{
if (close > _prevHighest && close > emaValue)
{
_entryPrice = close;
BuyMarket();
}
else if (close < _prevLowest && close < emaValue)
{
_entryPrice = close;
SellMarket();
}
}
_prevHighest = highestValue;
_prevLowest = lowestValue;
_hasPrev = true;
}
}
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.Indicators import Highest, Lowest, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class pipso_night_breakout_strategy(Strategy):
def __init__(self):
super(pipso_night_breakout_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
self._breakout_period = self.Param("BreakoutPeriod", 36).SetDisplay("Breakout Period", "Period for Highest/Lowest channel", "Indicators")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(pipso_night_breakout_strategy, self).OnReseted()
self._entry_price = 0
self._prev_highest = 0
self._prev_lowest = 0
self._has_prev = False
def OnStarted2(self, time):
super(pipso_night_breakout_strategy, self).OnStarted2(time)
self._entry_price = 0
self._prev_highest = 0
self._prev_lowest = 0
self._has_prev = False
highest = Highest()
highest.Length = self._breakout_period.Value
lowest = Lowest()
lowest.Length = self._breakout_period.Value
ema = ExponentialMovingAverage()
ema.Length = self._breakout_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(highest, lowest, ema, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def OnProcess(self, candle, highest_val, lowest_val, ema_val):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
mid = (highest_val + lowest_val) / 2.0
if self.Position > 0:
if close < mid or (self._entry_price > 0 and close < self._entry_price * 0.98):
self.SellMarket()
elif self.Position < 0:
if close > mid or (self._entry_price > 0 and close > self._entry_price * 1.02):
self.BuyMarket()
if self.Position == 0 and self._has_prev:
if close > self._prev_highest and close > ema_val:
self._entry_price = close
self.BuyMarket()
elif close < self._prev_lowest and close < ema_val:
self._entry_price = close
self.SellMarket()
self._prev_highest = highest_val
self._prev_lowest = lowest_val
self._has_prev = True
def CreateClone(self):
return pipso_night_breakout_strategy()