Открыть на GitHub

Стратегия Daydream

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

Daydream — конвертация эксперта MQL4 Daydream by Cothool для StockSharp. Исходный советник торгует USD/JPY на H1: как только цена закрывается за пределами недавнего ценового канала, открывается позиция и ведётся виртуальный трал по тейк-профиту. В версии StockSharp расчёт уровней выполняет индикатор Donchian Channels, сделки отправляются методами BuyMarket / SellMarket, а сопровождение позиции выполняется внутри стратегии без выставления заявок на биржу.

Ключевые особенности:

  • В рынке находится только одна позиция; разворот происходит после закрытия свечи вне предыдущих границ канала.
  • Виртуальный тейк-профит в пунктах подтягивается вслед за ценой и закрывает сделку при достижении уровня.
  • Блокировка повторных операций внутри одной свечи — аналог переменной LastOrderTime в MQL4.

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

  1. Построить Donchian Channel по ChannelPeriod завершённым свечам и сохранить предыдущие верхнюю/нижнюю границы.
  2. Если свеча закрывается ниже прошлой нижней границы:
    • закрыть открытую короткую позицию;
    • на следующей свече открыть лонг объёмом OrderVolume и установить виртуальный тейк-профит на уровне close + TakeProfitPips * pipSize.
  3. Если свеча закрывается выше прошлой верхней границы:
    • закрыть открытую длинную позицию;
    • на следующей свече открыть шорт и выставить виртуальный тейк-профит close - TakeProfitPips * pipSize.
  4. Пока позиция активна, уровень виртуального тейк-профита подтягивается вслед за ценой. При достижении — позиция закрывается рыночным ордером.

Размер пункта вычисляется по PriceStep инструмента. Для валютных пар с иеной шаг 0.001 превращается в пункт 0.01, как в MetaTrader.

Параметры

Параметр Описание Значение по умолчанию Примечание
OrderVolume Объём каждой новой позиции. 1 Соответствует входному параметру Lots.
ChannelPeriod Количество завершённых свечей в канале Дончиана. 25 Аналог одноимённого параметра MQL.
Slippage Допустимое проскальзывание в пунктах. 3 Хранится для совместимости; рыночные заявки его не используют.
TakeProfitPips Дистанция виртуального тейк-профита в пунктах. 15 Сдвигается по мере движения цены.
CandleType Таймфрейм для расчёта Donchian Channel. 1 час Рекомендуемый период исходного советника.

Схема работы

Закрытие свечи
      │
      ├─► Обновление канала Дончиана (предыдущие границы)
      │
      ├─► Пробой вниз? ──► Закрыть шорт → готовим вход в лонг на следующей свече
      │
      ├─► Пробой вверх? ─► Закрыть лонг → готовим вход в шорт на следующей свече
      │
      └─► Трал виртуального тейк-профита по направлению позиции
              └─► Цена достигла уровня? → Закрыть позицию

Практические рекомендации

  • Запускайте стратегию на любом инструменте с поступающими свечами. Значения по умолчанию ориентированы на USD/JPY H1.
  • В стратегии всегда одна позиция. Повторные сделки внутри текущей свечи блокируются, что повторяет поведение MQL4.
  • Тейк-профит виртуальный: фактическое закрытие происходит рыночной заявкой, реальные TP заявки не выставляются.
  • Изменяйте CandleType, если нужен другой таймфрейм. Для длинных периодов требуется достаточная история для прогрева канала.

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

  • Используется стандартный индикатор DonchianChannels, вместо ручного поиска максимумов и минимумов.
  • Логика трала и блокировки действий сохранена, но исполнение осуществляется через инфраструктуру StockSharp без работы с тикетами MT4.
  • Параметр Slippage оставлен для совместимости, хотя в StockSharp рыночное исполнение работает иначе.

Состав пакета

  • CS/DaydreamStrategy.cs — реализация стратегии на C#.
  • Python-версия пока не реализована.
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>
/// Daydream strategy - Donchian channel breakout.
/// Buys when price crosses above the midpoint of the channel.
/// Sells when price crosses below the midpoint.
/// </summary>
public class DaydreamStrategy : Strategy
{
	private readonly StrategyParam<int> _channelPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevMid;
	private bool _hasPrev;

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

	public DaydreamStrategy()
	{
		_channelPeriod = Param(nameof(ChannelPeriod), 20)
			.SetDisplay("Channel Period", "Donchian channel lookback", "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(); _prevClose = 0m; _prevMid = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var highest = new Highest { Length = ChannelPeriod };
		var lowest = new Lowest { Length = ChannelPeriod };

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

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

		var close = candle.ClosePrice;
		var mid = (highest + lowest) / 2;

		if (!_hasPrev)
		{
			_prevClose = close;
			_prevMid = mid;
			_hasPrev = true;
			return;
		}

		// Cross above midpoint
		if (_prevClose <= _prevMid && close > mid && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Cross below midpoint
		else if (_prevClose >= _prevMid && close < mid && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevClose = close;
		_prevMid = mid;
	}
}