Estratégia de nível de detalhamento de Nevalyashka
Visão geral
A estratégia Nevalyashka Breakdown Level é uma conversão direta do consultor especialista MT4 Nevalyashka_BreakdownLevel. O sistema constrói um intervalo de abertura entre dois tempos configuráveis e negocia rompimentos desse intervalo. Quando um rompimento falha e a negociação é interrompida, a estratégia imediatamente inverte a direção usando um multiplicador martingale para recuperar a perda. As negociações lucrativas bloqueiam quaisquer entradas adicionais durante o resto do dia de negociação, correspondendo ao comportamento original EA.
Conceitos-chave
Intervalo de abertura: Maior máximo e menor mínimo impressos entre RangeStart e RangeEnd definem o canal de breakout para o dia atual.
Entradas de breakout: Uma posição longa é aberta quando o preço de fechamento excede a faixa máxima; uma posição curta é aberta quando cai abaixo do intervalo mínimo.
Ordens de proteção: O stop loss é sempre colocado no lado oposto do intervalo. O take-profit é posicionado a uma distância igual à largura do intervalo.
Movimento de equilíbrio: Quando ativado, o stop é movido para o preço de entrada assim que a negociação avança até a metade do caminho em direção ao alvo.
Martingale recuperação: Após um stop-loss, a estratégia inverte a direção, multiplica o volume do pedido por MartingaleMultiplier e usa um tamanho alvo/stop simétrico para recuperar a perda anterior.
Bloqueio diário: Qualquer fechamento lucrativo (take-profit ou saída manual acima de zero) impede novas negociações até que o dia de negociação mude.
Flatização forçada: Quando OrdersCloseTime for posterior a RangeEnd, todas as posições abertas serão fechadas nesse horário e novas entradas serão bloqueadas pelo restante do dia.
Parâmetros
Nome
Descrição
Padrão
RangeStart
Hora de início (inclusive) do intervalo de referência.
04:00
RangeEnd
Hora final (inclusive) do intervalo de referência.
09:00
OrdersCloseTime
Hora do dia para fechar posições à força. Quando esse horário for posterior a RangeEnd, ele também bloqueará novas negociações posteriormente.
23:30
OrderVolume
Volume usado para cada negociação de breakout.
0.1
MartingaleMultiplier
Multiplicador aplicado à próxima ordem após um stop loss para recuperar a perda anterior.
2
UseBreakeven
Permite mover o stop para o ponto de equilíbrio quando a negociação tiver percorrido metade da distância alvo.
true
CandleType
Tipo de vela usado para construir o alcance e gerar sinais.
1 hour velas
Regras de negociação
Cálculo de intervalo: Para cada novo dia de negociação, a estratégia registra os máximos e mínimos das velas finalizadas entre RangeStart e RangeEnd (inclusive).
Condições de entrada:
Opere comprado quando o preço de fechamento da vela atual estiver acima da máxima registrada.
Opere vendido quando o preço de fechamento da vela atual estiver abaixo do mínimo registrado.
As entradas serão ignoradas se uma reversão do martingale estiver pendente, uma negociação lucrativa já tiver ocorrido no mesmo dia ou se a hora atual tiver passado de OrdersCloseTime (quando OrdersCloseTime > RangeEnd).
Gerenciamento de riscos:
O stop loss está ancorado no lado oposto da faixa de abertura.
O take-profit é definido pelo preço de entrada mais/menos a largura do intervalo de abertura.
Quando UseBreakeven está ativado, o stop se move para o preço de entrada após metade da distância alvo ter sido percorrida.
Martingale reversão:
Se o stop loss for atingido, a posição é fechada, o volume é multiplicado por MartingaleMultiplier e uma ordem de mercado imediata na direção oposta é enviada.
O novo stop e o alvo são colocados a uma distância igual à perda por lote dividida pelo multiplicador, correspondendo à lógica de recuperação do EA original.
Bloqueio comercial diário:
Se uma negociação fechar com lucro não negativo ou a meta for atingida, nenhuma nova negociação será permitida até que a data de negociação seja alterada.
Saída forçada:
Quando OrdersCloseTime estiver após a janela do intervalo e o horário atual atingir esse valor, todas as posições abertas serão achatadas e o dia será bloqueado.
Notas
A estratégia usa o StockSharp API (Strategy.SubscribeCandles().Bind(...)) de alto nível para ficar próximo das convenções da estrutura.
Todos os cálculos com estado (limites de intervalo, ordens pendentes de martingale, estado de equilíbrio) são armazenados dentro da classe de estratégia para evitar pesquisas históricas.
A conversão preserva o comportamento original do EA de contar os dias de negociação por data do calendário e gerenciar as etapas do martingale imediatamente após uma parada.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Nevalyashka BreakdownLevel: Previous candle breakout with EMA filter and ATR stops.
/// </summary>
public class NevalyashkaBreakdownLevelStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevHigh;
private decimal _prevLow;
private decimal _entryPrice;
public NevalyashkaBreakdownLevelStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_emaLength = Param(nameof(EmaLength), 30)
.SetDisplay("EMA Length", "Trend filter.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = 0; _prevLow = 0; _entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHigh = 0; _prevLow = 0; _entryPrice = 0;
var ema = new ExponentialMovingAverage { Length = EmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (_prevHigh == 0 || atrVal <= 0) { _prevHigh = candle.HighPrice; _prevLow = candle.LowPrice; return; }
if (Position > 0)
{
if (close <= _entryPrice - atrVal * 1.5m || close >= _entryPrice + atrVal * 2.5m) { SellMarket(); _entryPrice = 0; }
}
else if (Position < 0)
{
if (close >= _entryPrice + atrVal * 1.5m || close <= _entryPrice - atrVal * 2.5m) { BuyMarket(); _entryPrice = 0; }
}
if (Position == 0)
{
if (close > _prevHigh && close > emaVal) { _entryPrice = close; BuyMarket(); }
else if (close < _prevLow && close < emaVal) { _entryPrice = close; SellMarket(); }
}
_prevHigh = candle.HighPrice; _prevLow = candle.LowPrice;
}
}
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 StockSharp.Algo.Indicators import ExponentialMovingAverage, AverageTrueRange
class nevalyashka_breakdown_level_strategy(Strategy):
def __init__(self):
super(nevalyashka_breakdown_level_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(8))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._ema_length = self.Param("EmaLength", 30) \
.SetDisplay("EMA Length", "Trend filter.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_high = 0.0
self._prev_low = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(nevalyashka_breakdown_level_strategy, self).OnStarted2(time)
self._prev_high = 0.0
self._prev_low = 0.0
self._entry_price = 0.0
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._ema, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
ev = float(ema_val)
av = float(atr_val)
close = float(candle.ClosePrice)
if self._prev_high == 0 or av <= 0:
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
return
if self.Position > 0:
if close <= self._entry_price - av * 1.5 or close >= self._entry_price + av * 2.5:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close >= self._entry_price + av * 1.5 or close <= self._entry_price - av * 2.5:
self.BuyMarket()
self._entry_price = 0.0
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
return
if self.Position == 0:
if close > self._prev_high and close > ev:
self._entry_price = close
self.BuyMarket()
elif close < self._prev_low and close < ev:
self._entry_price = close
self.SellMarket()
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
def OnReseted(self):
super(nevalyashka_breakdown_level_strategy, self).OnReseted()
self._prev_high = 0.0
self._prev_low = 0.0
self._entry_price = 0.0
def CreateClone(self):
return nevalyashka_breakdown_level_strategy()