Auf GitHub ansehen

The Alert MACD Slow strategy reproduces the MetaTrader 4 expert Alert_MACD_Slow.mq4. It watches the MACD main line and two exponential moving averages and raises textual alerts when the indicator stack signals a potential breakout. No orders are submitted — the conversion stays faithful to the original advisor, which only displayed pop-up messages.

Core Idea

  1. Subscribe to the selected candle series and feed a MACD(3, 20, 9) together with fast and slow EMAs (20 and 65 periods).
  2. Cache MACD values for the previous four completed candles to evaluate the slope transitions used by the MQL code.
  3. Store the highs and lows of the last two candles to emulate the High[1]/High[2] and Low[1]/Low[2] breakout filters.
  4. When the fast EMA stays above (or below) the slow EMA and the candle close breaks the memorised highs (or lows) while MACD turns upward (or downward) under the zero line, log the respective alert message.

Parameters

Name Default Description
MacdFastPeriod 3 Fast EMA length inside the MACD calculation.
MacdSlowPeriod 20 Slow EMA length used by the MACD.
MacdSignalPeriod 9 Signal smoothing period of the MACD.
QuickEmaPeriod 20 Period of the trend-following fast EMA (Ma_Quick).
SlowEmaPeriod 65 Period of the slow EMA trend filter (Ma_Slow).
CandleType TimeFrame(30m) Candle source passed to the indicator chain; choose a timeframe that matches your chart.

Alert Logic Details

  • MACD slope memory: The strategy shifts the previous MACD values internally instead of calling GetValue, satisfying the conversion guidelines while preserving the original comparisons (Macd_1 > Macd_2, etc.).
  • Breakout check: Closing prices above prior highs or below prior lows are treated as a proxy for the bid/ask checks from MetaTrader, which used the live quote against historical candle extremes.
  • Trend filter: The alert triggers only when the fast EMA is on the correct side of the slow EMA, matching the long/short filters in the MQL expert.
  • Logging: Alerts are sent through AddInfoLog. They include the four cached MACD values and the breakout levels to ease debugging and back-testing.
  • No trading: Because the source advisor never placed trades, the StockSharp conversion keeps the strategy flat and focuses solely on signalling.

Typical Usage

  1. Attach the strategy to a symbol, configure the candle type to the desired timeframe, and keep the default indicator periods or adjust them for experimentation.
  2. Start the strategy and wait until the MACD and EMA indicators become formed (several candles are needed because MACD requires history).
  3. Watch the journal: when a bullish setup appears you will see SET UP LONG, while bearish setups produce SET UP SHORT_VALUE. The suffix mirrors the original alert text.
  4. Use the printed diagnostics to decide whether to act manually or to chain the strategy with custom automation.

Classification

  • Category: Alerts / Trend Breakout Confirmation
  • Trading Direction: None (signal-only)
  • Execution Style: Event-driven on finished candles
  • Data Requirements: Candle series compatible with the chosen CandleType
  • Complexity: Moderate (multiple indicator filters, but straightforward state handling)
  • Risk Management: Not applicable (no positions opened)

This port keeps the alerting behaviour of the MQL expert while leveraging StockSharp subscriptions, indicator bindings, and logging utilities.

using System;

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

namespace StockSharp.Samples.Strategies;

public class AlertMacdSlowStrategy : 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;
	private int _cooldown;

	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 AlertMacdSlowStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 26).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = default;
		_prevSlow = default;
		_hasPrev = default;
		_cooldown = default;
	}

	/// <inheritdoc />
	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 (!IsFormedAndOnlineAndAllowTrading()) return;

		if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
		if (_cooldown > 0)
		{
			_cooldown--;
			_prevFast = fast;
			_prevSlow = slow;
			return;
		}

		if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
		{
			var volume = Volume + Math.Abs(Position);
			BuyMarket(volume);
			_cooldown = 2;
		}
		else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
		{
			var volume = Volume + Math.Abs(Position);
			SellMarket(volume);
			_cooldown = 2;
		}

		_prevFast = fast; _prevSlow = slow;
	}
}