El Bebé Abandonado Alcista es un patrón raro de tres velas que presenta un doji con gap bajista seguido de un gap alcista.
Esta formación deja la vela del medio "abandonada" y a menudo precede a una fuerte reversión al alza.
Las pruebas indican un rendimiento anual promedio de aproximadamente el 76%. Funciona mejor en el mercado forex.
La estrategia compra en la apertura de la tercera vela una vez que supera con gap al doji, anticipando un fuerte seguimiento a medida que los cortos cubren sus posiciones.
Los stops se ubican justo por debajo del mínimo del doji, asegurando que las pérdidas sean pequeñas si la reversión no se sostiene.
Detalles
Criterios de entrada: coincidencia de patrón
Largo/Corto: Ambos
Criterios de salida: stop-loss o señal opuesta
Stops: Sí, basado en porcentaje
Valores predeterminados:
CandleType = 15 minute
DojiBodyPercent = 10
StopLossPercent = 2
El mercado opera las 24 horas, así que los rangos de las velas casi nunca dejan huecos (el mes de muestra no tiene ese patrón alcista); los huecos se miden entre los cuerpos de las velas. El cuerpo del doji es como mucho DojiBodyPercent de su rango. La estrategia solo compra, al cierre de la tercera vela; el stop se coloca StopLossPercent por debajo del mínimo del doji y la posición se cierra cuando una vela cierra por debajo.
Filtros:
Categoría: Patrón
Dirección: Ambos
Indicadores: Candlestick
Stops: Sí
Complejidad: Intermedio
Marco temporal: Intradía
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
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>
/// Bullish Abandoned Baby strategy.
/// While flat it buys after a bearish candle, a doji whose body gaps below the first body, and a bullish candle whose body gaps above the doji.
/// The stop lies StopLossPercent below the doji's low, and a close beyond it closes the position.
/// </summary>
public class BullishAbandonedBabyStrategy : Strategy
{
private readonly StrategyParam<decimal> _dojiBodyPercent;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private readonly List<ICandleMessage> _candles = [];
private decimal _stopPrice;
/// <summary>
/// Largest body of the doji, in percent of its range.
/// </summary>
public decimal DojiBodyPercent
{
get => _dojiBodyPercent.Value;
set => _dojiBodyPercent.Value = value;
}
/// <summary>
/// Distance of the stop beyond the pattern, in percent.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public BullishAbandonedBabyStrategy()
{
_dojiBodyPercent = Param(nameof(DojiBodyPercent), 10m)
.SetNotNegative()
.SetDisplay("Doji Body %", "Largest body of the doji, in percent of its range", "Pattern");
_stopLossPercent = Param(nameof(StopLossPercent), 2m)
.SetNotNegative()
.SetDisplay("Stop Loss %", "Distance of the stop beyond the pattern, in percent", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).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();
_candles.Clear();
_stopPrice = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candles.Clear();
_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;
_candles.Add(candle);
if (_candles.Count > 3)
_candles.RemoveAt(0);
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (Position > 0)
{
if (candle.ClosePrice <= _stopPrice)
SellMarket(Position);
return;
}
if (Position != 0 || _candles.Count < 3)
return;
var c0 = _candles[0];
var c1 = _candles[1];
var c2 = _candles[2];
if (!(c0.ClosePrice < c0.OpenPrice && Math.Abs(c1.ClosePrice - c1.OpenPrice) <= (c1.HighPrice - c1.LowPrice) * DojiBodyPercent / 100m && Math.Max(c1.OpenPrice, c1.ClosePrice) < Math.Min(c0.OpenPrice, c0.ClosePrice) && c2.ClosePrice > c2.OpenPrice && Math.Min(c2.OpenPrice, c2.ClosePrice) > Math.Max(c1.OpenPrice, c1.ClosePrice)))
return;
BuyMarket(Volume);
_stopPrice = c1.LowPrice * (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, Math, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
class bullish_abandoned_baby_strategy(Strategy):
"""
Bullish Abandoned Baby strategy.
While flat it buys after a bearish candle, a doji whose body gaps below the first body, and a bullish candle whose body gaps above the doji.
The stop lies StopLossPercent below the doji's low, and a close beyond it closes the position.
"""
def __init__(self):
super(bullish_abandoned_baby_strategy, self).__init__()
self._doji_body_percent = self.Param("DojiBodyPercent", 10.0).SetNotNegative().SetDisplay("Doji Body %", "Largest body of the doji, in percent of its range", "Pattern")
self._stop_loss_percent = self.Param("StopLossPercent", 2.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(15))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._candles = []
self._stop_price = Decimal(0)
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(bullish_abandoned_baby_strategy, self).OnReseted()
self._candles = []
self._stop_price = Decimal(0)
def OnStarted2(self, time):
super(bullish_abandoned_baby_strategy, self).OnStarted2(time)
self._candles = []
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
self._candles.append(candle)
if len(self._candles) > 3:
self._candles.pop(0)
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self.Position > 0:
if candle.ClosePrice <= self._stop_price:
self.SellMarket(self.Position)
return
if self.Position != 0 or len(self._candles) < 3:
return
c0, c1, c2 = self._candles
if not (c0.ClosePrice < c0.OpenPrice and Math.Abs(c1.ClosePrice - c1.OpenPrice) <= (c1.HighPrice - c1.LowPrice) * Decimal(self._doji_body_percent.Value) / Decimal(100) and Math.Max(c1.OpenPrice, c1.ClosePrice) < Math.Min(c0.OpenPrice, c0.ClosePrice) and c2.ClosePrice > c2.OpenPrice and Math.Min(c2.OpenPrice, c2.ClosePrice) > Math.Max(c1.OpenPrice, c1.ClosePrice)):
return
self.BuyMarket(self.Volume)
self._stop_price = c1.LowPrice * (Decimal(1) - Decimal(self._stop_loss_percent.Value) / Decimal(100))
def CreateClone(self):
return bullish_abandoned_baby_strategy()