Table of Contents

Торговые операции в стратегиях

В StockSharp класс Strategy предоставляет различные способы работы с заявками для максимального удобства при реализации торговых стратегий.

Способы выставления заявок

Существует несколько способов выставления заявок в стратегиях StockSharp:

1. Использование высокоуровневых методов

Самый простой способ — использование встроенных методов, которые создают и регистрируют заявку за один вызов:

// Покупка по рыночной цене
BuyMarket(volume);

// Продажа по рыночной цене
SellMarket(volume);

// Покупка по лимитной цене
BuyLimit(price, volume);

// Продажа по лимитной цене
SellLimit(price, volume);

// Закрытие текущей позиции по рыночной цене
ClosePosition();

Эти методы обеспечивают максимальную простоту и читаемость кода. Они автоматически:

  • Создают объект заявки с указанными параметрами
  • Заполняют необходимые поля (инструмент, портфель и т.д.)
  • Регистрируют заявку в торговой системе

2. Использование CreateOrder + RegisterOrder

Более гибкий подход заключается в раздельном создании и регистрации заявок:

// Создаем объект заявки
var order = CreateOrder(Sides.Buy, price, volume);

// Дополнительная настройка заявки
order.Comment = "My special order";
order.TimeInForce = TimeInForce.MatchOrCancel;

// Регистрация заявки
RegisterOrder(order);

Метод CreateOrder создает инициализированный объект заявки, который затем можно дополнительно настроить перед регистрацией.

3. Прямое создание и регистрация заявки

Для максимального контроля можно создать объект заявки напрямую и зарегистрировать его:

// Создаем объект заявки напрямую
var order = new Order
{
    Security = Security,
    Portfolio = Portfolio,
    Side = Sides.Buy,
    Type = OrderTypes.Limit,
    Price = price,
    Volume = volume,
    Comment = "Custom order"
};

// Регистрация заявки
RegisterOrder(order);

Подробнее о работе с заявками можно узнать в разделе Заявки.

Обработка событий заявок

После регистрации заявки важно отслеживать её состояние. Для этого в стратегии можно:

1. Использовать обработчики событий

// Подписка на событие изменения заявки
OrderChanged += OnOrderChanged;

// Подписка на событие исполнения заявки
OrderRegisterFailed += OnOrderRegisterFailed;

private void OnOrderChanged(Order order)
{
    if (order.State == OrderStates.Done)
    {
        // Заявка исполнена - выполняем соответствующую логику
    }
}

private void OnOrderRegisterFailed(OrderFail fail)
{
    // Обработка ошибки регистрации заявки
    LogError($"Ошибка регистрации заявки: {fail.Error}");
}

2. Использовать правила для заявок

Более мощный подход — использование правил для заявок:

// Создаем заявку
var order = BuyLimit(price, volume);

// Создаем правило, которое сработает при исполнении заявки
order
    .WhenMatched(this)
    .Do(() => {
        // Действия после исполнения заявки
        LogInfo($"Заявка {order.TransactionId} исполнена");
        
        // Например, выставляем стоп-заявку
        var stopOrder = SellLimit(price * 0.95, volume);
    })
    .Apply(this);

// Правило для обработки ошибки регистрации
order
    .WhenRegisterFailed(this)
    .Do(fail => {
        LogError($"Ошибка регистрации заявки: {fail.Error}");
        // Возможно, повторная попытка с другими параметрами
    })
    .Apply(this);

Подробные примеры использования правил с заявками можно найти в разделе Примеры правил на заявки.

Управление позицией

Стратегия также предоставляет методы для управления позицией:

// Получение текущей позиции
decimal currentPosition = Position;

// Закрытие текущей позиции
ClosePosition();

// Защита позиции через стоп-лосс и тейк-профит
StartProtection(
    takeProfit: new Unit(50, UnitTypes.Absolute),   // тейк-профит
    stopLoss: new Unit(20, UnitTypes.Absolute),     // стоп-лосс
    isStopTrailing: true,                        // трейлинг стоп
    useMarketOrders: true                        // использовать рыночные заявки
);

Пример использования торговых операций в стратегии

Состояние стратегии перед торговлей

Перед выполнением торговых операций важно убедиться, что стратегия находится в корректном состоянии. StockSharp предоставляет несколько свойств и методов для проверки готовности стратегии:

Свойство IsFormed

Свойство IsFormed указывает, сформированы ли (прогреты) все индикаторы, используемые в стратегии. По умолчанию проверяет, чтобы все индикаторы, добавленные в коллекцию Indicators, были в состоянии IIndicator.IsFormed = true.

Подробнее о работе с индикаторами в стратегии можно прочитать в разделе Индикаторы в стратегии.

Свойство IsOnline

Свойство IsOnline показывает, находится ли стратегия в режиме реального времени. Оно становится true только когда стратегия запущена и все её подписки на маркет-данные перешли в состояние SubscriptionStates.Online.

Более подробно о подписках на маркет-данные в стратегиях можно узнать в разделе Подписки на маркет-данные в стратегиях.

Свойство TradingMode

Свойство TradingMode определяет режим торговли для стратегии. Возможные значения:

Это свойство можно настроить через параметры стратегии:

public SmaStrategy()
{
    _tradingMode = Param(nameof(TradingMode), StrategyTradingModes.Full)
                   .SetDisplay("Режим торговли", "Разрешенные торговые операции", "Основные настройки");
}

Вспомогательные методы проверки состояния

Для удобной проверки готовности стратегии к торговле, StockSharp предоставляет вспомогательные методы:

  • IsFormedAndOnline() - проверяет, что стратегия находится в состоянии IsFormed = true и IsOnline = true

  • IsFormedAndOnlineAndAllowTrading(StrategyTradingModes) - проверяет, что стратегия сформирована, находится в онлайн-режиме и имеет необходимые права на торговлю

Метод IsFormedAndOnlineAndAllowTrading принимает опциональный параметр required типа StrategyTradingModes:

public bool IsFormedAndOnlineAndAllowTrading(StrategyTradingModes required = StrategyTradingModes.Full)

Этот параметр позволяет указать минимальный уровень прав на торговлю, необходимый для конкретной операции:

  1. StrategyTradingModes.Full (значение по умолчанию) - возвращает true, только если стратегия находится в режиме полной торговли (TradingMode = StrategyTradingModes.Full). Используется для операций, которые могут увеличивать позицию.

  2. StrategyTradingModes.ReducePositionOnly - возвращает true, если стратегия находится в режиме полной торговли или в режиме только уменьшения позиции. Используется для операций закрытия или частичного закрытия позиции.

  3. StrategyTradingModes.CancelOrdersOnly - возвращает true при любом активном режиме торговли (кроме Disabled). Используется для операций отмены заявок.

Это позволяет избирательно разрешать или запрещать различные торговые операции в зависимости от текущего режима торговли:

// Для выставления новой заявки, увеличивающей позицию, требуется полный режим торговли
if (IsFormedAndOnlineAndAllowTrading(StrategyTradingModes.Full))
{
    // Можем выставлять любые заявки
    RegisterOrder(CreateOrder(Sides.Buy, price, volume));
}
// Для закрытия позиции достаточно режима уменьшения позиции
else if (IsFormedAndOnlineAndAllowTrading(StrategyTradingModes.ReducePositionOnly) && Position != 0)
{
    // Можем только закрывать позицию
    ClosePosition();
}
// Для снятия активных заявок достаточно режима снятия заявок
else if (IsFormedAndOnlineAndAllowTrading(StrategyTradingModes.CancelOrdersOnly))
{
    // Можем только снимать заявки
    CancelActiveOrders();
}

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

Хорошей практикой является использование этих методов перед выполнением торговых операций:

private void ProcessCandle(ICandleMessage candle)
{
    // Проверка, сформирована ли стратегия и в онлайн-режиме ли она,
    // и разрешена ли торговля
    if (!IsFormedAndOnlineAndAllowTrading())
        return;
    
    // Торговая логика
    // ...
}

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

protected override void OnStarted(DateTimeOffset time)
{
    base.OnStarted(time);
    
    // Подписка на свечи
    var subscription = new Subscription(
        DataType.TimeFrame(TimeSpan.FromMinutes(5)),
        Security);
    
    // Создание правила для обработки свечей
    Connector
        .WhenCandlesFinished(subscription)
        .Do(ProcessCandle)
        .Apply(this);
    
    Connector.Subscribe(subscription);
}

private void ProcessCandle(ICandleMessage candle)
{
    // Проверка готовности стратегии к торговле
    if (!this.IsFormedAndOnlineAndAllowTrading())
        return;
    
    // Пример торговой логики на основе цены закрытия
    if (candle.ClosePrice > _previousClose * 1.01)
    {
        // Вариант 1: Использование высокоуровневого метода
        var order = BuyLimit(candle.ClosePrice, Volume);
        
        // Создаем правило для обработки исполнения заявки
        order
            .WhenMatched(this)
            .Do(() => {
                // При исполнении заявки выставляем стоп-лосс и тейк-профит
                StartProtection(
                    takeProfit: new Unit(50, UnitTypes.Absolute),
                    stopLoss: new Unit(20, UnitTypes.Absolute)
                );
            })
            .Apply(this);
    }
    else if (candle.ClosePrice < _previousClose * 0.99)
    {
        // Вариант 2: Раздельное создание и регистрация
        var order = CreateOrder(Sides.Sell, candle.ClosePrice, Volume);
        RegisterOrder(order);
        
        // Альтернативный способ обработки через событие
        OrderChanged += (o) => {
            if (o == order && o.State == OrderStates.Done)
            {
                // Действия после исполнения
            }
        };
    }
    
    _previousClose = candle.ClosePrice;
}

См. также