Открыть на GitHub

Стратегия Trading Panel Control

Обзор

Trading Panel Strategy переносит в StockSharp возможности вспомогательной панели из MetaTrader 4. В оригинальном советнике пользователь переключал таймфрейм графика и список инструментов через кнопки. В версии для StockSharp те же действия выполняются через параметры стратегии, которыми можно управлять из Designer, терминала или собственного интерфейса.

Стратегия не выставляет заявки и служит исключительно для управления подписками на свечи и вывода сервисной информации. Это позволяет повторить сценарий использования панели без необходимости держать отдельный интерфейс MQL.

Основные возможности

  • Переключение таймфрейма – поддерживаются интервалы M1, M5, M15, M30, H1, H4, D1 и W1. Изменение параметра мгновенно пересоздаёт подписку на свечи.
  • Поиск инструмента – можно указать идентификатор инструмента. При включённом AutoLookupSecurity стратегия ищет его через SecurityProvider; иначе используется уже привязанный к стратегии инструмент.
  • Журнал закрытий – каждое завершённое свечное сообщение логируется с идентификатором инструмента, активным таймфреймом и ценой закрытия, что заменяет информационные подписи оригинальной панели.

Параметры

Параметр Описание
TimeFrameName Код выбранного таймфрейма (M1, M5, M15, M30, H1, H4, D1, W1). Значение по умолчанию – M15.
SecurityId Идентификатор инструмента. Пустое значение означает использование текущего Security.
AutoLookupSecurity При true выполняется поиск инструмента через SecurityProvider.
DefaultCandleType Запасной тип свечей, если введён неизвестный таймфрейм. По умолчанию – минутные свечи.

Как работает

  1. Запуск – в OnStarted стратегия определяет целевой инструмент и таймфрейм, затем подписывается на соответствующие свечи.
  2. Изменение параметров – при обновлении TimeFrameName, SecurityId или AutoLookupSecurity активная подписка перезапускается с новыми параметрами.
  3. Обработка свечей – после закрытия свечи поле LastFinishedCandle обновляется, а в лог записывается информация о выбранном инструменте и таймфрейме.
  4. Остановка – при завершении работы или смене настроек подписка корректно останавливается.

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

  • Добавьте стратегию в Designer вместе с графиком, чтобы повторить поведение панели MT4. Редакторы параметров будут играть роль кнопок и списков.
  • Если стратегия запускается на уже выбранном инструменте, оставьте SecurityId пустым.
  • Направьте журнал стратегии в интерфейс или консоль, чтобы отображать сведения, аналогичные надписям из MQL-версии.

Отличия от MQL-реализации

  • Нет графических кнопок, управление осуществляется через параметры.
  • Не выполняется торговых операций – только управление данными и логирование.
  • Список таймфреймов полностью совпадает с оригиналом для удобства перехода с MT4.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Trading Panel Control strategy: Williams %R crossover.
/// Buys when Williams %R crosses above -80, sells when crosses below -20.
/// </summary>
public class TradingPanelControlStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _period;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _prevWr;
	private int _candlesSinceTrade;
	private bool _hasPrev;

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

	public TradingPanelControlStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_period = Param(nameof(Period), 14)
			.SetGreaterThanZero()
			.SetDisplay("Period", "Williams %R period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevWr = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevWr = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
		var wr = new RelativeStrengthIndex { Length = Period };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(wr, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (_hasPrev)
		{
			if (_prevWr < 35 && wrValue >= 35 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (_prevWr > 65 && wrValue <= 65 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevWr = wrValue;
		_hasPrev = true;
	}
}