Uma barra interna se forma quando o intervalo de uma vela está completamente contido dentro da máxima e da mínima da barra anterior. Ela sinaliza indecisão de curto prazo que pode levar a um rompimento assim que o preço superar o padrão. Esta estratégia aguarda esse rompimento e então opera na direção da expansão.
Os testes indicam um retorno anual médio de aproximadamente 118%. Funciona melhor no mercado de ações.
Cada nova vela é comparada com a anterior. Se uma barra interna aparecer, o sistema marca sua máxima e mínima e observa um fechamento fora desses níveis. Um rompimento de alta abre uma posição comprada com stop abaixo da mínima do padrão, enquanto um rompimento de baixa aciona uma posição vendida com stop acima da máxima do padrão.
Caso o preço não rompa imediatamente, a estratégia gerencia as posições existentes saindo se a próxima vela se mover contra a operação além dos extremos da barra anterior.
Detalhes
Critérios de entrada: Rompimento da máxima ou mínima de uma barra interna.
Comprado/Vendido: Ambos.
Critérios de saída: Preço cruzando o extremo da vela anterior ou stop-loss.
Stops: Sim, colocados além do padrão.
Valores padrão:
CandleType = 5 minute
StopLossPercent = 1
Filtros:
Categoria: Rompimento
Direção: Ambos
Indicadores: Candlestick
Stops: Sim
Complexidade: Intermediário
Período: Intradiário
Sazonalidade: Não
Redes neurais: Não
Divergência: Não
Nível de risco: Médio
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;
/// <summary>
/// Inside Bar Breakout strategy.
/// Detects inside bar patterns (high lower than previous high, low higher than previous low).
/// Enters on breakout of the inside bar's high (buy) or low (sell).
/// Uses SMA for exit signals.
/// </summary>
public class InsideBarBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private ICandleMessage _prevCandle;
private ICandleMessage _insideBar;
private bool _waitingForBreakout;
private int _cooldown;
/// <summary>
/// MA Period.
/// </summary>
public int MAPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown bars.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public InsideBarBreakoutStrategy()
{
_maPeriod = Param(nameof(MAPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Period for SMA", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_cooldownBars = Param(nameof(CooldownBars), 500)
.SetRange(1, 1000)
.SetDisplay("Cooldown Bars", "Bars to wait between trades", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_insideBar = null;
_waitingForBreakout = false;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_insideBar = null;
_waitingForBreakout = false;
_cooldown = 0;
var sma = new SimpleMovingAverage { Length = MAPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_cooldown > 0)
{
_cooldown--;
_prevCandle = candle;
_waitingForBreakout = false;
return;
}
if (_prevCandle == null)
{
_prevCandle = candle;
return;
}
// Check for breakout of a previously detected inside bar
if (_waitingForBreakout && _insideBar != null && Position == 0)
{
if (candle.HighPrice > _insideBar.HighPrice)
{
BuyMarket();
_cooldown = CooldownBars;
_waitingForBreakout = false;
}
else if (candle.LowPrice < _insideBar.LowPrice)
{
SellMarket();
_cooldown = CooldownBars;
_waitingForBreakout = false;
}
}
// Check if current candle is an inside bar
if (candle.HighPrice < _prevCandle.HighPrice && candle.LowPrice > _prevCandle.LowPrice)
{
_insideBar = candle;
_waitingForBreakout = true;
}
// Exit logic using SMA
if (Position > 0 && candle.ClosePrice < smaValue)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && candle.ClosePrice > smaValue)
{
BuyMarket();
_cooldown = CooldownBars;
}
_prevCandle = candle;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class inside_bar_breakout_strategy(Strategy):
"""
Inside Bar Breakout strategy.
Detects inside bar patterns (high lower than previous high, low higher than previous low).
Enters on breakout of the inside bar's high (buy) or low (sell).
Uses SMA for exit signals.
"""
def __init__(self):
super(inside_bar_breakout_strategy, self).__init__()
self._ma_period = self.Param("MAPeriod", 20).SetDisplay("MA Period", "Period for SMA", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._cooldown_bars = self.Param("CooldownBars", 500).SetDisplay("Cooldown Bars", "Bars to wait between trades", "General")
self._prev_candle = None
self._inside_bar = None
self._waiting_for_breakout = False
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(inside_bar_breakout_strategy, self).OnReseted()
self._prev_candle = None
self._inside_bar = None
self._waiting_for_breakout = False
self._cooldown = 0
def OnStarted2(self, time):
super(inside_bar_breakout_strategy, self).OnStarted2(time)
self._prev_candle = None
self._inside_bar = None
self._waiting_for_breakout = False
self._cooldown = 0
sma = SimpleMovingAverage()
sma.Length = self._ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sma_val):
if candle.State != CandleStates.Finished:
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_candle = candle
self._waiting_for_breakout = False
return
if self._prev_candle is None:
self._prev_candle = candle
return
cd = self._cooldown_bars.Value
# Check for breakout of a previously detected inside bar
if self._waiting_for_breakout and self._inside_bar is not None and self.Position == 0:
if candle.HighPrice > self._inside_bar.HighPrice:
self.BuyMarket()
self._cooldown = cd
self._waiting_for_breakout = False
elif candle.LowPrice < self._inside_bar.LowPrice:
self.SellMarket()
self._cooldown = cd
self._waiting_for_breakout = False
# Check if current candle is an inside bar
if candle.HighPrice < self._prev_candle.HighPrice and candle.LowPrice > self._prev_candle.LowPrice:
self._inside_bar = candle
self._waiting_for_breakout = True
# Exit logic using SMA
sv = float(sma_val)
close = float(candle.ClosePrice)
if self.Position > 0 and close < sv:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and close > sv:
self.BuyMarket()
self._cooldown = cd
self._prev_candle = candle
def CreateClone(self):
return inside_bar_breakout_strategy()