A Estratégia de Three Breaky é uma conversão completa do expert advisor MetaTrader 4 ThreeBreaky_v1.mq4. A versão StockSharp mantém o trio original de subsistemas de rompimento, traduz sua lógica baseada em velas para a API de alto nível e adiciona controle claro de posições para cada módulo. A estratégia trabalha em um único período configurável e pode habilitar ou desabilitar qualquer subsistema sem afetar os outros.
Módulos de negociação
Sistema 1 – Rompimento de expansão ATR
Usa apenas a vela anterior.
Vai comprado quando a vela anterior é de alta e seu intervalo máximo-mínimo excede quatro vezes o average true range de 72 períodos.
Vai vendido quando a vela anterior é de baixa e a mesma condição de intervalo é satisfeita.
Sistema 2 – Flip de nuvem Ichimoku
Observa os limites da nuvem (Senkou Span A e Senkou Span B) com períodos padrão 9/26/52.
Um sinal comprado é acionado quando duas velas atrás fechou abaixo de ambos os spans e o último fechou acima de ambos (um flip de alta através da nuvem).
Um sinal vendido é acionado quando duas velas atrás fechou acima de ambos os spans e o último fechou abaixo de ambos.
Sistema 3 – Rompimento de corpo excepcional
Rastreia o tamanho do corpo das últimas 20 velas completadas.
Uma configuração comprada exige que a vela anterior seja de alta e seu corpo seja mais de três vezes o corpo máximo observado nessa história de 20 velas.
Uma configuração vendida espelha a condição para corpos de baixa.
Cada subsistema negocia uma posição virtual dedicada. Os carimbos de tempo das ordens são armazenados para garantir que um módulo possa abrir no máximo uma operação por vela, assim como a lógica original buyTag e sellTag.
Lógica de saída
Reversão de SAR Parabólico: Todas as posições abertas compartilham uma saída de SAR Parabólico (0.005/0.2). Quando o preço cruza o SAR entre as duas últimas velas, a posição afetada é fechada.
Gestão de risco: Distâncias opcionais de stop-loss e take-profit (em pips) são avaliadas em cada vela completada. Se os limiares configurados forem violados, a posição relevante é fechada imediatamente.
Indicadores utilizados
Average True Range (período 72) para a linha de base de volatilidade média.
Ichimoku Kinko Hyo (9, 26, 52) para o filtro de flip de nuvem.
SAR Parabólico (aceleração 0.005, máximo 0.2) para saídas e lógica de trailing.
Buffer de tamanho de corpo rotativo (20 velas) para reproduzir a comparação de corpo máximo MQL.
Parâmetros
Parâmetro
Descrição
UseSystem1
Habilita o módulo de rompimento de expansão ATR.
UseSystem2
Habilita o módulo de flip de nuvem Ichimoku.
UseSystem3
Habilita o módulo de rompimento de corpo grande.
OrderVolume
Volume usado para cada ordem a mercado gerada por qualquer módulo.
StopLossPips
Distância de stop protetor em pips. Definir como zero para desativar.
TakeProfitPips
Distância de take-profit em pips. Definir como zero para desativar.
CandleType
Período para as velas de trabalho (padrão 1 hora).
Resumo do fluxo de trabalho
Assinar a série de velas configurada e processar apenas velas finalizadas.
Atualizar os indicadores ATR, Ichimoku e SAR Parabólico junto com o histórico de corpo rotativo.
Fechar posições que atingirem stops, alvos ou reversões de SAR Parabólico.
Se a negociação for permitida, avaliar cada subsistema independentemente e emitir ordens a mercado quando todas as condições respectivas forem atendidas.
Armazenar as últimas saídas dos indicadores para que a próxima vela possa acessar os mesmos valores históricos da implementação MQL original.
Notas
A estratégia assume um valor de pip baseado no passo de preço do instrumento; cotações FX de cinco e três dígitos são normalizadas para tamanhos de pip de quatro e dois decimais, respectivamente.
Os subsistemas podem rodar simultaneamente. Cada um mantém seu próprio preço de entrada, direção de posição e últimos carimbos de tempo de sinal para espelhar a separação MagicNumber+N do EA fonte.
A implementação StockSharp retém o padrão de execução "uma vez por barra" usando tempos de abertura de velas para bloquear ordens duplicadas dentro de uma única barra.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class ThreeBreakyStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public ThreeBreakyStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 15).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 60).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 three_breaky_strategy(Strategy):
def __init__(self):
super(three_breaky_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 15) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 60) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(three_breaky_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(three_breaky_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return three_breaky_strategy()