Ver en GitHub

Estrategia de Área MACD

Descripción general

La Estrategia de Área MACD evalúa el equilibrio entre el impulso alcista y bajista usando la línea principal del MACD. Para cada vela, la estrategia acumula la suma de todos los valores positivos del MACD y la suma absoluta de todos los valores negativos del MACD durante una ventana de historial configurable. El lado dominante define la dirección de trading: un área positiva más fuerte favorece las posiciones largas, mientras que un área negativa más fuerte favorece la exposición corta. Un interruptor inverso permite operar contra la tendencia detectada cuando sea necesario.

La implementación utiliza la API de alto nivel de StockSharp con suscripciones de velas y vínculos de indicadores. Solo se procesan las velas completadas y toda la lógica de trading está encapsulada dentro del manejador ProcessCandle.

Indicadores y Datos

  • MACD (Media Móvil de Convergencia/Divergencia) con períodos rápido, lento y de señal configurables.
  • Velas de un marco temporal definido por el usuario (30 minutos por defecto).

Reglas de Trading

  1. Entrada Larga – Cuando el área positiva acumulada del MACD es mayor que el área negativa absoluta acumulada. Si el modo inverso está habilitado, la condición se invierte.
  2. Entrada Corta – Cuando el área negativa absoluta acumulada del MACD domina. El modo inverso intercambia el comportamiento.
  3. Gestión de Posición – Cuando aparece una nueva señal de entrada, la estrategia cierra cualquier posición opuesta antes de abrir la nueva para que solo se mantenga una única posición direccional.

Gestión de Riesgo

  • Stop Loss – Distancia fija en pips medida desde el precio de entrada. Convertida automáticamente a unidades de precio usando el paso de precio del instrumento.
  • Take Profit – Objetivo de ganancia fijo en pips usando las mismas reglas de conversión.
  • Trailing Stop – Stop de seguimiento opcional que se activa una vez que la posición se mueve en ganancias por TrailingStopPips + TrailingStepPips. El stop luego sigue el precio con una brecha definida por TrailingStopPips y solo se mueve hacia adelante cuando el precio avanza al menos TrailingStepPips más. Ambos valores deben ser mayores que cero para habilitar la lógica de trailing.

Parámetros

Nombre Descripción Predeterminado
OrderVolume Volumen de orden usado para entradas de mercado. 1
HistoryLength Número de velas almacenadas para la comparación de área MACD. 60
MacdFastLength Período de EMA rápida para el MACD. 12
MacdSlowLength Período de EMA lenta para el MACD. 26
MacdSignalLength Período de EMA de señal para el MACD. 9
ReverseSignals Si está habilitado, intercambia las condiciones de entrada larga y corta. false
StopLossPips Distancia de stop loss expresada en pips. 100
TakeProfitPips Distancia de take profit en pips. 150
TrailingStopPips Distancia del trailing stop en pips. Establecer en cero para deshabilitar el trailing. 5
TrailingStepPips Progreso adicional requerido antes de actualizar el trailing stop. Establecer en cero para deshabilitar el trailing. 5
CandleType Marco temporal de velas usado por la suscripción. Marco temporal de 30 minutos

Notas de Uso

  1. Adjuntar la estrategia a un portafolio y un instrumento, luego ajustar los parámetros para el mercado objetivo.
  2. Asegurarse de que tanto TrailingStopPips como TrailingStepPips sean mayores que cero para habilitar la protección de trailing. De lo contrario, el trailing se ignora y solo los niveles de stop loss/take profit están activos.
  3. Monitorear los mensajes de registro para información sobre eventos de stop-loss, take-profit y trailing. Todos los registros se producen en inglés según lo requerido.

Idea Original

La conversión se basa en el asesor experto de MetaTrader 5 "Area MACD". La versión StockSharp mantiene el concepto central de comparar áreas MACD mientras integra la gestión de riesgo y el manejo de indicadores a través de la API de alto nivel del framework.

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>
/// Area MACD strategy (simplified). Tracks cumulative positive/negative
/// areas of fast-slow EMA difference to determine trend direction.
/// </summary>
public class AreaMacdStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<int> _historyLength;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	public int HistoryLength
	{
		get => _historyLength.Value;
		set => _historyLength.Value = value;
	}

	public AreaMacdStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");

		_fastLength = Param(nameof(FastLength), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Length", "Fast EMA period", "Indicators");

		_slowLength = Param(nameof(SlowLength), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "Indicators");

		_historyLength = Param(nameof(HistoryLength), 20)
			.SetGreaterThanZero()
			.SetDisplay("History Length", "Area accumulation window", "Indicators");
	}

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

		var fastEma = new ExponentialMovingAverage { Length = FastLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowLength };

		var diffHistory = new Queue<decimal>();
		decimal posArea = 0, negArea = 0;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, (ICandleMessage candle, decimal fastValue, decimal slowValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				var diff = fastValue - slowValue;

				diffHistory.Enqueue(diff);
				if (diff > 0) posArea += diff;
				else negArea += Math.Abs(diff);

				if (diffHistory.Count > HistoryLength)
				{
					var old = diffHistory.Dequeue();
					if (old > 0) posArea -= old;
					else negArea -= Math.Abs(old);
				}

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (diffHistory.Count < HistoryLength)
					return;

				// Bullish area dominates
				if (posArea > negArea * 1.25m && Position <= 0)
					BuyMarket();
				// Bearish area dominates
				else if (negArea > posArea * 1.25m && Position >= 0)
					SellMarket();
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fastEma);
			DrawIndicator(area, slowEma);
			DrawOwnTrades(area);
		}
	}
}