Ver en GitHub

Estrategia de Tendencia FATL MACD

Esta estrategia implementa un sistema de seguimiento de tendencia basado en el indicador FATL MACD. La FATL (Fast Adaptive Trend Line) se resta del precio para producir un oscilador similar al MACD que luego se suaviza mediante una media móvil adaptativa. Los valores positivos indican impulso alcista; los valores negativos indican impulso bajista.

El algoritmo analiza la pendiente de este oscilador en cada vela completada:

  • Cuando el valor anterior es inferior al valor anterior a él, el oscilador ha girado hacia arriba. Si el valor actual sube aún más, la estrategia abre una posición larga y cierra cualquier posición corta.
  • Cuando el valor anterior es superior al valor anterior a él, el oscilador ha girado hacia abajo. Si el valor actual continúa cayendo, la estrategia abre una posición corta y cierra cualquier posición larga.

Todos los parámetros principales son configurables:

  • Fast EMA – período de la media móvil rápida del MACD (predeterminado 12).
  • Slow EMA – período de la media móvil lenta del MACD (predeterminado 26).
  • Signal EMA – período de la línea de señal del MACD (predeterminado 9).
  • Candle Type – serie de velas utilizada para el cálculo del indicador.

Las posiciones se abren con órdenes de mercado y se cierran cuando aparece una señal opuesta.

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>
/// FATL MACD trend-following strategy.
/// Opens long positions when the indicator turns upward
/// and short positions when it turns downward.
/// </summary>
public class FatlMacdStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prev1;
	private decimal _prev2;
	private bool _isInitialized;

	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public FatlMacdStrategy()
	{
		_fastLength = Param(nameof(FastLength), 12)
			.SetDisplay("Fast EMA", "Period of the fast moving average", "MACD")
			.SetGreaterThanZero();

		_slowLength = Param(nameof(SlowLength), 26)
			.SetDisplay("Slow EMA", "Period of the slow moving average", "MACD")
			.SetGreaterThanZero();

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

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prev1 = default;
		_prev2 = default;
		_isInitialized = default;
	}

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

		var macd = new MovingAverageConvergenceDivergence
		{
			ShortMa = { Length = FastLength },
			LongMa = { Length = SlowLength },
		};

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(macd, Process)
			.Start();
	}

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (!_isInitialized)
		{
			_prev2 = _prev1 = macdValue;
			_isInitialized = true;
			return;
		}

		// Indicator turned upward
		if (_prev1 < _prev2)
		{
			if (Position < 0)
				BuyMarket();

			if (macdValue > _prev1 && Position <= 0)
				BuyMarket();
		}
		// Indicator turned downward
		else if (_prev1 > _prev2)
		{
			if (Position > 0)
				SellMarket();

			if (macdValue < _prev1 && Position >= 0)
				SellMarket();
		}

		_prev2 = _prev1;
		_prev1 = macdValue;
	}
}