Eine Inside Bar entsteht, wenn die Handelsspanne einer Kerze vollständig innerhalb des Hochs und Tiefs des vorherigen Balkens liegt. Sie signalisiert kurzfristige Unentschlossenheit, die zu einem Ausbruch führen kann, sobald der Kurs das Muster verlässt. Diese Strategie wartet auf diesen Ausbruch und handelt dann in Richtung der Expansion.
Tests zeigen eine durchschnittliche Jahresrendite von etwa 118%. Die Strategie eignet sich am besten für den Aktienmarkt.
Jede neue Kerze wird mit der vorherigen verglichen. Erscheint eine Inside Bar, markiert das System ihr Hoch und Tief und beobachtet einen Schlusskurs außerhalb dieser Niveaus. Ein bullischer Ausbruch eröffnet eine Long-Position mit einem Stop unterhalb des Musters-Tiefs, während ein bearischer Ausbruch einen Short mit einem Stop oberhalb des Musters-Hochs auslöst.
Sollte der Kurs nicht sofort ausbrechen, verwaltet die Strategie bestehende Positionen, indem sie aussteigt, wenn die nächste Kerze gegen den Trade über die Extrempunkte des vorherigen Balkens hinausgeht.
Details
Einstiegskriterien: Ausbruch des Hochs oder Tiefs einer Inside Bar.
Long/Short: Beide.
Ausstiegskriterien: Kurs kreuzt das Extrem der vorherigen Kerze oder Stop-Loss.
Stops: Ja, außerhalb des Musters platziert.
Standardwerte:
CandleType = 5 minute
StopLossPercent = 1
Der Stop liegt so viele Prozent jenseits der gegenüberliegenden Seite des Inside Bars; er und der Ausstieg am Extrem der Vorkerze werden bei Kerzenschluss geprüft.
Filter:
Kategorie: Ausbruch
Richtung: Beide
Indikatoren: Candlestick
Stops: Ja
Komplexität: Mittel
Zeitrahmen: Intraday
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
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()