Ver en GitHub

Estrategia estrella de la mañana/tarde CCI

Descripción general

Esta estrategia replica el MetaTrader 5 Asesor Experto Expert_AMS_ES_CCI usando la API de alto nivel de StockSharp. Busca patrones de reversión de tres velas Morning Star y Evening Star y requiere confirmación del Commodity Channel Index (CCI) antes de abrir nuevas posiciones. La lógica funciona solo con velas terminadas y opera con el valor principal especificado en la configuración de la estrategia.

Lógica de trading

  • Entrada larga de Morning Star
    • Detecta tres velas consecutivas que forman un patrón de Estrella de la Mañana:
      • Vela 1: cuerpo bajista fuerte (tamaño del cuerpo mayor que el cuerpo promedio en la ventana seleccionada).
      • Vela 2: vela de cuerpo pequeño con un gap más bajo que la vela 1.
      • Vela 3: cierra por encima del punto medio de la Vela 1.
    • Confirme que el valor CCI en la barra de señal sea menor que el umbral de entrada negativo (predeterminado −50).
  • Entrada corta de Evening Star
    • Detectar un patrón de Estrella Vespertina válido:
      • Vela 1: fuerte cuerpo alcista.
      • Vela 2: vela de cuerpo pequeño que se abre por encima de la Vela 1.
      • Vela 3: cierra por debajo del punto medio de la Vela 1.
    • Confirme que el valor CCI en la barra de señal sea mayor que el umbral de entrada positivo (predeterminado +50).
  • Reglas de salida de posición
    • Cierre las posiciones cortas cuando CCI vuelva a cruzar por encima de −NeutralThreshold o caiga por debajo de +NeutralThreshold (predeterminado ±80).
    • Cierre las posiciones largas cuando CCI vuelva a cruzar por debajo de +NeutralThreshold o caiga por debajo de −NeutralThreshold.
    • No se incluyen reglas adicionales de limitación de pérdidas o toma de ganancias; los usuarios pueden agregar protecciones externas si es necesario.

Indicadores

  • Índice de canales de productos básicos (CCI): filtro de confirmación, período predeterminado 25.
  • Promedio móvil simple de cuerpos de velas: calcula el tamaño promedio del cuerpo durante las últimas velas BodyAveragePeriod (predeterminado 5) para validar la fuerza del patrón.

Parámetros

Nombre Descripción Predeterminado Notas
CciPeriod Número de barras utilizadas en el cálculo CCI. 25 Optimizable.
BodyAveragePeriod Número de velas utilizadas para medir el tamaño corporal promedio. 5 Optimizable.
EntryThreshold Valor absoluto de CCI requerido para nuevas operaciones. 50 Valor positivo; la estrategia comprueba ±EntryThreshold.
NeutralThreshold Nivel absoluto CCI que define la zona de salida. 80 Valor positivo; la estrategia comprueba ±NeutralThreshold.
CandleType Tipo de vela (período de tiempo) utilizado para el análisis. plazo de 1 hora Cambie para que coincida con la resolución deseada.

Notas

  • La estrategia se suscribe a actualizaciones de velas a través de SubscribeCandles y utiliza Bind para recibir valores del indicador.
  • Las operaciones se ejecutan con órdenes de mercado usando BuyMarket y SellMarket.
  • Todos los comentarios en el código están escritos en inglés según sea necesario.
  • Para ampliar la gestión de riesgos, combine la estrategia con StartProtection o módulos personalizados de gestión de dinero.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Morning/Evening Star + CCI strategy.
/// Buys on morning star with negative CCI, sells on evening star with positive CCI.
/// </summary>
public class MorningEveningStarCciStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _cciLevel;

	private ICandleMessage _prevCandle;
	private ICandleMessage _prevPrevCandle;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	public decimal CciLevel { get => _cciLevel.Value; set => _cciLevel.Value = value; }

	public MorningEveningStarCciStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("CCI Period", "CCI period", "Indicators");
		_cciLevel = Param(nameof(CciLevel), 0m)
			.SetDisplay("CCI Level", "CCI threshold for confirmation", "Signals");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevCandle = null;
		_prevPrevCandle = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCandle = null;
		_prevPrevCandle = null;
		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(cci, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal cciValue)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_prevCandle != null && _prevPrevCandle != null)
		{
			var prevBody = Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice);
			var prevRange = _prevCandle.HighPrice - _prevCandle.LowPrice;
			var isSmallBody = prevRange > 0 && prevBody < prevRange * 0.3m;

			var firstBearish = _prevPrevCandle.OpenPrice > _prevPrevCandle.ClosePrice;
			var currBullish = candle.ClosePrice > candle.OpenPrice;
			var isMorningStar = firstBearish && isSmallBody && currBullish &&
							   candle.ClosePrice > _prevPrevCandle.OpenPrice * 0.5m + _prevPrevCandle.ClosePrice * 0.5m;

			var firstBullish = _prevPrevCandle.ClosePrice > _prevPrevCandle.OpenPrice;
			var currBearish = candle.OpenPrice > candle.ClosePrice;
			var isEveningStar = firstBullish && isSmallBody && currBearish &&
							   candle.ClosePrice < _prevPrevCandle.OpenPrice * 0.5m + _prevPrevCandle.ClosePrice * 0.5m;

			if (isMorningStar && cciValue < -CciLevel && Position <= 0)
				BuyMarket();
			else if (isEveningStar && cciValue > CciLevel && Position >= 0)
				SellMarket();
		}

		_prevPrevCandle = _prevCandle;
		_prevCandle = candle;
	}
}