Ver en GitHub

Estrategia Bebé Abandonado Alcista

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);
	}
}