Открыть на GitHub

Стратегия SilverTrend Duplex

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

SilverTrend Duplex — порт советника MetaTrader 5 Exp_SilverTrend_Duplex на платформу StockSharp. Оригинальный робот использует два независимых фильтра SilverTrend для длинных и коротких решений и открывает сделки при смене цвета индикатора. Реализация на C# сохраняет эту двухканальную архитектуру, позволяя настраивать параметры длинных и коротких сигналов по отдельности и использовать высокоуровневый API StockSharp.

Стратегия работает только по завершённым свечам. Для каждой стороны можно выбрать собственный тип данных: одинаковые таймфреймы поддерживаются, но также можно указать разные интервалы или источники данных. Внутри применяется пользовательский индикатор SilverTrendIndicator, который на основе Donchian-канала и коэффициента риска воссоздаёт логику окраски, идентичную MQL-версии.

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

  1. Пересчёт индикатора

    • Рассчитываются верхняя и нижняя границы Donchian-канала на SSP барах.
    • Пороговые уровни smin и smax вычисляются через коэффициент 33 - risk, как в исходном коде.
    • При закрытии выше smax фиксируется бычье состояние, ниже smin — медвежье, иначе сохраняется предыдущее состояние. Направление тела свечи задаёт финальный цвет (0..4).
  2. Подготовка сигналов

    • Для длинного и короткого фильтра хранится по SignalBar + 1 последних цветов.
    • Длинный сигнал формируется при цвет[текущий] < 2 и цвет[предыдущий] > 1, что повторяет условие Value[1] < 2 && Value[0] > 1 из советника.
    • Короткий сигнал возникает, когда цвет[текущий] > 2 и цвет[предыдущий] > 0, как в исходном Value[1] > 2 && Value[0] > 0.
  3. Исполнение сделок

    • Вход выполняется рыночными ордерами BuyMarket / SellMarket объёмом Volume + |Position|, что позволяет закрыть противоположную позицию и открыть новую сторону одним действием.
    • Выход из длинных позиций происходит при переходе цвета выше 2, из коротких — при снижении ниже 2.

Важно: функции управления капиталом, стоп-лоссами, отклонением цены и магическими номерами из TradeAlgorithms.mqh не перенесены. Используйте стандартные правила риск-менеджмента StockSharp (например, StopLossRule, TakeProfitRule).

Параметры

Параметр Значение по умолчанию Описание
LongCandleType Свечи 4 часа Тип данных для длинного фильтра.
LongSsp 9 Длина окна SilverTrend для длинной стороны.
LongRisk 3 Коэффициент риска (33 - risk) для длинного фильтра.
LongSignalBar 1 Количество завершённых свечей для оценки длинного сигнала (≥ 1).
EnableLongEntries true Разрешение на открытие длинных позиций.
EnableLongExits true Разрешение на закрытие длинных позиций при медвежьем сигнале.
ShortCandleType Свечи 4 часа Тип данных для короткого фильтра.
ShortSsp 9 Длина окна SilverTrend для короткой стороны.
ShortRisk 3 Коэффициент риска для короткого фильтра.
ShortSignalBar 1 Количество завершённых свечей для оценки короткого сигнала (≥ 1).
EnableShortEntries true Разрешение на открытие коротких позиций.
EnableShortExits true Разрешение на закрытие коротких позиций при бычьем сигнале.
Volume 1 Базовый объём ордеров.

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

  • Сигналы анализируются только после формирования индикатора и накопления достаточного числа значений цвета (SignalBar + 1), что аналогично проверкам BarsCalculated в MQL.
  • Индикатор возвращает непосредственно код цвета, поэтому нет обращения к буферам через GetValue; используется связка Bind высокого уровня.
  • Для одинаковых таймфреймов создаются две подписки, что соответствует двум хэндлам iCustom в оригинальном роботе и упрощает независимую настройку.
  • Защита позиций, стоп-приказы и проскальзывание нужно реализовывать дополнительными правилами StockSharp либо брокерскими настройками.

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

  • Оптимизируйте параметры длинного и короткого фильтра раздельно, чтобы адаптировать чувствительность к выбранному инструменту.
  • Значение SignalBar = 1 имитирует «сигнал по закрытию предыдущей свечи», увеличение задерживает реакцию стратегии.
  • Для снижения числа ложных входов в боковике комбинируйте стратегию с временными фильтрами, ограничениями по просадке и другими элементами риск-менеджмента.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// SilverTrend Duplex strategy (simplified). Uses ATR channel breakout.
/// </summary>
public class SilverTrendDuplexStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _atrLength;
	private readonly StrategyParam<int> _emaLength;

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

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

	public SilverTrendDuplexStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");

		_atrLength = Param(nameof(AtrLength), 10)
			.SetGreaterThanZero()
			.SetDisplay("ATR Length", "ATR period", "Indicators");

		_emaLength = Param(nameof(EmaLength), 21)
			.SetGreaterThanZero()
			.SetDisplay("EMA Length", "EMA trend", "Indicators");
	}

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

		var ema = new ExponentialMovingAverage { Length = EmaLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, (ICandleMessage candle, decimal emaValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var close = candle.ClosePrice;
				var range = candle.HighPrice - candle.LowPrice;
				if (range <= 0m)
					return;

				if (close > emaValue + range * 1.5m && Position <= 0)
					BuyMarket();
				else if (close < emaValue - range * 1.5m && Position >= 0)
					SellMarket();
			})
			.Start();

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