A Estratégia Nextbar é uma tradução direta do MetaTrader 4 consultor especialista nextbar.mq4. O EA original avalia a distância entre a última vela concluída e uma vela várias barras mais antiga. Quando o preço viaja longe o suficiente em uma direção, ele segue o impulso ou negocia contra ele, dependendo da bandeira de direção configurada. As posições são então protegidas com níveis simétricos de take-profit/stop-loss e são fechadas à força após um número fixo de barras.
Esta versão StockSharp mantém o mesmo comportamento ao usar a estratégia de alto nível API. Ele processa apenas velas concluídas, garantindo que todos os cálculos correspondam à lógica de barra ao fechar do script MT4.
Lógica MQL original
Distância do momento – compare Close[1] com Close[bars2check+1]. Se a diferença for de pelo menos minbar * Point, trate-a como um sinal válido.
Sinalizador de direção – a entrada MQL direction é igual a 1 para acompanhamento de tendência (comprar após uma alta, vender após uma queda) e 2 para negociação contrária (comprar após uma queda, vender após uma alta).
Restrição de entrada – apenas um pedido pode ser aberto por vez. Uma nova negociação é enviada no início da barra seguindo o sinal.
Regras de saída – feche uma posição comprada se o último fechamento atingir a distância de lucro acima da entrada ou a distância de perda abaixo dela; o inverso se aplica a shorts. Se nenhum dos níveis for atingido, feche a negociação após bars2hold velas concluídas.
StockSharp destaques de implementação
Usa SubscribeCandles() e Bind para receber velas concluídas no período configurado.
Armazena um breve histórico contínuo de preços de fechamento para fazer referência à vela que corresponde ao deslocamento MQL bars2check + 1.
Converte todos os parâmetros baseados em pontos com Security.PriceStep, imitando a constante MetaTrader Point.
Coloca ordens de mercado com a estratégia Volume e suporta entradas de acompanhamento de impulso ou contrárias por meio do parâmetro Direction.
Implementa saídas de lucros, perdas e períodos de retenção exatamente uma vez por vela concluída para permanecer alinhado com o fluxo de trabalho original.
Parâmetros
Parâmetro
Descrição
Padrão
Notas
CandleType
Prazo usado para avaliação do sinal.
Período de 1 hora
Anexe a estratégia a um título que possa fornecer esse tipo de vela.
BarsToCheck
Número de velas concluídas entre o fechamento de referência e o último fechamento.
8
Corresponde a bars2check de EA.
BarsToHold
Número máximo de velas concluídas para manter uma posição aberta.
10
Corresponde a bars2hold. A posição é fechada na barra onde o contador atinge este número.
MinMovePoints
Distância mínima (em MetaTrader pontos) entre os dois fechamentos comparados.
77
Corresponde a minbar. Convertido usando Security.PriceStep.
TakeProfitPoints
Distância alvo de lucro em MetaTrader pontos.
115
Equivalente à entrada profit. Defina como zero para desativar, se desejar.
StopLossPoints
Distância de stop-loss em MetaTrader pontos.
115
Equivalente à entrada loss. Defina como zero para desativar, se desejar.
Direction
Modo de negociação: Follow (tendência) ou Reverse (contrária).
Follow
Espelha a entrada direction (1 = seguir, 2 = reverter).
Volume
Volume de negociação usado para ordens de mercado.
Volume de estratégia
Configure por meio da propriedade padrão Strategy.Volume.
Fluxo de trabalho de negociação
Espere por uma vela finalizada e armazene seu preço de fechamento.
Obtenha o fechamento de BarsToCheck velas atrás e calcule a diferença.
Se o movimento absoluto estiver abaixo de MinMovePoints * PriceStep, não faça nada.
Caso contrário:
No modo Seguir, compre se o preço subir e venda se o preço cair.
No modo Reverso, compre se o preço cair e venda se o preço subir.
Em cada vela finalizada subsequente enquanto a posição estiver aberta:
Fechar posições compradas quando o fechamento estiver TakeProfitPoints acima ou StopLossPoints abaixo do preço de entrada armazenado.
Fechar posições vendidas quando o fechamento estiver TakeProfitPoints abaixo ou StopLossPoints acima da entrada.
Forçar o fechamento assim que BarsToHold velas tiverem decorrido desde a entrada.
Notas de uso
A conversão de pontos em preço absoluto requer Security.PriceStep. Forneça os metadados corretos do instrumento (etapa de preço, preço escalonado, regras de volume) antes de executar a estratégia.
A estratégia não gerencia múltiplas posições simultâneas; certifique-se de que Volume corresponda ao tamanho esperado para um único pedido MT4.
Como as decisões são avaliadas apenas em velas concluídas, a estratégia deve ser executada com dados históricos e em tempo real que forneçam barras concluídas.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class NextbarStrategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevOpen;
private decimal _prevClose;
private bool _hasPrev;
private int _cooldownRemaining;
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public NextbarStrategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 50).SetDisplay("EMA Period", "EMA filter", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 200).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevOpen = default;
_prevClose = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevOpen = 0;
_prevClose = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ema)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (!_hasPrev) { _prevOpen = candle.OpenPrice; _prevClose = close; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevOpen = candle.OpenPrice;
_prevClose = close;
return;
}
var prevBullish = _prevClose > _prevOpen;
var prevBearish = _prevClose < _prevOpen;
if (prevBullish && close > ema && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (prevBearish && close < ema && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevOpen = candle.OpenPrice;
_prevClose = close;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class nextbar_strategy(Strategy):
def __init__(self):
super(nextbar_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 50) \
.SetDisplay("EMA Period", "EMA filter", "Indicators")
self._cooldown_candles = self.Param("CooldownCandles", 200) \
.SetDisplay("Cooldown", "Candles between signals", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_open = 0.0
self._prev_close = 0.0
self._has_prev = False
self._cooldown_remaining = 0
@property
def ema_period(self):
return self._ema_period.Value
@property
def cooldown_candles(self):
return self._cooldown_candles.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(nextbar_strategy, self).OnReseted()
self._prev_open = 0.0
self._prev_close = 0.0
self._has_prev = False
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(nextbar_strategy, self).OnStarted2(time)
self._prev_open = 0.0
self._prev_close = 0.0
self._has_prev = False
self._cooldown_remaining = 0
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self.process_candle).Start()
def process_candle(self, candle, ema):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
ema_val = float(ema)
if not self._has_prev:
self._prev_open = open_price
self._prev_close = close
self._has_prev = True
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_open = open_price
self._prev_close = close
return
prev_bullish = self._prev_close > self._prev_open
prev_bearish = self._prev_close < self._prev_open
if prev_bullish and close > ema_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown_remaining = self.cooldown_candles
elif prev_bearish and close < ema_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown_remaining = self.cooldown_candles
self._prev_open = open_price
self._prev_close = close
def CreateClone(self):
return nextbar_strategy()