Ver no GitHub

Estratégia de Rastreamento de Liquidez MACD

MACD Liquidity Tracker utiliza os estados de cor do MACD para gerar sinais de negociação. Quatro modos (Fast, Normal, Safe, Crossover) ajustam a sensibilidade dos sinais. Stop loss e take profit opcionais são suportados.

Detalhes

  • Dados: Velas de preço.
  • Critérios de entrada:
    • Comprado: Depende de SystemType (padrão Normal usa MACD acima da linha de sinal).
    • Vendido: Depende de SystemType (padrão Normal usa MACD abaixo da linha de sinal).
  • Critérios de saída: Sinal oposto.
  • Stops: Stop loss e take profit opcionais.
  • Valores padrão:
    • 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:
    • Categoria: Tendência
    • Direção: Comprado/Vendido
    • Indicadores: MACD
    • Stops: Sim
    • Complexidade: Básico
    • Período: Intradiário (5m)
    • Sazonalidade: Não
    • Redes neurais: Não
    • Divergência: Não
    • Nível de risco: Médio
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;
	}
}