インサイドバー・ブレイクアウト戦略
インサイドバーは、ローソク足のレンジが前のバーの高値と安値の範囲内に完全に収まる時に形成されます。価格がパターンを超えると、ブレイクアウトにつながる可能性のある短期的な不決断を示します。この戦略はそのブレイクを待ち、その後、拡張の方向に取引します。
テストでは年平均リターンが約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.
/// 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()