Открыть на GitHub

Стратегия Tipu MACD EA

Общее описание

Стратегия является портом эксперт-советника Tipu MACD EA с MQL4 на StockSharp. Торговля ведётся по одному инструменту с использованием сигналов индикатора MACD и включает функциональность, реализованную в оригинале:

  • Фильтрация по торговым часам с двумя настраиваемыми временными окнами.
  • Входы по пересечениям MACD с нулевой линией и сигнальной линией с настройкой периодов EMA и сдвига.
  • Автоматическое сопровождение позиции: тейк-профит, стоп-лосс, трейлинг и перевод в безубыток.
  • Ограничение максимально допустимого суммарного объёма позиции («Max Lots» из исходного кода).

Все сделки выполняются рыночными ордерами. Защитные уровни рассчитываются внутри стратегии и позиция закрывается, когда очередная свеча пробивает стоп-лосс или тейк-профит.

Логика торговли

  1. Подписаться на выбранный тип свечей и рассчитывать индикатор MovingAverageConvergenceDivergenceSignal (линия MACD и сигнальная линия).
  2. Читать значения MACD с учётом сдвига (MacdShift 0 — текущая свеча, 1 — предыдущая) и формировать сигналы пересечения:
    • Пересечение нулевой линии (опционально) — покупка при переходе MACD выше нуля, продажа при переходе ниже нуля.
    • Пересечение с сигнальной линией (опционально) — покупка при пересечении MACD выше сигнальной линии, продажа при пересечении ниже неё.
  3. Перед открытием позиции убедиться, что текущий час попадает хотя бы в одно из торговых окон, если фильтр включён.
  4. При сигнале на покупку:
    • Если хеджирование запрещено и открыта короткая позиция, при включённом CloseOnReverseSignal она закрывается; иначе вход пропускается.
    • Регистрируется рыночная покупка на меньший из объёмов: TradeVolume или остаток до лимита MaxPositionVolume.
    • Фиксируется средняя цена входа по лонгу и рассчитываются защитные уровни, если они активны.
  5. При сигнале на продажу выполняются симметричные действия для шорта.
  6. Пока позиция открыта:
    • На каждой завершённой свече проверяются защитные уровни, и при их пробое позиция закрывается.
    • При включенном трейлинге и проходе цены на TrailingPips + TrailingCushionPips стоп подтягивается на расстояние TrailingPips от цены.
    • При активном переводе в безубыток и достижении прибыли RiskFreePips стоп переносится в точку входа.

Параметры

Имя Описание
CandleType Тип свечей, используемый для расчётов MACD.
TradeVolume Объём каждой рыночной заявки (в лотах).
MaxPositionVolume Максимальный суммарный объём длинной или короткой позиции.
UseTimeFilter Включение фильтра торговых часов.
Zone1StartHour, Zone1EndHour Начало и конец первого торгового окна (часы, время площадки).
Zone2StartHour, Zone2EndHour Начало и конец второго торгового окна.
FastPeriod, SlowPeriod, SignalPeriod Периоды быстрой EMA, медленной EMA и сигнальной SMA для MACD.
MacdShift 0 — анализ текущей свечи, 1 — предыдущей (аналог параметра iShift в MQL).
UseZeroCross Включение сигналов пересечения нулевой линии MACD.
UseSignalCross Включение сигналов пересечения MACD и сигнальной линии.
AllowHedging Разрешение удерживать разнонаправленные позиции без предварительного закрытия.
CloseOnReverseSignal Закрытие противоположной позиции при появлении нового сигнала (при отключённом хеджировании).
UseTakeProfit, TakeProfitPips Включение тейк-профита и его расстояние в пунктах.
UseStopLoss, StopLossPips Включение стоп-лосса и его расстояние в пунктах.
UseTrailingStop, TrailingPips, TrailingCushionPips Настройка трейлинга: расстояние и дополнительный зазор (пункты).
UseRiskFree, RiskFreePips Перенос стопа в точку входа после указанной прибыли (пункты).

Рекомендации по использованию

  • Подберите таймфрейм свечей в соответствии с периодом, на котором работал советник в MetaTrader (по умолчанию 15 минут).
  • Размер пункта берётся из Security.PriceStep. Если данные отсутствуют, используется значение 0.0001.
  • Стратегия предполагает мгновенное исполнение рыночных заявок. В реальной торговле добавьте контроль проскальзывания при необходимости.
  • Если отключить оба вида сигналов (zero-line и signal-line), стратегия не будет открывать позиции.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Tipu MACD EA strategy: MACD signal line crossover.
/// Buys when MACD crosses above signal, sells when crosses below.
/// </summary>
public class TipuMacdEaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _prevMacd;
	private decimal _prevSignal;
	private int _candlesSinceTrade;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int SignalPeriod { get => _signalPeriod.Value; set => _signalPeriod.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public TipuMacdEaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("MACD Fast", "MACD fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("MACD Slow", "MACD slow EMA period", "Indicators");
		_signalPeriod = Param(nameof(SignalPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Signal Period", "MACD signal period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevMacd = 0;
		_prevSignal = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevMacd = 0;
		_prevSignal = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd = { ShortMa = { Length = FastPeriod }, LongMa = { Length = SlowPeriod } },
			SignalMa = { Length = SignalPeriod }
		};
		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(macd, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!macdValue.IsFinal) return;

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (macdValue is not MovingAverageConvergenceDivergenceSignalValue typed) return;
		if (typed.Macd is not decimal macdMain || typed.Signal is not decimal signal) return;

		if (_hasPrev)
		{
			if (_prevMacd <= _prevSignal && macdMain > signal && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (_prevMacd >= _prevSignal && macdMain < signal && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevMacd = macdMain;
		_prevSignal = signal;
		_hasPrev = true;
	}
}