Открыть на GitHub

Bread and Butter 2 (ADX + AMA)

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

Стратегия является переносом эксперта MetaTrader 5 Breadandbutter2, созданного Роном Томпсоном. Алгоритм анализирует только закрытые свечи: сравнивает два последних значения индикатора Average Directional Index (ADX) и направление адаптивной скользящей Kaufman Adaptive Moving Average (KAMA/AMA). При ослаблении трендовой силы (ADX снижается) и одновременном росте AMA открывается длинная позиция; при усилении тренда и падении AMA открывается короткая позиция. Реализация на StockSharp закрывает встречные позиции перед разворотом и использует те же фиксированные стоп-лосс и тейк-профит, заданные в пипсах в оригинальном советнике.

Используемые индикаторы

  • Average Directional Index (ADX) — измеряет силу тренда. Стратегия использует основную линию и сравнивает текущее и предыдущее значение.
  • Kaufman Adaptive Moving Average (KAMA/AMA) — адаптивная скользящая, настраиваемая быстрым и медленным сглаживанием. Два последних значения показывают изменение импульса цены.

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

  1. Подписаться на заданный тип свечей (по умолчанию — часовые) и обрабатывать данные только после их завершения.
  2. Рассчитать KAMA с заданными длиной, быстрым и медленным периодами.
  3. Рассчитать ADX с указанным периодом и получить значение основной линии.
  4. Сравнить текущие и предыдущие значения индикаторов:
    • Сигнал на покупку — ADX уменьшается, AMA растёт.
    • Сигнал на продажу — ADX увеличивается, AMA падает.
  5. При появлении сигнала закрыть позицию противоположного направления и открыть рыночный ордер, чтобы итоговая позиция соответствовала параметру Volume.
  6. В течение сделки следить за ценой: при достижении уровней стоп-лосса или тейк-профита (пересчитанных из пипсов в абсолютное значение через PriceStep) позиция закрывается.

Управление рисками

  • Стоп-лосс задаётся в пипсах и пересчитывается в цену с учётом минимального шага. Для инструментов с 3 или 5 знаками после запятой один pip равен 10 шагам, как в MetaTrader.
  • Тейк-профит вычисляется аналогично стоп-лоссу.
  • Входы и выходы выполняются рыночными ордерами, развороты сопровождаются закрытием текущей позиции и открытием новой в противоположном направлении.

Параметры

Имя Значение по умолчанию Описание
CandleType TimeSpan.FromHours(1).TimeFrame() Тип свечей для расчётов.
AdxPeriod 14 Период сглаживания ADX.
AmaPeriod 9 Основной период KAMA.
AmaFastPeriod 2 Быстрый период EMA внутри KAMA.
AmaSlowPeriod 30 Медленный период EMA внутри KAMA.
StopLossPips 50 Расстояние до стоп-лосса в пипсах (0 — отключить).
TakeProfitPips 50 Расстояние до тейк-профита в пипсах (0 — отключить).

Практические рекомендации

  • Убедитесь, что выбранный инструмент содержит корректный PriceStep, иначе перевод пипсов в цену будет некорректным.
  • Параметр Volume задаёт базовый объём. При смене сигнала алгоритм добавляет объём, чтобы закрыть противоположную позицию и открыть новую с величиной Volume.
  • Проверка стопов и целей выполняется по максимуму/минимуму свечи, поэтому результат повторяет логику заявок, выставленных терминалом MetaTrader.

Ссылки

  • Оригинальный советник: MQL/22003/Breadandbutter2.mq5
  • Используемые индикаторы StockSharp: KaufmanAdaptiveMovingAverage, AverageDirectionalIndex
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>
/// Bread and Butter 2 ADX AMA strategy. Uses KAMA direction with ADX filter.
/// </summary>
public class Breadandbutter2AdxAmaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _kamaPeriod;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private decimal? _prevKama;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int KamaPeriod { get => _kamaPeriod.Value; set => _kamaPeriod.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }

	public Breadandbutter2AdxAmaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_kamaPeriod = Param(nameof(KamaPeriod), 10).SetGreaterThanZero().SetDisplay("KAMA Period", "KAMA lookback", "Indicators");
		_fastPeriod = Param(nameof(FastPeriod), 8).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 21).SetGreaterThanZero().SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
	}

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

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevKama = null;
		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevKama = fast; return; }
		if (_prevKama == null) { _prevKama = fast; return; }
		var prevAbove = _prevKama.Value > slow;
		var currAbove = fast > slow;
		_prevKama = fast;
		if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
	}
}