インサイドバー・ブレイクアウト戦略
インサイドバーは、ローソク足のレンジが前のバーの高値と安値の範囲内に完全に収まる時に形成されます。価格がパターンを超えると、ブレイクアウトにつながる可能性のある短期的な不決断を示します。この戦略はそのブレイクを待ち、その後、拡張の方向に取引します。
テストでは年平均リターンが約118%であることが示されています。株式市場で最も良いパフォーマンスを発揮します。
各新しいローソク足は前のものと比較されます。インサイドバーが現れると、システムはその高値と安値をマークし、それらのレベルの外での終値を監視します。強気のブレイクアウトはパターンの安値の下にストップを置いてロングポジションを開き、弱気のブレイクアウトはパターンの高値の上にストップを置いてショートを起動します。
価格がすぐにブレイクアウトしない場合、次のローソク足が前のバーの極値を超えてトレードに逆行するとポジションを決済することで、既存のポジションを管理します。
詳細
- エントリー条件: インサイドバーの高値または安値のブレイクアウト。
- ロング/ショート: 両方。
- エグジット条件: 価格が前のローソク足の極値を越えるか、ストップロス。
- ストップ: はい、パターンの外側に配置。
- デフォルト値:
CandleType= 5 minuteStopLossPercent= 1 ストップはインサイドバーの反対側からこの割合(%)だけ外側に置かれ、ストップと前の足の高値・安値による手仕舞いはどちらも終値で判定します。
- フィルター:
- カテゴリ: ブレイクアウト
- 方向: 両方
- インジケーター: Candlestick
- ストップ: はい
- 複雑さ: 中級
- 時間軸: イントラデイ
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
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()