Ver en GitHub

Estrategia de Patrón Estrella Vespertina

La Estrella Vespertina es la imagen especular de la Estrella de la Mañana pero indica un posible techo. Comienza con una fuerte vela alcista, seguida de una pequeña vela de indecisión, y termina con una vela bajista que cierra por debajo del punto medio de la primera barra.

Las pruebas indican un rendimiento anual promedio de aproximadamente el 100%. Funciona mejor en el mercado forex.

El algoritmo observa secuencias de tres velas. Cuando se forma el patrón, entra en corto con un stop por encima del máximo de la pequeña vela central. Las posiciones salen una vez que el precio cae por debajo del mínimo de la vela de confirmación o si el stop es activado.

Dado que la configuración anticipa una reversión rápida desde condiciones de sobrecompra, las operaciones típicamente apuntan a movimientos cortos impulsados por el momentum a la baja.

Detalles

  • Criterios de entrada: Patrón de tres velas Estrella Vespertina.
  • Largo/Corto: Solo cortos.
  • Criterios de salida: Precio por debajo del mínimo de la barra de confirmación o stop-loss.
  • Stops: Sí, por encima del máximo de la vela central.
  • Valores predeterminados:
    • CandleType = 5 minute
    • StopLossPercent = 1
  • Filtros:
    • Categoría: Patrón
    • Dirección: Corto
    • 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>
/// Evening Star candle pattern strategy.
/// Evening Star: 1st bullish, 2nd small body (doji), 3rd bearish closing below midpoint of 1st.
/// Morning Star (reverse): 1st bearish, 2nd small body, 3rd bullish closing above midpoint of 1st.
/// Uses SMA for exit signals.
/// </summary>
public class EveningStarStrategy : Strategy
{
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cooldownBars;

	private ICandleMessage _bar1;
	private ICandleMessage _bar2;
	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 EveningStarStrategy()
	{
		_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();
		_bar1 = null;
		_bar2 = null;
		_cooldown = default;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_bar1 = null;
		_bar2 = null;
		_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--;
			_bar1 = _bar2;
			_bar2 = candle;
			return;
		}

		if (_bar1 != null && _bar2 != null)
		{
			var firstBody = Math.Abs(_bar1.OpenPrice - _bar1.ClosePrice);
			var secondBody = Math.Abs(_bar2.OpenPrice - _bar2.ClosePrice);
			var secondSmall = firstBody > 0 && secondBody < firstBody * 0.5m;
			var firstMid = (_bar1.HighPrice + _bar1.LowPrice) / 2;

			// Evening Star (bearish reversal) - primary
			var firstBullish = _bar1.ClosePrice > _bar1.OpenPrice;
			var thirdBearish = candle.ClosePrice < candle.OpenPrice;
			var eveningStar = firstBullish && secondSmall && thirdBearish && candle.ClosePrice < firstMid;

			// Morning Star (bullish reversal) - secondary
			var firstBearish = _bar1.ClosePrice < _bar1.OpenPrice;
			var thirdBullish = candle.ClosePrice > candle.OpenPrice;
			var morningStar = firstBearish && secondSmall && thirdBullish && candle.ClosePrice > firstMid;

			if (Position == 0 && eveningStar)
			{
				SellMarket();
				_cooldown = CooldownBars;
			}
			else if (Position == 0 && morningStar)
			{
				BuyMarket();
				_cooldown = CooldownBars;
			}
			else if (Position > 0 && candle.ClosePrice < smaValue)
			{
				SellMarket();
				_cooldown = CooldownBars;
			}
			else if (Position < 0 && candle.ClosePrice > smaValue)
			{
				BuyMarket();
				_cooldown = CooldownBars;
			}
		}

		_bar1 = _bar2;
		_bar2 = candle;
	}
}