This strategy trades breakouts of outside bars. A bullish outside bar occurs when the current candle's high is above the previous high and its low is below the previous low. Orders are placed inside the bar with optional partial profit taking and breakeven stop movement.
Details
Entry Criteria: Outside bar with bullish or bearish classification.
Long/Short: Both.
Exit Criteria: Stop loss or take profit derived from bar range.
Stops: Yes.
Default Values:
CandleType = 5 minute
EntryPercentage = 0.5
TpPercentage = 1
PartialRR = 1
PartialExitPercent = 0.5
StopLossOffset = 10
Filters:
Category: Pattern
Direction: Both
Indicators: Candlestick
Stops: Yes
Complexity: Intermediate
Timeframe: Intraday
Seasonality: No
Neural networks: No
Divergence: No
Risk level: Medium
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class OutsideBarStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private decimal _prevHigh;
private decimal _prevLow;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public OutsideBarStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame());
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = 0;
_prevLow = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHigh = 0;
_prevLow = 0;
_hasPrev = false;
var sma = new SimpleMovingAverage { Length = 20 };
var lastSignal = DateTimeOffset.MinValue;
var cooldown = TimeSpan.FromMinutes(360);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, (candle, smaVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!sma.IsFormed)
return;
if (!_hasPrev)
{
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_hasPrev = true;
return;
}
var isOutsideBar = candle.HighPrice > _prevHigh && candle.LowPrice < _prevLow;
if (isOutsideBar && candle.OpenTime - lastSignal >= cooldown)
{
var isBullish = candle.ClosePrice > candle.OpenPrice;
if (isBullish && candle.ClosePrice > smaVal && Position <= 0)
{
BuyMarket();
lastSignal = candle.OpenTime;
}
else if (!isBullish && candle.ClosePrice < smaVal && Position >= 0)
{
SellMarket();
lastSignal = candle.OpenTime;
}
}
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
}
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 outside_bar_strategy(Strategy):
def __init__(self):
super(outside_bar_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
self._last_signal_ticks = 0
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(outside_bar_strategy, self).OnReseted()
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
self._last_signal_ticks = 0
def OnStarted2(self, time):
super(outside_bar_strategy, self).OnStarted2(time)
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
self._last_signal_ticks = 0
self._sma = SimpleMovingAverage()
self._sma.Length = 20
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._sma, self.OnProcess).Start()
def OnProcess(self, candle, sma_val):
if candle.State != CandleStates.Finished:
return
if not self._sma.IsFormed:
return
sv = float(sma_val)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
close = float(candle.ClosePrice)
opn = float(candle.OpenPrice)
if not self._has_prev:
self._prev_high = high
self._prev_low = low
self._has_prev = True
return
is_outside_bar = high > self._prev_high and low < self._prev_low
cooldown_ticks = TimeSpan.FromMinutes(360).Ticks
current_ticks = candle.OpenTime.Ticks
if is_outside_bar and current_ticks - self._last_signal_ticks >= cooldown_ticks:
is_bullish = close > opn
if is_bullish and close > sv and self.Position <= 0:
self.BuyMarket()
self._last_signal_ticks = current_ticks
elif not is_bullish and close < sv and self.Position >= 0:
self.SellMarket()
self._last_signal_ticks = current_ticks
self._prev_high = high
self._prev_low = low
def CreateClone(self):
return outside_bar_strategy()