Открыть на GitHub

Стратегия Smart AC Trader

Обзор

Smart AC Trader переносит одноимённого эксперта MetaTrader в экосистему StockSharp. В исходном советнике рассчитывалась относительная сила валют в каждой паре и открывались сделки, когда базовая валюта становилась сильнее котируемой. В StockSharp мы сохраняем идею торговли по силе, но применяем её к одному инструменту, используя комбинацию экспоненциальных скользящих средних (EMA) и индикатора скорости изменения (ROC):

  • Быстрая EMA отражает краткосрочное направление.
  • Медленная EMA показывает основную тенденцию.
  • ROC подтверждает наличие импульса в сторону тренда, прежде чем стратегия разрешит вход.

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

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

  1. Подписка на выбранный тип свечей и расчёт быстрой EMA, медленной EMA и ROC по закрытию свечи.
  2. Открытие длинной позиции, когда быстрая EMA находится выше медленной и значение ROC не ниже порога для покупок. При наличии короткой позиции она закрывается перед разворотом.
  3. Открытие короткой позиции, когда быстрая EMA находится ниже медленной и значение ROC не выше отрицательного порога для продаж. При наличии длинной позиции она закрывается перед разворотом.
  4. Управление открытой позицией на каждой завершённой свече:
    • Закрытие по тейк-профиту или стоп-лоссу, выраженным в шагах цены.
    • При необходимости перевод в безубыток: после достижения заданной прибыли стратегия запоминает смещённый уровень и закрывает позицию при возврате цены.
    • При необходимости использование трейлинг-стопа с заданной дистанцией от максимума (для лонга) или минимума (для шорта), достигнутых после входа.

Параметры

Параметр Описание
Fast EMA Период быстрой EMA.
Slow EMA Период медленной EMA.
ROC Period Длина окна для индикатора ROC.
Buy Momentum Минимальное положительное значение ROC для открытия лонга.
Sell Momentum Минимальное отрицательное значение ROC (по модулю) для открытия шорта.
Stop Loss Дистанция стоп-лосса в шагах цены.
Take Profit Дистанция тейк-профита в шагах цены.
Use Trailing Включение трейлинг-стопа.
Trailing Дистанция трейлинг-стопа в шагах цены.
Use Break Even Включение перевода в безубыток.
Break Even Trigger Прибыль в шагах цены, необходимая для активации безубытка.
Break Even Offset Смещение, сохраняемое после активации безубытка.
Candle Type Тип свечей, используемых в расчётах.

Примечания

  • При запуске вызывается Strategy.StartProtection(), что соответствует требованиям проекта по защите позиций.
  • Размер позиции определяется через свойство Strategy.Volume. При смене направления учитывается текущая позиция, поэтому противоположные сигналы закрывают старую сделку и открывают новую.
  • Все расстояния заданы в шагах цены — это аналог пунктов (pip) из MetaTrader. Перед использованием убедитесь, что у инструмента задан корректный PriceStep.
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

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

/// <summary>
/// Smart AC Trader: EMA trend + ROC momentum filter.
/// Buys when fast EMA above slow EMA and ROC positive.
/// Sells when fast EMA below slow EMA and ROC negative.
/// </summary>
public class SmartAcTraderStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rocPeriod;

	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 RocPeriod
	{
		get => _rocPeriod.Value;
		set => _rocPeriod.Value = value;
	}

	public SmartAcTraderStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_rocPeriod = Param(nameof(RocPeriod), 13)
			.SetGreaterThanZero()
			.SetDisplay("ROC Period", "Rate of Change period", "Indicators");
	}

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var roc = new RateOfChange { Length = RocPeriod };

		decimal? prevFast = null;
		decimal? prevSlow = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, roc, (candle, fastVal, slowVal, rocVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (prevFast.HasValue && prevSlow.HasValue)
				{
					var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
					var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;

					if (crossUp && rocVal > 0 && Position <= 0)
						BuyMarket();
					else if (crossDown && rocVal < 0 && Position >= 0)
						SellMarket();
				}

				prevFast = fastVal;
				prevSlow = slowVal;
			})
			.Start();

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