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
O stop fica essa porcentagem além do lado oposto da barra interna; ele e a saída pelo extremo da vela anterior são verificados no fechamento das velas.
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.
/// An inside bar's range lies within the previous candle's high and low. While flat, a close above the latest inside bar's
/// high buys and a close below its low sells. The stop lies StopLossPercent percent beyond the opposite side of the pattern,
/// and a close beyond the previous candle's extreme against the position also exits.
/// </summary>
public class InsideBarBreakoutStrategy : Strategy
{
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private (decimal High, decimal Low)? _prevCandle;
private (decimal High, decimal Low)? _insideBar;
private decimal _stopPrice;
/// <summary>
/// Distance of the stop beyond the pattern, in percent.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Candle type and timeframe.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public InsideBarBreakoutStrategy()
{
_stopLossPercent = Param(nameof(StopLossPercent), 1m)
.SetNotNegative()
.SetDisplay("Stop Loss %", "Distance of the stop beyond the pattern, in percent", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_insideBar = null;
_stopPrice = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_insideBar = null;
_stopPrice = default;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var previous = _prevCandle;
var pattern = _insideBar;
_prevCandle = (candle.HighPrice, candle.LowPrice);
var isInside = previous is { } prev && candle.HighPrice <= prev.High && candle.LowPrice >= prev.Low;
var close = candle.ClosePrice;
// A close outside the pattern uses it up; a new inside bar replaces it.
if (pattern is { } bar && (close > bar.High || close < bar.Low))
_insideBar = null;
if (isInside)
_insideBar = (candle.HighPrice, candle.LowPrice);
if (previous is not { } prior || !IsFormedAndOnlineAndAllowTrading())
return;
if (Position > 0)
{
if (close <= _stopPrice || close < prior.Low)
SellMarket(Position);
}
else if (Position < 0)
{
if (close >= _stopPrice || close > prior.High)
BuyMarket(-Position);
}
else if (pattern is { } inside)
{
if (close > inside.High)
{
BuyMarket(Volume);
_stopPrice = inside.Low * (1 - StopLossPercent / 100m);
}
else if (close < inside.Low)
{
SellMarket(Volume);
_stopPrice = inside.High * (1 + StopLossPercent / 100m);
}
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
class inside_bar_breakout_strategy(Strategy):
"""
Inside Bar Breakout strategy.
An inside bar's range lies within the previous candle's high and low. While flat, a close above the latest inside bar's
high buys and a close below its low sells. The stop lies StopLossPercent percent beyond the opposite side of the pattern,
and a close beyond the previous candle's extreme against the position also exits.
"""
def __init__(self):
super(inside_bar_breakout_strategy, self).__init__()
self._stop_loss_percent = self.Param("StopLossPercent", 1.0).SetNotNegative().SetDisplay("Stop Loss %", "Distance of the stop beyond the pattern, in percent", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_candle = None
self._inside_bar = None
self._stop_price = Decimal(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._stop_price = Decimal(0)
def OnStarted2(self, time):
super(inside_bar_breakout_strategy, self).OnStarted2(time)
self._prev_candle = None
self._inside_bar = None
self._stop_price = Decimal(0)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
previous = self._prev_candle
pattern = self._inside_bar
self._prev_candle = (candle.HighPrice, candle.LowPrice)
is_inside = previous is not None and candle.HighPrice <= previous[0] and candle.LowPrice >= previous[1]
close = candle.ClosePrice
# A close outside the pattern uses it up; a new inside bar replaces it.
if pattern is not None and (close > pattern[0] or close < pattern[1]):
self._inside_bar = None
if is_inside:
self._inside_bar = (candle.HighPrice, candle.LowPrice)
if previous is None or not self.IsFormedAndOnlineAndAllowTrading():
return
percent = Decimal(self._stop_loss_percent.Value) / Decimal(100)
if self.Position > 0:
if close <= self._stop_price or close < previous[1]:
self.SellMarket(self.Position)
elif self.Position < 0:
if close >= self._stop_price or close > previous[0]:
self.BuyMarket(-self.Position)
elif pattern is not None:
if close > pattern[0]:
self.BuyMarket(self.Volume)
self._stop_price = pattern[1] * (Decimal(1) - percent)
elif close < pattern[1]:
self.SellMarket(self.Volume)
self._stop_price = pattern[0] * (Decimal(1) + percent)
def CreateClone(self):
return inside_bar_breakout_strategy()