Table of Contents

Параметры стратегии

Для настройки стратегии и проведения оптимизации StockSharp предоставляет специальный класс StrategyParam<T>. Параметры стратегии позволяют изменять настройки торгового алгоритма без модификации программного кода, что особенно удобно при переключении между режимами тестирования и реальной торговли. Кроме того, эти параметры используются в процессе оптимизации для автоматического перебора значений и поиска оптимальных настроек стратегии.

В отличие от обычных свойств C#, параметры, созданные с помощью этого класса, автоматически отображаются в визуальных настройках (например, в Дизайнере) и могут использоваться при оптимизации стратегий.

Создание параметров стратегии

Параметры создаются в конструкторе стратегии с помощью метода Strategy.Param:

public class SmaStrategy : Strategy
{
	private readonly StrategyParam<int> _longSmaLength;

	public int LongSmaLength
	{
		get => _longSmaLength.Value;
		set => _longSmaLength.Value = value;
	}

	public SmaStrategy()
	{
		_longSmaLength = Param(nameof(LongSmaLength), 80)
							.SetGreaterThanZero()
							.SetDisplay("Long SMA length", string.Empty, "Base settings");
	}
}

В этом примере создается параметр LongSmaLength с начальным значением 80, задается валидатор для проверки, что значение будет больше нуля, и устанавливаются настройки отображения в пользовательском интерфейсе.

Методы настройки параметров

Класс StrategyParam<T> предоставляет несколько методов для настройки параметра:

SetDisplay

Метод StrategyParam<T>.SetDisplay задает отображаемое имя, описание и категорию параметра:

_longSmaLength = Param(nameof(LongSmaLength), 80)
					.SetDisplay("Long SMA length", "Период длинной скользящей средней", "Основные настройки");

SetValidator

Метод StrategyParam<T>.SetValidator устанавливает валидатор для проверки значения параметра. StockSharp предоставляет ряд предопределенных валидаторов, которые можно использовать для наиболее распространенных задач:

// Проверка, что число больше нуля
_longSmaLength = Param(nameof(LongSmaLength), 80)
					.SetValidator(new IntGreaterThanZeroAttribute());

// Проверка, что число не отрицательное
_volume = Param(nameof(Volume), 1)
			.SetValidator(new DecimalNotNegativeAttribute());

// Проверка на диапазон значений
_percentage = Param(nameof(Percentage), 50)
				.SetValidator(new RangeAttribute(0, 100));

// Проверка на обязательное значение
_security = Param<Security>(nameof(Security))
				.SetValidator(new RequiredAttribute());

Для удобства в StrategyParam<T> есть встроенные методы для наиболее распространенных валидаторов:

// Проверка, что число больше нуля
_longSmaLength = Param(nameof(LongSmaLength), 80).SetGreaterThanZero();

// Проверка, что число не отрицательное
_volume = Param(nameof(Volume), 1).SetNotNegative();

// Проверка, что значение NULL или не отрицательное
_interval = Param<TimeSpan?>(nameof(Interval)).SetNullOrNotNegative();

// Установка диапазона значений
_percentage = Param(nameof(Percentage), 50).SetRange(0, 100);

Если встроенных валидаторов недостаточно, вы можете создать свой собственный, унаследовав его от ValidationAttribute:

public class EvenNumberAttribute : ValidationAttribute
{
	public EvenNumberAttribute()
		: base("Значение должно быть четным числом.")
	{
	}

	public override bool IsValid(object value)
	{
		if (value is int intValue)
			return intValue % 2 == 0;
		
		return false;
	}
}

// Использование пользовательского валидатора
_barCount = Param(nameof(BarCount), 10)
				.SetValidator(new EvenNumberAttribute());

SetHidden

Метод StrategyParam<T>.SetHidden скрывает параметр в редакторе свойств:

_systemParam = Param(nameof(SystemParam), "value")
				.SetHidden(true);

SetBasic

Метод StrategyParam<T>.SetBasic отмечает параметр как базовый, что влияет на его отображение в пользовательском интерфейсе. Базовые параметры отображаются в упрощенном режиме редактора свойств:

_longSmaLength = Param(nameof(LongSmaLength), 80)
					.SetBasic(true);

strategy parameters basic advanced

SetReadOnly

Метод StrategyParam<T>.SetReadOnly делает параметр только для чтения:

_calculatedParam = Param(nameof(CalculatedParam), 0)
					.SetReadOnly(true);

SetCanOptimize и SetOptimize

Методы StrategyParam<T>.SetCanOptimize и StrategyParam<T>.SetOptimize указывают, может ли параметр использоваться для оптимизации, и задают диапазон значений для оптимизации:

_longSmaLength = Param(nameof(LongSmaLength), 80)
					.SetCanOptimize(true)
					.SetOptimize(10, 200, 10);

В примере выше параметр будет оптимизироваться в диапазоне от 10 до 200 с шагом 10.

Использование параметров в стратегии

Параметры стратегии используются так же, как обычные свойства:

protected override void OnStarted(DateTimeOffset time)
{
	base.OnStarted(time);

	_shortSma = new SimpleMovingAverage { Length = ShortSmaLength };
	_longSma = new SimpleMovingAverage { Length = LongSmaLength };
	
	// ...
}

Сохранение и загрузка параметров

Значения параметров автоматически сохраняются и загружаются в базовом классе Strategy. При переопределении методов Strategy.Save и Strategy.Load необходимо вызывать методы базового класса:

public override void Save(SettingsStorage settings)
{
	base.Save(settings);
	
	// Дополнительная логика сохранения...
}

public override void Load(SettingsStorage settings)
{
	base.Load(settings);
	
	// Дополнительная логика загрузки...
}

Пример: Стратегия с несколькими параметрами

Ниже представлен пример стратегии с несколькими параметрами:

public class SmaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _series;
	private readonly StrategyParam<int> _longSmaLength;
	private readonly StrategyParam<int> _shortSmaLength;

	public DataType Series
	{
		get => _series.Value;
		set => _series.Value = value;
	}

	public int LongSmaLength
	{
		get => _longSmaLength.Value;
		set => _longSmaLength.Value = value;
	}

	public int ShortSmaLength
	{
		get => _shortSmaLength.Value;
		set => _shortSmaLength.Value = value;
	}

	public SmaStrategy()
	{
		base.Name = "SMA strategy";

		Param("TypeId", GetType().GetTypeName(false)).SetHidden();
		_longSmaLength = Param(nameof(LongSmaLength), 80)
							.SetGreaterThanZero()
							.SetDisplay("Long SMA length", string.Empty, "Base settings")
							.SetCanOptimize(true)
							.SetOptimize(20, 200, 10);
		
		_shortSmaLength = Param(nameof(ShortSmaLength), 30)
							.SetGreaterThanZero()
							.SetDisplay("Short SMA length", string.Empty, "Base settings")
							.SetCanOptimize(true)
							.SetOptimize(5, 50, 5);
		
		_series = Param(nameof(Series), DataType.TimeFrame(TimeSpan.FromMinutes(15)))
					.SetDisplay("Series", string.Empty, "Base settings");
	}

	// ...
}

В данном примере мы создали стратегию на основе пересечения двух скользящих средних с тремя настраиваемыми параметрами:

  • Series - тип и таймфрейм данных
  • LongSmaLength - период длинной скользящей средней
  • ShortSmaLength - период короткой скользящей средней

Для двух числовых параметров мы настроили возможность оптимизации с заданными диапазонами.

См. также

Сохранение и загрузка настроек