Открыть на GitHub

Стратегия Donchian Channels

Эта стратегия является переносом классического советника "Donchian Channels" на высокоуровневый API StockSharp. Она сочетает прорывы по каналу Дончиана на старшем таймфрейме, фильтрацию двумя взвешенными скользящими средними, проверку импульса и трендовый фильтр MACD, дополняясь расширенным управлением риском (стоп-лосс, тейк-профит, перевод в безубыток, трейлинг и экстренный выход по просадке капитала).

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

  • Режим рынка:
    • Канал Дончиана рассчитывается на старшем таймфрейме (по умолчанию 4 часа), что позволяет выявить структуру потенциального прорыва.
    • MACD настраиваемого трендового таймфрейма (по умолчанию дневной) подтверждает направление тренда перед открытием позиции.
  • Условия входа:
    • Лонг:
      • Нижняя граница канала или медиана входит в тело предыдущей свечи старшего таймфрейма снизу, сигнализируя о попытке выхода цены вверх.
      • Две последние свечи рабочего таймфрейма формируют восходящее колено (Low[2] < High[1]).
      • Абсолютное отклонение индикатора Momentum от уровня 100 на старшем таймфрейме превышает порог покупки хотя бы в одном из трёх последних значений.
      • Быстрая LWMA не выходит выше медленной LWMA дальше заданного расстояния, чтобы избегать перекупленности.
      • Основная линия MACD выше сигнальной (при этом обе могут быть как положительными, так и отрицательными), подтверждая бычий фон.
    • Шорт: зеркальные условия для верхней границы канала, нисходящего колена, медвежьего импульса и подтверждения MACD.
    • Допускается пирамидинг — новые заявки подаются до достижения заданного лимита сделок.
  • Условия выхода:
    • Фиксированный стоп-лосс и тейк-профит в шагах цены.
    • Перевод стопа в безубыток после прохождения ценой заданной дистанции.
    • Трейлинг-стоп по экстремумам последних свечей (с запасом) либо классический вариант с триггером и шагом.
    • Стоп по эквити отслеживает просадку P&L и закрывает позицию при превышении допустимого бюджета риска.

Параметры

Группа Имя Описание
General Base Candle Рабочий таймфрейм для сигналов и контроля риска.
General Donchian Candle Старший таймфрейм для канала Дончиана и фильтра Momentum.
General Trend Candle Таймфрейм, на котором рассчитывается MACD.
General Volume Объём каждой заявки.
Indicators Donchian Length Глубина расчёта канала Дончиана.
Indicators Fast MA / Slow MA Периоды взвешенных скользящих средних на рабочем таймфрейме.
Indicators MA Distance Максимально допустимое расхождение между LWMA в шагах цены.
Indicators Momentum Period Период Momentum на старшем таймфрейме.
Filters Momentum Buy / Sell Порог отклонения Momentum от 100 для длинных/коротких сделок.
Risk Stop Loss / Take Profit Жёсткие уровни выхода относительно цены входа.
Risk Use Trailing Включение трейлинг-стопа.
Risk Trailing Trigger / Step Настройки классического трейлинга, когда режим по свечам отключён.
Risk Candle Trail / Trail Candles Использование свечных экстремумов и их количество для трейлинга.
Risk Trailing Padding Дополнительный зазор вокруг экстремумов свечей.
Risk Use BreakEven Включение перевода в безубыток.
Risk BreakEven Trigger / Offset Расстояние до безубытка и величина смещения стопа.
Risk Use Equity Stop Включение защиты по просадке капитала.
Risk Equity Risk Максимальная допустимая просадка (в валюте счёта).
Risk Max Trades Максимальное число одновременных сделок (пирамидинг).

Рекомендации по применению

  1. Таймфреймы. Подбирайте рабочий таймфрейм под свой стиль (например, 1H или 4H), а старшие таймфреймы оставляйте выше по иерархии, чтобы сохранить многотаймфреймовую фильтрацию.
  2. Пороги Momentum. В оригинальном советнике импульс измерялся относительно уровня 100. Начинайте с невысоких значений (0.3) и повышайте их, чтобы отфильтровать слабые движения во флэте.
  3. Настройки риска. Переводите значения стопов из пунктов в реальные шаги цены инструмента. Проверьте параметр Step у инструмента перед запуском.
  4. Пирамидинг. Если нужна одна позиция, установите Max Trades = 1. При тестировании пирамидинга увеличивайте значение постепенно.
  5. Стоп по эквити. Параметр Equity Risk задаёт допустимую просадку стратегии в валюте счёта. Настройте его под собственную толерантность к риску.

Тестирование

  • Стратегия работает в StockSharp Designer/Backtester только на свечных данных, без необходимости в тиковых потоках.
  • Перед тестированием убедитесь, что выбранные таймфреймы доступны у поставщика данных.
  • При оптимизации в первую очередь изменяйте длину канала Дончиана, пороги MA Distance и Momentum — они сильнее всего влияют на частоту и качество сделок.
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 DonchianChannelsStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _period;
	private decimal? _prevHigh, _prevLow;

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

	public DonchianChannelsStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_period = Param(nameof(Period), 20).SetGreaterThanZero().SetDisplay("Channel Period", "Donchian channel lookback", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHigh = null;
		_prevLow = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevHigh = null; _prevLow = null;
		var highest = new Highest { Length = Period };
		var lowest = new Lowest { Length = Period };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(highest, lowest, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal high, decimal low)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevHigh = high; _prevLow = low; return; }
		if (_prevHigh == null || _prevLow == null) { _prevHigh = high; _prevLow = low; return; }
		if (candle.ClosePrice > _prevHigh.Value && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (candle.ClosePrice < _prevLow.Value && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevHigh = high; _prevLow = low;
	}
}