Auf GitHub ansehen

1H EUR/USD MACD Swing Strategy

This strategy ports the "1H EUR_USD" MetaTrader expert advisor into the StockSharp high-level API. It trades the EUR/USD pair on hourly candles using dual moving averages and MACD swing detection. Entries require both a trend filter (fast MA above/below slow MA) and a MACD double-bottom/double-top pattern combined with a breakout of recent highs or lows. Risk is controlled with pip-based stop loss, take profit, and an incremental trailing stop that mirrors the original EA logic.

Details

  • Market: Designed for EUR/USD on the 1-hour timeframe but can be applied to any instrument producing standard candles.
  • Entry Criteria:
    • Long:
      • Fast MA is above the slow MA (type selectable between SMA, EMA, SMMA, LWMA).
      • MACD main line forms either of the following bullish swings entirely below the zero line:
        • MACD[-1] > MACD[-2] < MACD[-3] with MACD[-2] < 0 and the current close breaks the previous candle high.
        • MACD[-2] > MACD[-3] < MACD[-4] with MACD[-3] < 0 and the current close breaks the high from two candles ago.
    • Short:
      • Fast MA is below the slow MA.
      • MACD main line forms the mirrored bearish swings entirely above the zero line and price closes below the relevant prior low.
  • Exit Criteria:
    • Pip-based take profit and stop loss are attached immediately after entry.
    • Trailing stop activates only after price moves in favor by TrailingStop + TrailingStep pips and then follows price at a distance of TrailingStop pips, matching the EA's stepwise modification logic.
    • Protective orders trigger on the candle's intraperiod high/low.
  • Position Management:
    • Uses the configured trade volume; reversing positions closes the opposite side before opening the new one.
    • Long and short trades share the same pip calculations (pip size automatically adapts to 4/5-digit quotes).
  • Indicators:
    • Fast and slow moving averages with selectable type (Simple, Exponential, Smoothed, Linear Weighted) and optional horizontal shift.
    • Classic MACD (fast/slow/signal EMA lengths).
  • Parameters:
    • TradeVolume – base lot size sent with each order.
    • StopLossPips, TakeProfitPips – protective distances in pips (set to zero to disable).
    • TrailingStopPips, TrailingStepPips – trailing configuration; trailing step must remain positive when trailing is active.
    • FastMaLength, FastMaShift, FastMaType – fast MA settings.
    • SlowMaLength, SlowMaShift, SlowMaType – slow MA settings.
    • MacdFastLength, MacdSlowLength, MacdSignalLength – MACD parameters.
    • CandleType – timeframe for processing (defaults to 1 hour).
    • LookbackPeriod – preserved for compatibility with the MQL inputs; it does not alter logic because the original EA also left it unused.

Notes

  • Trailing stop behaviour mirrors the MQL version: no adjustment occurs until both the trailing distance and trailing step are surpassed by unrealized profit.
  • The strategy assumes price step equals the quote point; if the instrument has 3 or 5 decimal digits the code automatically scales pip size by 10.
  • Comments inside the C# source explain every key block in English for easier maintenance and extension.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// 1H EUR/USD style strategy using EMA with RSI confirmation.
/// </summary>
public class OneHourEurUsdStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;

	private decimal? _prevRsi;

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

	public int EmaPeriod
	{
		get => _emaPeriod.Value;
		set => _emaPeriod.Value = value;
	}

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public OneHourEurUsdStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "Trend EMA period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevRsi = null;
	}

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

		_prevRsi = null;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, rsi, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevRsi = rsiVal;
			return;
		}

		if (_prevRsi == null)
		{
			_prevRsi = rsiVal;
			return;
		}

		var close = candle.ClosePrice;

		// Price above EMA + RSI crosses 50 up
		if (close > emaVal && _prevRsi.Value <= 50 && rsiVal > 50 && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Price below EMA + RSI crosses 50 down
		else if (close < emaVal && _prevRsi.Value >= 50 && rsiVal < 50 && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevRsi = rsiVal;
	}
}