Ver en GitHub

EMA Estrategia cruzada 6/12

Esta estrategia replica el asesor experto MetaTrader que intercambia el cruce entre un EMA(6) rápido y un }(12) lento. Se suscribe a velas horarias de forma predeterminada, calcula ambas medias móviles y espera un cruce confirmado al cierre de una vela antes de actuar.

Lógica de trading

  • Entrada:
    • Aparece una señal alcista cuando EMA(6) cruza por encima de EMA(12). La estrategia abre una posición larga si no hay ninguna posición activa.
    • Aparece una señal bajista cuando EMA(6) cruza por debajo de EMA(12). La estrategia abre una posición corta si no hay una posición activa.
  • Salir:
    • Cuando UseCloseSignals está habilitado (comportamiento predeterminado), la estrategia cierra la posición actual una vez que se detecta un cruce opuesto. Espera el próximo cruce antes de abrir una nueva operación, reflejando al asesor experto original.
    • Las protecciones opcionales de toma de ganancias y trailing stop se administran a través del asistente integrado StartProtection de StockSharp.
  • Tamaño de posición:
    • Los pedidos utilizan el parámetro OrderVolume (1 lote predeterminado). Los volúmenes se alinean con la configuración de seguridad antes de enviar pedidos.

Gestión del riesgo

  • Parada dinámica: Convierte la configuración original de "puntos" en incrementos de precios. Cuando es mayor que cero, el stop se desplaza automáticamente en la dirección de la operación una vez que la posición se vuelve rentable.
  • Take de ganancias: Expresado en incrementos de precio. Establezca en cero para desactivar.
  • La estrategia nunca promedia hacia abajo o pirámides. Sólo se permite una posición por símbolo.

Parámetros

Parámetro Descripción
CandleType Marco de tiempo utilizado para construir velas y EMA. El valor predeterminado es 1 hora.
OrderVolume Tamaño comercial en lotes.
ShortEmaLength Periodo para la EMA rápida (por defecto 6).
LongEmaLength Período para el EMA lento (predeterminado 12).
UseCloseSignals Cierre la posición actual en un cruce opuesto (predeterminado: habilitado).
TrailingStopSteps Distancia de seguimiento en pasos de precio. Zero desactiva el seguimiento.
TakeProfitSteps Tome la distancia de beneficio en pasos de precio. Zero lo desactiva.

Notas

  • Las señales se procesan únicamente en velas terminadas para evitar el ruido dentro de la barra.
  • Los valores EMA anteriores se restablecen cada vez que la posición vuelve a cero, lo que garantiza una detección limpia para el siguiente cruce.
  • Todos los comentarios del código están escritos en inglés y la sangría utiliza tabulaciones de acuerdo con las pautas del proyecto.
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// EMA 6/12 crossover strategy.
/// Buys when EMA(6) crosses above EMA(12).
/// Sells when EMA(6) crosses below EMA(12).
/// </summary>
public class Ema612Strategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public Ema612Strategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 6)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 12)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_hasPrev = false;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}