Открыть на GitHub

Стратегия Pinbar Reversal

Конвертация из исходного советника MQL PINBAR.mq4 (каталог MQL/22269). Стратегия ищет разворотные свечи типа «пин-бар» на основном таймфрейме и подтверждает их сигналами старшего таймфрейма по индикаторам Momentum и MACD. Реализация выполнена на высокоуровневом API StockSharp.

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

  • Основной таймфрейм – настраиваемый тип свечей, на котором ищутся паттерны price action.
  • Старший таймфрейм – настраиваемые свечи для фильтров Momentum и MACD.
  • Распознавание пин-баров – тело свечи должно быть небольшим относительно полного диапазона, а одна из тенью должна занимать большую часть диапазона (параметры задаются).
  • Трендовый фильтр – быстрая EMA должна находиться выше (либо ниже) медленной EMA для подтверждения длинных (либо коротких) сигналов, что повторяет LWMA-фильтр оригинала.
  • Фильтр Momentum – значение индикатора Momentum на старшем таймфрейме (или одно из двух предыдущих значений) должно превышать порог по модулю в нужную сторону.
  • Фильтр MACD – значение MACD должно быть выше сигнальной линии для покупок и ниже сигнальной для продаж, что соответствует проверке MACD на месячном графике в MQL-версии.
  • Подтверждение фракталом – используется скользящее окно из пяти свечей; сделка разрешается только после формирования актуального фрактала и пока цена не пробьёт его уровень.
  • Управление позицией – реализованы процентный стоп-лосс, тейк-профит, перевод в безубыток и трейлинг-стоп. Позиция закрывается при срабатывании любого из уровней либо при появлении встречного сигнала.

Правила входа

Покупка

  1. Последняя свеча основного таймфрейма – бычий пин-бар (длинная нижняя тень, небольшое тело).
  2. Быстрая EMA выше медленной EMA.
  3. Momentum на старшем таймфрейме (текущее или одно из двух предыдущих значений) превышает заданный порог.
  4. MACD выше сигнальной линии.
  5. Есть актуальный бычий фрактал, уровень которого не пробит ценой.
  6. Позиция отсутствует либо открыта короткая (короткая позиция переворачивается).

Продажа

  1. Последняя свеча основного таймфрейма – медвежий пин-бар (длинная верхняя тень, небольшое тело).
  2. Быстрая EMA ниже медленной EMA.
  3. Momentum на старшем таймфрейме (текущее или одно из двух предыдущих значений) ниже отрицательного порога.
  4. MACD ниже сигнальной линии.
  5. Есть актуальный медвежий фрактал, уровень которого не пробит.
  6. Позиция отсутствует либо открыта длинная (позиция переворачивается).

Правила выхода

  • Стоп-лосс и тейк-профит задаются в процентах от цены входа.
  • После достижения порога перевода в безубыток стоп переносится на цену входа с дополнительным смещением.
  • После выполнения условия активации включается трейлинг-стоп на заданном расстоянии.
  • Встречный сигнал приводит к немедленному перевороту позиции.

Параметры

Имя Значение по умолчанию Описание
CandleType 15-минутные свечи Основной таймфрейм для поиска паттернов.
TrendCandleType Часовые свечи Старший таймфрейм для фильтров Momentum и MACD.
FastMaLength 6 Период быстрой EMA (аналог быстрой LWMA).
SlowMaLength 85 Период медленной EMA (аналог медленной LWMA).
MomentumLength 14 Период Momentum на старшем таймфрейме.
MomentumThreshold 0.1 Минимальное абсолютное значение Momentum для подтверждения.
MacdFastLength 12 Период быстрой EMA для MACD.
MacdSlowLength 26 Период медленной EMA для MACD.
MacdSignalLength 9 Период сигнальной EMA для MACD.
BodyToRangeRatio 0.3 Максимальная доля тела свечи от полного диапазона.
WickRatio 0.6 Минимальная доля доминирующей тени.
StopLossPercent 2 Процент стоп-лосса.
TakeProfitPercent 4 Процент тейк-профита.
BreakEvenTriggerPercent 1.5 Порог для перевода позиции в безубыток.
BreakEvenOffsetPercent 0.2 Дополнительное смещение безубыточного стопа.
TrailingActivationPercent 2.5 Порог включения трейлинг-стопа.
TrailingDistancePercent 1 Расстояние трейлинг-стопа.

Дополнительно

  • По умолчанию объём позиции равен 1; при необходимости отрегулируйте свойство Volume.
  • При пробое цены через сохранённый уровень фрактала требуются новые условия для следующей сделки.
  • Для ключевых параметров заданы диапазоны оптимизации, что упрощает тестирование и подбор настроек в StockSharp Designer.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

public class PinbarReversal2Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private decimal? _prevFast, _prevSlow;

	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 PinbarReversal2Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 6).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 25).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();
		_prevFast = null;
		_prevSlow = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = null; _prevSlow = 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()) { _prevFast = fast; _prevSlow = slow; return; }
		if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
		var prevAbove = _prevFast.Value > _prevSlow.Value;
		var currAbove = fast > slow;
		_prevFast = fast; _prevSlow = slow;
		if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
	}
}