Открыть на GitHub

Стратегия Tokyo Session

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

Стратегия Tokyo Session переносит логику советника MetaTrader TokyoSessionEA_v2.8 в экосистему StockSharp. Она предназначена для внутридневной торговли вокруг азиатской (Токийской) сессии и строит торговый канал по опорной свече в указанный час. После формирования канала стратегия проверяет условия пробоя или возврата в другом часе и в зависимости от режима (ContraryTrend или AccordingTrend) открывает позицию против всплеска цены или по направлению пробоя.

В портированной версии используются только высокоуровневые возможности StockSharp. Сигналы рассчитываются внутри подписки на свечи, стопы и трейлинг управляются через StartProtection, а все действия сопровождаются сообщениями LogInfo, что упрощает анализ как в тестере, так и на реальном рынке.

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

  1. Опорная свеча. В момент TimeSetLevels (час брокера) фиксируются максимум, минимум и цена закрытия свечи. Полученный диапазон служит каналом для последующих проверок, а внутренние флаги валидности сбрасываются.
  2. Проверка канала. Каждая завершённая свеча между часами TimeSetLevels и TimeCheckLevels может отменить сигнал:
    • CheckAllBars требует, чтобы закрытие свечей оставалось внутри канала.
    • ReCheckPrices в момент TimeRecheckPrices сравнивает закрытие со скользящей средней по закрытиям, контролируя импульс.
  3. Условия входа. Когда закрывается свеча, предшествующая часу TimeCheckLevels, её цена закрытия сравнивается с границами канала. Если цена попадает в диапазон [MinDistanceOfLevel, MaxDistanceOfLevel], открывается позиция.
  4. Выходы. Сделка может быть закрыта тремя механизмами:
    • CloseInSignal закрывает позицию при возврате цены в канал (аналогично оригинальному советнику).
    • CloseOrdersOnTime принудительно фиксирует результат в час TimeCloseOrders, исключая перенос позиций.
    • Защитные стопы, трейлинг и перевод в безубыток выполняет подсистема StartProtection.

Параметры

Общие

Параметр Описание
CandleType Тип свечей для расчётов (по умолчанию H1).
BrokerOffset Смещение времени брокера относительно GMT в часах.

Сигналы

Параметр Описание
TypeOfSignals ContraryTrend — контртрендовая торговля, AccordingTrend — по направлению пробоя.
TimeSetLevels Час фиксации опорной свечи.
TimeCheckLevels Час проверки условий входа.
TimeRecheckPrices Час дополнительной проверки импульса.
MinDistanceOfLevel Минимальное расстояние от уровня (в пунктах), допускающее вход.
MaxDistanceOfLevel Максимальное расстояние от уровня (в пунктах). Значение 0 отключает ограничение.
ReCheckPrices Включает дополнительную проверку импульса.
CheckAllBars Требует, чтобы все промежуточные свечи оставались внутри канала.

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

Параметр Описание
CloseInSignal Закрыть позицию при пересечении обратного сигнала.
CloseOrdersOnTime Закрыть позиции по времени.
TimeCloseOrders Час закрытия по времени.
UseTakeProfit, TakeProfit Фиксированный тейк-профит в пунктах.
UseStopLoss, StopLoss Фиксированный стоп-лосс в пунктах.
UseTrailingStop, TrailingStop, TrailingStep Настройки трейлинг-стопа StockSharp (в пунктах).
UseBreakEven, BreakEven, BreakEvenAfter Перевод стопа в безубыток после достижения заданной прибыли.

Торговля

Параметр Описание
Volume Базовый объём ордера. При смене направления противоположная позиция закрывается автоматически.
MaxOrders Максимальное количество объёмов Volume в одну сторону. Значение 0 снимает ограничение.

Порядок использования

  1. Выберите инструмент с корректным шагом цены (Security.PriceStep).
  2. Настройте таймфрейм и смещение времени, чтобы синхронизировать расписание с торговой сессией.
  3. Подберите дистанции и фильтры в соответствии с требованиями рынка или параметрами оригинального советника.
  4. Задайте параметры управления риском. Защитные ордера обслуживает StartProtection.
  5. Запустите стратегию и отслеживайте сообщения LogInfo, фиксирующие захват уровней и сделки.

Отличия от версии MetaTrader

  • Не реализован режим «плавающего» входа (UseFloatingPoint и PipsFloatingPoint), так как в StockSharp сигналы исполняются немедленно рыночными ордерами.
  • Фильтр по спреду и проскальзыванию опущен: высокоуровневые подписки на свечи не содержат поток котировок Bid/Ask.
  • Автоматическое управление объёмом (AutoLotSize, RiskFactor, восстановление лота и пресеты по инструментам) заменено на параметры Volume и MaxOrders. Размер позиции следует задавать напрямую в настройках стратегии.
  • Звуковые и текстовые уведомления заменены на стандартные логи LogInfo.

Все остальные проверки уровней, условия входа и алгоритмы выхода соответствуют оригинальному алгоритму.

Дополнительные замечания

  • Конфигурация по умолчанию рассчитана на таймфрейм H1. Для других таймфреймов важно, чтобы их длительность делила час без остатка.
  • Отсутствие свечей или разрывы в данных могут нарушить расчёт среднего значения и привести к отмене сигнала.
  • Стратегия закрывает позиции рыночными ордерами; если брокер требует лимитных заявок или накладывает ограничения по времени удержания, может потребоваться дополнительная адаптация.
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

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

/// <summary>
/// Tokyo Session strategy: breakout from session range.
/// Tracks high/low during first hours, then buys breakout above high, sells below low.
/// </summary>
public class TokyoSessionStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _atrPeriod;

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

	public int AtrPeriod
	{
		get => _atrPeriod.Value;
		set => _atrPeriod.Value = value;
	}

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

		_atrPeriod = Param(nameof(AtrPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("ATR Period", "ATR period for volatility filter", "Indicators");
	}

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

		var atr = new AverageTrueRange { Length = AtrPeriod };

		var sessionHigh = decimal.MinValue;
		var sessionLow = decimal.MaxValue;
		var candleCount = 0;
		var rangeSet = false;
		decimal? prevClose = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(atr, (candle, atrVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				candleCount++;

				// Build range from first 4 candles (2 hours of 30min candles)
				if (candleCount <= 4)
				{
					if (candle.HighPrice > sessionHigh)
						sessionHigh = candle.HighPrice;
					if (candle.LowPrice < sessionLow)
						sessionLow = candle.LowPrice;

					if (candleCount == 4)
						rangeSet = true;

					prevClose = candle.ClosePrice;
					return;
				}

				if (!rangeSet)
				{
					prevClose = candle.ClosePrice;
					return;
				}

				// Reset range every 48 candles (24 hours of 30min candles)
				if (candleCount % 48 == 0)
				{
					sessionHigh = candle.HighPrice;
					sessionLow = candle.LowPrice;
					rangeSet = false;
					candleCount = 0;
					prevClose = candle.ClosePrice;
					return;
				}

				var close = candle.ClosePrice;

				if (prevClose.HasValue)
				{
					var crossAboveHigh = prevClose.Value <= sessionHigh && close > sessionHigh;
					var crossBelowLow = prevClose.Value >= sessionLow && close < sessionLow;

					if (crossAboveHigh && Position <= 0)
						BuyMarket();
					else if (crossBelowLow && Position >= 0)
						SellMarket();
				}

				prevClose = close;
			})
			.Start();

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