Открыть на GitHub

Стратегия E-Friday Session

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

Стратегия E-Friday повторяет классического эксперта MetaTrader, который торгует только по пятницам. Алгоритм анализирует предыдущую дневную свечу и в заданный час пятницы открывает позицию. Направление противоположно движению предыдущего дня: если свеча была медвежьей (закрылась ниже открытия) — совершается покупка, если свеча бычья — совершается продажа. Позиция ведётся внутри дня: её можно закрывать автоматически в заданный час либо по защитным ордерам.

Правила торговли

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

Особенности реализации

  • Используется высокоуровневый API StockSharp: отдельные подписки на дневные и внутридневные свечи.
  • Параметры риска в «пунктах» из MQL переводятся в абсолютные ценовые смещения с учётом минимального шага цены инструмента.
  • Трейлинг-стоп ведётся в коде: на каждой завершённой свече проверяются экстремумы и при необходимости позиция закрывается рыночной заявкой.
  • Ведётся учёт состояния, чтобы по пятницам открывалась не более одной позиции.
  • Поддерживаются длинные и короткие позиции; как и в оригинале, стратегия рассчитана на один инструмент на экземпляр.

Параметры

Имя Описание Значение по умолчанию
Volume Объём сделки в лотах/контрактах. 0.1
StopLossPoints Дистанция стоп-лосса в шагах цены (0 отключает). 75
TakeProfitPoints Дистанция тейк-профита в шагах цены (0 отключает). 0
HourOpen Час (0-23), когда открывается позиция. 7
UseClosePositions Закрывать ли позицию после заданного часа. true
HourClose Час (0-23), после которого позиция закрывается. 19
UseTrailing Включить управление трейлинг-стопом. true
ProfitTrailing Требовать превышения прибыли над дистанцией трейлинга перед его активацией. true
TrailingStopPoints Дистанция трейлинг-стопа в шагах цены. 60
TrailingStepPoints Дополнительные шаги перед очередным подтягиванием стопа. 5
IntradayCandleType Тип свечей для внутридневного тайминга (по умолчанию 1 минута). TimeSpan.FromMinutes(1)
DailyCandleType Тип свечей для анализа предыдущего дня (по умолчанию 1 день). TimeSpan.FromDays(1)

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

  • Убедитесь, что торговая сессия инструмента позволяет открыть сделку в выбранный час пятницы.
  • Значения стопов и трейлинга задавайте в «пунктах» исходя из минимального шага цены, чтобы максимально приблизиться к поведению MetaTrader.
  • Стратегия рассчитана на одну сделку в пятницу. Для торговли несколькими инструментами запустите отдельные экземпляры стратегии.

Отличия от оригинального эксперта

  • Решения принимаются по завершённым свечам, тогда как оригинал проверял условия на каждом тике.
  • Защитные ордера исполняются рыночными заявками при достижении уровней внутри свечи, поэтому возможны небольшие расхождения во времени выхода.
  • Все параметры оформлены через систему StrategyParam, что позволяет использовать оптимизацию и интеграцию с UI StockSharp.
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>
/// E-Friday Session strategy - candle body direction with EMA filter.
/// Buys when previous candle was bearish and current closes above EMA (reversal).
/// Sells when previous candle was bullish and current closes below EMA (reversal).
/// </summary>
public class EFridaySessionStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevOpen;
	private decimal _prevClose;
	private bool _hasPrev;

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

	public EFridaySessionStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetDisplay("EMA Period", "EMA trend filter", "Indicators");

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

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevOpen = 0m; _prevClose = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

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

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevOpen = candle.OpenPrice;
			_prevClose = close;
			_hasPrev = true;
			return;
		}

		var prevBearish = _prevClose < _prevOpen;
		var prevBullish = _prevClose > _prevOpen;

		// Previous bearish + close above EMA = buy reversal
		if (prevBearish && close > ema && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Previous bullish + close below EMA = sell reversal
		else if (prevBullish && close < ema && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevOpen = candle.OpenPrice;
		_prevClose = close;
	}
}