Открыть на GitHub

Стратегия Alexav D1 Profit GBPUSD

Обзор

Alexav D1 Profit GBPUSD — это дневная стратегия пробоя, конвертированная из советника MetaTrader 4 Alexav_d1_profit_gbpusd.mq4. Алгоритм работает на дневных свечах GBP/USD и оценивает завершившуюся сессию один раз в день (со вторника по пятницу). Моментум подтверждается при помощи RSI и MACD, а уровни стоп-лоссов и поэтапных тейк-профитов рассчитываются на основе ATR.

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

  1. Подготовка индикаторов
    • Две EMA одинакового периода прикладываются к максимумам и минимумам дневных свечей, формируя ориентиры для пробоя вверх и вниз.
    • RSI с периодом 10 измеряет силу импульса; экстремальные значения временно блокируют новые сделки в том же направлении.
    • MACD (5/24/14) анализирует ускорение, сравнивая два последних значения гистограммы.
    • ATR (28) задаёт единицу волатильности для расчёта стопов и целей.
  2. Фильтр по дням недели
    • Проверка условий проводится один раз для каждой завершённой дневной свечи со вторника по пятницу. Понедельник и выходные пропускаются.
  3. Условия входа в лонг
    • Предыдущая дневная свеча закрылась выше EMA по максимумам, рассчитанной два дня назад.
    • RSI предыдущей свечи выше уровня допуска (по умолчанию 60), но ниже верхнего предела (80).
    • MACD либо находился ниже нуля два дня назад, либо показал достаточное положительное ускорение относительно предыдущего значения.
    • Если открытие предыдущей свечи опускается ниже EMA по максимумам, запрет на новые покупки снимается.
  4. Условия входа в шорт
    • Зеркальные условия: используется EMA по минимумам, нижние уровни RSI (39 / 25) и аналогичный фильтр ускорения MACD.

Управление позициями

При выполнении условий стратегия открывает пакет из четырёх рыночных ордеров (каждый с объёмом Volume):

  • Стоп-лосс: единый защитный стоп на расстоянии ATR * AtrStopMultiplier (по умолчанию 1.6) от цены входа.
  • Тейк-профит: цель для i-го ордера равна AtrTargetMultiplier * (1 + i / 2) ATR, что воспроизводит уровни 1.0, 1.5, 2.0 и 2.5 ATR из оригинального советника.
  • Разрешение конфликтов: перед открытием нового пакета противоположные позиции закрываются; запуск длинного пакета сбрасывает активность короткого и наоборот.

Контроль позиций ведётся по завершённым свечам. Если минимум дня достигает стопа — соответствующий лонг закрывается по рынку; достижение цели по максимуму также фиксирует прибыль. Для шортов используется максимум дня для стопа и минимум для тейк-профита.

Параметры

Параметр Описание Значение по умолчанию
CandleType Основной ряд свечей (по умолчанию дневной). 1 день
MaPeriod Период EMA по максимумам и минимумам. 6
RsiPeriod Период RSI для фильтра импульса. 10
AtrPeriod Период ATR для расчёта стопов и целей. 28
AtrStopMultiplier Множитель ATR для стоп-лосса. 1.6
AtrTargetMultiplier Базовый множитель ATR для тейк-профитов. 1.0
RsiUpperLevel Минимальный RSI для подтверждения покупок. 60
RsiUpperLimit Верхний предел RSI, блокирующий покупки. 80
RsiLowerLevel Минимальный RSI для подтверждения продаж. 39
RsiLowerLimit Нижний предел RSI, блокирующий продажи. 25
FastMaPeriod Быстрый EMA MACD. 5
SlowMaPeriod Медленный EMA MACD. 24
SignalMaPeriod EMA сигнальной линии MACD. 14
MacdDiffBuy Минимальное ускорение MACD для покупок. 0.5
MacdDiffSell Минимальное ускорение MACD для продаж. 0.15

Перед запуском задайте свойство Volume, чтобы определить объём каждой сделки.

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

  • Перенос сохраняет ключевую особенность оригинала — единственную проверку условий в день.
  • Для корректного бэктеста используйте дневные данные GBP/USD.
  • Стопы и цели контролируются по экстремумам дневных свечей; внутридневные всплески, не отразившиеся в дневном диапазоне, останутся незамеченными.
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>
/// Alexav D1 Profit breakout strategy.
/// Buys when price breaks above EMA and RSI is rising.
/// Sells when price breaks below EMA and RSI is falling.
/// </summary>
public class AlexavD1ProfitGbpUsdBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevEma;
	private decimal _prevRsi;
	private bool _hasPrev;

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

	public AlexavD1ProfitGbpUsdBreakoutStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetDisplay("EMA Period", "EMA period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = 0m;
		_prevEma = 0m;
		_prevRsi = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, rsi, ProcessCandle)
			.Start();
	}

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevClose = close;
			_prevEma = emaValue;
			_prevRsi = rsiValue;
			_hasPrev = true;
			return;
		}

		// Breakout above EMA with rising RSI
		if (_prevClose <= _prevEma && close > emaValue && rsiValue > _prevRsi && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Breakout below EMA with falling RSI
		else if (_prevClose >= _prevEma && close < emaValue && rsiValue < _prevRsi && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevClose = close;
		_prevEma = emaValue;
		_prevRsi = rsiValue;
	}
}