Открыть на GitHub

Ichimoku Price Action Strategy

Обзор

Ichimoku Price Action Strategy — перенос советника “Ichimoku Price Action Strategy v1.0” из MQL4 в высокоуровневый API StockSharp. Оригинальный советник открывал рыночные сделки, когда торговля была разрешена и фильтр MACD подтверждал направление. Переносная версия повторяет эту логику и дополняет её расширенными механизмами управления риском — стоп-лоссами, тейк-профитами, переводом в безубыток и трейлингом.

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

Важно: В StockSharp стратегия работает с чистой позицией. Оригинальный режим одновременного удержания лонга и шорта не реализован. Все остальные элементы мани-менеджмента перенесены в виде пересчёта стопов и целей на каждой завершённой свече.

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

  1. Торговое окно — сделки возможны только внутри интервала [StartTime; EndTime]. Установка 00:00 для обеих границ отключает фильтр.
  2. MACD-фильтр (опционально) — при UseMacdFilter = true лонг возможен лишь при MACD выше сигнальной линии, шорт — при обратном условии.
  3. Открытие позиции — если направление разрешено и позиция отсутствует, отправляется рыночный ордер объёмом Volume.
  4. Стоп-лосс — рассчитывается по выбранному режиму: фиксированное число пунктов, ATR-множитель или ближайший экстремум с младшего таймфрейма. Более жёсткий уровень замещает старый.
  5. Тейк-профит — проверяется на каждой свече. Доступен фиксированный размер или динамическая цель по коэффициенту риск/прибыль.
  6. Безубыток и трейлинг — после достижения MoveToBreakEven стоп переносится в точку входа, а по достижении TrailingTrigger запускается трейлинг с параметрами TrailingStop и TrailingStep.
  7. Выход по развороту — если CloseOnReverse = true, появление встречного сигнала закрывает текущую позицию до возможного переворота.

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

  • Стоп-лосс
    • FixedPipsStopLossPips × PriceStep.
    • AtrMultiplier — последняя величина ATR (AtrCandleType) × AtrMultiplier.
    • SwingHighLow — ближайший экстремум, рассчитанный по SwingCandleType и SwingBars.
  • Тейк-профит
    • FixedPipsTakeProfitPips.
    • RiskReward — дистанция до стопа × TakeProfitRatio.
  • Безубыток — параметр MoveToBreakEven определяет, на сколько пунктов должна уйти цена, чтобы стоп был зафиксирован на уровне входа.
  • Трейлинг — параметры TrailingStop, TrailingTrigger, TrailingStep определяют расстояние, условие активации и шаг подтягивания.

Параметры

Группа Параметр Описание
General BuyMode Разрешить покупки.
General SellMode Разрешить продажи.
General CandleType Рабочий таймфрейм (по умолчанию 1 час).
Schedule StartTime / EndTime Торговый интервал (00:00 отключает фильтр).
Filters UseMacdFilter Включить фильтр MACD.
Filters MacdFast, MacdSlow, MacdSignal Периоды MACD.
Risk StopLossMode Режим стоп-лосса (FixedPips, AtrMultiplier, SwingHighLow).
Risk StopLossPips Размер фиксированного стопа.
Risk AtrMultiplier, AtrPeriod, AtrCandleType Настройки ATR-стопа.
Risk SwingBars, SwingCandleType Настройки стопа по экстремумам.
Risk TakeProfitMode Режим тейк-профита (FixedPips, RiskReward).
Risk TakeProfitPips, TakeProfitRatio Параметры тейк-профита.
Risk CloseOnReverse Закрывать позицию при обратном сигнале.
Orders Volume Объём рыночного ордера.
Risk MoveToBreakEven Порог перевода в безубыток (в пунктах).
Risk TrailingStop, TrailingTrigger, TrailingStep Конфигурация трейлинга.

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

  • Убедитесь, что у инструмента задан PriceStep; иначе будет использовано значение 0.0001.
  • При включении ATR- или swing-стопов необходимо наличие данных соответствующих таймфреймов.
  • Чтобы отключить перевод в безубыток или трейлинг, установите соответствующие параметры в 0.
  • Стратегия не накапливает несколько сделок в одном направлении — вход возможен только после закрытия текущей позиции.

Отличия от MQL-версии

  • Поддерживается только чистая позиция, хеджирование отсутствует.
  • Сложные режимы управления объёмом (Kelly, частичное закрытие и т. п.) не реализованы.
  • Не переносились функции панели, скриншотов и ручного подтверждения из оригинального шаблона.

Чек-лист для тестирования

  1. Настройте рабочий таймфрейм и дополнительные подписки (ATR, swing).
  2. Подберите Volume, параметры стопа и цели под свою модель.
  3. Включите или отключите MACD-фильтр согласно исходной конфигурации.
  4. Запустите тест с корректным торговым окном.
  5. Проверьте журналы, чтобы убедиться, что события стопов, тейков и трейлинга отрабатывают ожидаемо.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Ichimoku Price Action strategy: EMA trend with price action confirmation.
/// Buys on bullish candle above EMA, sells on bearish candle below EMA.
/// </summary>
public class IchimokuPriceActionStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private ICandleMessage _prevCandle;
	private int _candlesSinceTrade;

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

	public IchimokuPriceActionStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA trend filter", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCandle = null;
		_candlesSinceTrade = SignalCooldownCandles;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaValue)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (_prevCandle != null)
		{
			var prevBearish = _prevCandle.ClosePrice < _prevCandle.OpenPrice;
			var currBullish = candle.ClosePrice > candle.OpenPrice;
			var prevBullish = _prevCandle.ClosePrice > _prevCandle.OpenPrice;
			var currBearish = candle.ClosePrice < candle.OpenPrice;
			var bullishBreakout = candle.ClosePrice > _prevCandle.HighPrice;
			var bearishBreakout = candle.ClosePrice < _prevCandle.LowPrice;

			if (prevBearish && currBullish && bullishBreakout && candle.ClosePrice > emaValue && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (prevBullish && currBearish && bearishBreakout && candle.ClosePrice < emaValue && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevCandle = candle;
	}
}