Ver en GitHub

Estrategia de Seguimiento de Liquidez MACD

MACD Liquidity Tracker utiliza los estados de color del MACD para generar señales de trading. Cuatro modos (Fast, Normal, Safe, Crossover) ajustan la sensibilidad de las señales. Se admiten stop loss y take profit opcionales.

Detalles

  • Datos: Velas de precio.
  • Criterios de entrada:
    • Largo: Depende de SystemType (por defecto Normal usa MACD por encima de la señal).
    • Corto: Depende de SystemType (por defecto Normal usa MACD por debajo de la señal).
  • Criterios de salida: Señal opuesta.
  • Stops: Stop loss y take profit opcionales.
  • Valores predeterminados:
    • FastLength = 25
    • SlowLength = 60
    • SignalLength = 220
    • AllowShortTrades = false
    • SystemType = Normal
    • UseStopLoss = false
    • StopLossPercent = 3
    • UseTakeProfit = false
    • TakeProfitPercent = 6
    • StartDate = 2018-01-01
    • EndDate = 2069-12-31
    • CandleType = tf(5)
  • Filtros:
    • Categoría: Tendencia
    • Dirección: Largo/Corto
    • Indicadores: MACD
    • Stops: Sí
    • Complejidad: Básico
    • Marco temporal: Intradía (5m)
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

public class MacdLiquidityTrackerStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<int> _cooldownBars;
	private readonly StrategyParam<DataType> _candleType;

	private ExponentialMovingAverage _emaFast;
	private ExponentialMovingAverage _emaSlow;
	private decimal _prevMacd;
	private bool _initialized;
	private int _barsFromSignal;

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

	public MacdLiquidityTrackerStrategy()
	{
		_fastLength = Param(nameof(FastLength), 12).SetDisplay("Fast", "Fast EMA", "MACD");
		_slowLength = Param(nameof(SlowLength), 26).SetDisplay("Slow", "Slow EMA", "MACD");
		_cooldownBars = Param(nameof(CooldownBars), 10).SetDisplay("Cooldown", "Bars between signals", "Risk");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_emaFast = null;
		_emaSlow = null;
		_prevMacd = 0m;
		_initialized = false;
		_barsFromSignal = int.MaxValue;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevMacd = 0;
		_initialized = false;
		_barsFromSignal = int.MaxValue;

		_emaFast = new ExponentialMovingAverage { Length = FastLength };
		_emaSlow = new ExponentialMovingAverage { Length = SlowLength };

		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(_emaFast, _emaSlow, ProcessCandle).Start();

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

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

		if (fast == 0 || slow == 0)
			return;

		var isFastAbove = fast > slow;

		if (!_initialized) { _prevMacd = isFastAbove ? 1m : -1m; _initialized = true; _barsFromSignal = 0; return; }
		if (_barsFromSignal < 10000) _barsFromSignal++;

		var prevAbove = _prevMacd > 0;
		var crossUp = isFastAbove && !prevAbove;
		var crossDown = !isFastAbove && prevAbove;
		var canSignal = _barsFromSignal >= CooldownBars;

		if (canSignal && crossUp && Position <= 0)
		{
			BuyMarket();
			_barsFromSignal = 0;
		}
		else if (canSignal && crossDown && Position >= 0)
		{
			SellMarket();
			_barsFromSignal = 0;
		}

		_prevMacd = isFastAbove ? 1m : -1m;
	}
}