Bearish Abandoned Baby Strategy
The Bearish Abandoned Baby mirrors the bullish version but signals a potential top. It features a gap up doji followed by a gap down, leaving the middle candle isolated above the prior range.
Testing indicates an average annual return of about 79%. It performs best in the stocks market.
The strategy sells short when the third candle gaps below the doji, aiming to profit from the abrupt shift in sentiment.
Risk is limited with a stop just above the doji high in case price recovers.
Details
- Entry Criteria: pattern match
- Long/Short: Both
- Exit Criteria: stop-loss or opposite signal
- Stops: Yes, percent based
- Default Values:
CandleType= 15 minuteStopLoss= 2%
- 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 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>
/// Strategy based on Bearish Abandoned Baby candlestick pattern.
/// Detects a bullish candle followed by a small-body candle near highs,
/// then a bearish confirmation candle. Uses SMA for trend filter.
/// Also detects the bullish mirror pattern for long entries.
/// </summary>
public class BearishAbandonedBabyStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<int> _cooldownBars;
private SimpleMovingAverage _ma;
private decimal _prev2Open;
private decimal _prev2Close;
private decimal _prev2High;
private decimal _prev2Low;
private decimal _prev1Open;
private decimal _prev1Close;
private decimal _prev1High;
private decimal _prev1Low;
private decimal _prevMa;
private int _candleCount;
private int _cooldown;
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// MA period.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Cooldown bars.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public BearishAbandonedBabyStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetDisplay("MA Period", "SMA period for exit", "Indicators")
.SetRange(10, 50);
_cooldownBars = Param(nameof(CooldownBars), 400)
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
.SetRange(10, 3000);
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_ma = default;
_prev2Open = 0;
_prev2Close = 0;
_prev2High = 0;
_prev2Low = 0;
_prev1Open = 0;
_prev1Close = 0;
_prev1High = 0;
_prev1Low = 0;
_prevMa = 0;
_candleCount = 0;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_ma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_ma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal ma)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
_candleCount++;
var close = candle.ClosePrice;
var open = candle.OpenPrice;
var high = candle.HighPrice;
var low = candle.LowPrice;
if (_cooldown > 0)
{
_cooldown--;
_prev2Open = _prev1Open;
_prev2Close = _prev1Close;
_prev2High = _prev1High;
_prev2Low = _prev1Low;
_prev1Open = open;
_prev1Close = close;
_prev1High = high;
_prev1Low = low;
_prevMa = ma;
return;
}
// Exit logic: MA cross
if (Position > 0 && close < ma && _prevMa > 0 && _prev1Close >= _prevMa)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && close > ma && _prevMa > 0 && _prev1Close <= _prevMa)
{
BuyMarket();
_cooldown = CooldownBars;
}
// Entry logic
if (Position == 0 && _candleCount >= 3 && _prev2Close != 0)
{
var prev2Body = Math.Abs(_prev2Close - _prev2Open);
var prev2Range = _prev2High - _prev2Low;
// Small body (doji-like) for middle candle
var isSmallBody = Math.Abs(_prev1Close - _prev1Open) < prev2Body * 0.4m && prev2Range > 0;
// Bearish abandoned baby (relaxed):
// 1. First candle is bullish
// 2. Middle candle has small body near first candle high
// 3. Current candle is bearish
var firstBullish = _prev2Close > _prev2Open;
var middleNearHigh = _prev1Close >= _prev2High - prev2Range * 0.3m;
var currentBearish = close < open;
// Bullish abandoned baby (relaxed, mirror):
var firstBearish = _prev2Close < _prev2Open;
var middleNearLow = _prev1Close <= _prev2Low + prev2Range * 0.3m;
var currentBullish = close > open;
if (isSmallBody && firstBullish && middleNearHigh && currentBearish && close < ma)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (isSmallBody && firstBearish && middleNearLow && currentBullish && close > ma)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
// Shift candle history
_prev2Open = _prev1Open;
_prev2Close = _prev1Close;
_prev2High = _prev1High;
_prev2Low = _prev1Low;
_prev1Open = open;
_prev1Close = close;
_prev1High = high;
_prev1Low = low;
_prevMa = ma;
}
}
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 bearish_abandoned_baby_strategy(Strategy):
"""
Strategy based on Bearish Abandoned Baby candlestick pattern.
Detects a bullish candle followed by a small-body candle near highs,
then a bearish confirmation candle. Uses SMA for trend filter.
Also detects the bullish mirror pattern for long entries.
"""
def __init__(self):
super(bearish_abandoned_baby_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._ma_period = self.Param("MaPeriod", 20).SetDisplay("MA Period", "SMA period for exit", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 400).SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._prev2_open = 0.0
self._prev2_close = 0.0
self._prev2_high = 0.0
self._prev2_low = 0.0
self._prev1_open = 0.0
self._prev1_close = 0.0
self._prev1_high = 0.0
self._prev1_low = 0.0
self._prev_ma = 0.0
self._candle_count = 0
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(bearish_abandoned_baby_strategy, self).OnReseted()
self._prev2_open = 0.0
self._prev2_close = 0.0
self._prev2_high = 0.0
self._prev2_low = 0.0
self._prev1_open = 0.0
self._prev1_close = 0.0
self._prev1_high = 0.0
self._prev1_low = 0.0
self._prev_ma = 0.0
self._candle_count = 0
self._cooldown = 0
def OnStarted2(self, time):
super(bearish_abandoned_baby_strategy, self).OnStarted2(time)
self._prev2_open = 0.0
self._prev2_close = 0.0
self._prev2_high = 0.0
self._prev2_low = 0.0
self._prev1_open = 0.0
self._prev1_close = 0.0
self._prev1_high = 0.0
self._prev1_low = 0.0
self._prev_ma = 0.0
self._candle_count = 0
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, ma_val):
if candle.State != CandleStates.Finished:
return
self._candle_count += 1
close = float(candle.ClosePrice)
opn = float(candle.OpenPrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
ma = float(ma_val)
cd = self._cooldown_bars.Value
if self._cooldown > 0:
self._cooldown -= 1
self._prev2_open = self._prev1_open
self._prev2_close = self._prev1_close
self._prev2_high = self._prev1_high
self._prev2_low = self._prev1_low
self._prev1_open = opn
self._prev1_close = close
self._prev1_high = high
self._prev1_low = low
self._prev_ma = ma
return
# Exit logic: MA cross
if self.Position > 0 and close < ma and self._prev_ma > 0 and self._prev1_close >= self._prev_ma:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and close > ma and self._prev_ma > 0 and self._prev1_close <= self._prev_ma:
self.BuyMarket()
self._cooldown = cd
# Entry logic
if self.Position == 0 and self._candle_count >= 3 and self._prev2_close != 0:
prev2_body = abs(self._prev2_close - self._prev2_open)
prev2_range = self._prev2_high - self._prev2_low
# Small body (doji-like) for middle candle
is_small_body = abs(self._prev1_close - self._prev1_open) < prev2_body * 0.4 and prev2_range > 0
# Bearish abandoned baby (relaxed)
first_bullish = self._prev2_close > self._prev2_open
middle_near_high = self._prev1_close >= self._prev2_high - prev2_range * 0.3
current_bearish = close < opn
# Bullish abandoned baby (relaxed, mirror)
first_bearish = self._prev2_close < self._prev2_open
middle_near_low = self._prev1_close <= self._prev2_low + prev2_range * 0.3
current_bullish = close > opn
if is_small_body and first_bullish and middle_near_high and current_bearish and close < ma:
self.SellMarket()
self._cooldown = cd
elif is_small_body and first_bearish and middle_near_low and current_bullish and close > ma:
self.BuyMarket()
self._cooldown = cd
# Shift candle history
self._prev2_open = self._prev1_open
self._prev2_close = self._prev1_close
self._prev2_high = self._prev1_high
self._prev2_low = self._prev1_low
self._prev1_open = opn
self._prev1_close = close
self._prev1_high = high
self._prev1_low = low
self._prev_ma = ma
def CreateClone(self):
return bearish_abandoned_baby_strategy()