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 - период короткой скользящей средней

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

См. также

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