Открыть на GitHub

Стратегия AMA Trader v2.1

Стратегия AMA Trader v2.1 представляет собой перенос эксперта MetaTrader 4 AMA_TRADER_v2_1.mq4. Она объединяет импульсные скачки адаптивной средней Кауфмана (Kaufman AMA), двойное сглаживание свечей Heiken Ashi и фильтр RSI.

Основная логика

  1. Адаптивный тренд-фильтр – собственная реализация AMA повторяет оригинальный индикатор, включая быстрый/медленный коэффициенты, отношение эффективности и показатель AmaPower. Когда значение AMA увеличивается или уменьшается более чем на AmaThreshold ценовых шагов по сравнению с предыдущей свечой, формируется импульсный сигнал.
  2. Подтверждение Heiken Ashi – цены OHLC сначала сглаживаются выбранным типом скользящей средней, затем рассчитанные буферы Heiken Ashi проходят второе сглаживание. Бычья (close ≥ open) свеча разрешает покупки, медвежья – продажи.
  3. RSI-контроль – классический RSI с настраиваемым периодом. Для лонга требуется откат RSI вниз при значении не выше 70, для шорта – рост RSI при значении не ниже 30.
  4. Управление позицией – одновременно держится только одно направление. Доступны стоп-лосс/тейк-профит в ценовых шагах, трейлинг-стоп и частичное закрытие позиции при пробое RSI уровней 70/30 с последующим полным выходом.

Параметры

Название Значение по умолчанию Описание
CandleType 15 минут Таймфрейм расчёта.
TradeVolume 0.1 Базовый объём рыночного ордера.
AmaLength 9 Длина расчёта AMA.
AmaFastPeriod 2 Быстрая константа сглаживания AMA.
AmaSlowPeriod 30 Медленная константа сглаживания AMA.
AmaPower 2 Показатель степени, аналог параметра G в MQ4.
AmaThreshold 2 шага Минимальный скачок AMA (в шагах цены) для формирования сигнала.
FirstMaMethod Smoothed Тип первой скользящей средней для сглаживания исходных цен.
FirstMaPeriod 6 Период первого сглаживания.
SecondMaMethod LinearWeighted Тип второй скользящей средней для буферов Heiken Ashi.
SecondMaPeriod 2 Период второго сглаживания.
RsiPeriod 14 Период RSI.
PartialClosePercent 70% Доля позиции для частичного закрытия при экстремумах RSI (0 выключает).
StopLossSteps 50 Стоп-лосс в шагах цены (0 выключает).
TakeProfitSteps 100 Тейк-профит в шагах цены (0 выключает).
TrailingSteps 30 Трейлинг-стоп в шагах цены (0 выключает).

Правила торговли

  • Вход в лонг – AMA растёт более чем на AmaThreshold, сглаженная свеча Heiken Ashi бычья, RSI ≤ 70 и снижается относительно предыдущего значения.
  • Вход в шорт – AMA падает ниже -AmaThreshold, свеча Heiken Ashi медвежья, RSI ≥ 30 и растёт относительно предыдущего значения.
  • Частичное закрытие – при включённом параметре закрывается PartialClosePercent позиции, когда RSI пробивает уровень 70 (для лонга) или 30 (для шорта).
  • Полный выход – оставшаяся позиция закрывается при обратном пробое уровней RSI, срабатывании стоп-лосса/тейк-профита или трейлинг-стопа.

Реализация использует высокоуровневый API StockSharp: подписка на свечи обновляет пользовательский калькулятор AMA, цепочку сглаживания Heiken Ashi и индикатор RSI. Все комментарии в исходном коде оставлены на английском языке согласно требованиям конвертации.

using System;

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

namespace StockSharp.Samples.Strategies;

public class AmaTraderV21Strategy : 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 AmaTraderV21Strategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 10).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 30).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	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 (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }

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

		if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _cooldown = 140; }
		else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _cooldown = 140; }
		_prevFast = fast; _prevSlow = slow;
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
		_cooldown = 0;
	}
}