Открыть на GitHub

Стратегия ADX & MA

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

Данная стратегия представляет собой порт эксперта MetaTrader ADX_MA (fortrader) на платформу StockSharp. Она сочетает сглаженную скользящую среднюю (SMMA) и индикатор среднего направленного движения (ADX), чтобы сделки открывались только при подтверждённом пересечении и достаточной силе тренда. Как и оригинал, порт использует несимметричное управление рисками: для покупок задан увеличенный зазор стопов и трейлинга, для продаж параметры значительно более жёсткие.

Логика работы

  1. Строится SMMA по медианной цене свечей и ADX с заданными периодами.
  2. Сигналы рассчитываются только на закрытых свечах, имитируя вызовы iClose(...,1) и iClose(...,2) в MQL4.
  3. Покупка выполняется, когда предыдущая свеча закрылась выше SMMA, свеча до неё — ниже, а ADX выше порога.
  4. Продажа выполняется, когда предыдущая свеча закрылась ниже SMMA, ещё более ранняя — выше, и ADX превышает порог.
  5. Управление позицией включает:
    • закрытие при смене направления относительно SMMA;
    • индивидуальные уровни стоп-лосса и тейк-профита в пунктах;
    • опциональный трейлинг, который подтягивается по мере движения цены в нужную сторону.

Все ценовые смещения пересчитываются из пунктов по шагу цены инструмента. Если шаг не задан, используется значение 1.

Параметры

Название Описание
SMMA Period Период сглаженной скользящей средней (по умолчанию 21).
ADX Period Период индикатора ADX (по умолчанию 14).
ADX Threshold Минимальное значение ADX для разрешения входа (по умолчанию 16).
Long Take Profit (pips) Тейк-профит для длинных позиций в пунктах (по умолчанию 1300).
Long Stop Loss (pips) Стоп-лосс для длинных позиций в пунктах (по умолчанию 30).
Long Trailing Stop (pips) Трейлинг-стоп для длинных позиций в пунктах (по умолчанию 270).
Short Take Profit (pips) Тейк-профит для коротких позиций в пунктах (по умолчанию 160).
Short Stop Loss (pips) Стоп-лосс для коротких позиций в пунктах (по умолчанию 50).
Short Trailing Stop (pips) Трейлинг-стоп для коротких позиций в пунктах (по умолчанию 20).
Volume Объём заявки при открытии новой позиции (по умолчанию 0.1).
Candle Type Тип свечей, используемых в расчётах (по умолчанию минутные).

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

Дополнительные замечания

  • Трейлинг активируется только после того, как цена пройдёт в прибыль не меньше указанного расстояния.
  • Противоположный сигнал закрывает текущую позицию перед открытием новой.
  • При наличии области графика стратегия автоматически отображает свечи, индикаторы и собственные сделки.
  • Автоматические тесты не поставляются; рекомендуется провести собственное тестирование в терминале или на истории.
using System;

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

namespace StockSharp.Samples.Strategies;

public class AdxMaStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose; private decimal _prevEma; private bool _hasPrev;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public AdxMaStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 14).SetDisplay("EMA Period", "EMA lookback", "Indicators");
		_smaPeriod = Param(nameof(SmaPeriod), 50).SetDisplay("SMA Period", "SMA trend filter", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = 0;
		_prevEma = 0;
		_hasPrev = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal ema)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		if (!_hasPrev) { _prevClose = close; _prevEma = ema; _hasPrev = true; return; }

		if (_prevClose <= _prevEma && close > ema && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (_prevClose >= _prevEma && close < ema && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); }
		_prevClose = close; _prevEma = ema;
	}
}