понедельник, 12 апреля 2010 г.

Stock# 1.8

Ага, опять не S# 2.0. Сам уже удивляюсь, что можно сделать в рамках одного Quik. Поистине, пределов для автоматизации не существует. Качаем-с.

  1. Главное нововведение в этой версии - асинхронные заявки. Я уже писал в своем посте о том, насколько они быстрее обычных. Поэтому, теперь QuikTrader умеет работать и в асинхронном режиме. Достаточно установить у него свойство IsAsyncMode в true. Более подробно, я написал в документации и показал в примере SampleAsyncTransaction. Кстати, последний выглядит как очень простой, но все же привод. Полезно будет посмотреть тем, кто хочет написать подобное. Но есть и ложечка дегтя. Котирование в асинхронном режиме работать не будет - проверено. Надо полностью переписывать стратегию. С большей вероятностью, это относится к тем стратегиям, которые уже написаны на базе S#.

  2. Добавил события ITrader.OrdersFailed и ITrader.StopOrdersFailed (опять же, для асинхронного режима). Как я уже написал, при синхронном режиме в случае неуспеха QuikTrader бросает исключение. Для асинхронного режима реализовать подобное невозможно, потому что информация по заявке может прийти в любое время. Поэтому, когда она придет, и будет означать не успешную регистрацию, будет вызвано данное событие.

  3. Для асинхронного режима было добавлено свойство QuikTrader.CurrentTransactionId. Первоначально, при создании QuikTrader, оно установлено в значение, равное количеству миллисекунд, прошедшее с начала дня. Для чего сделаны такие хитросплетения. Дело в том, что асинхронный режим, в отличие от синхронного режима, при определении заявки, переданной по DDE, основывается не на номере заявки (Order.Id), а на идентификаторе транзакции (Order.TransactionId). Чтобы обеспечить уникальность данного значение (а оно должно быть строго уникальным), то я сделал эту первоначальную инициализацию. Если у вас ведется какой-то собственный механизм генерации идентификаторов транзакции, то перед самым началом работы необходимо присвоить значение в QuikTrader.CurrentTransactionId. Если же ничего такого нет, то будет достаточно и стандартного поведения.

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

  5. Наконец-то пункт, не касающийся асинхронного режима... Для Strategy я сделал механизм генерации отчетов. Две реализации: XmlStrategyReport - генерация отчетов в формат Xml, и ExcelStrategyReport - генерация в Excel. Первый удобен, если нужно передавать данные между разными роботами. Или, к примеру, сохранять состояние между сессиями. Я уже писал об этом в пункте 6, что нужен механизм выставления первоначального состояния для стратегий, выходящих за границы интрадей трейдинга. Так вот, Xml формат - это идеальное решение.

    ExcelStrategyReport необходим тогда, когда нужно в конце дня посмотреть, что же робот наторговал, и как именно. Построить графики, проанализировать результат. Особенность ExcelStrategyReport в том, что он умеет работать с файлом-шаблоном. Например, можно настроить в файле-шаблоне формулы, написать макросы, построить графики. А ExcelStrategyReport будет обновлять свежими данными, и весь отчет автоматически будет перестраиваться. Очень удобно.

  6. Добавил давно необходимый метод - ITrader.CancelOrders. Отменяет все активные заявки по определенной маске (инструмент, направление, счет и т.д.). Пригодился, к слову, и в примере SampleAsyncTransactions.

  7. Очень важный пункт. Устранил проблему с ошибкой в конструкторе QuikTrader, когда больше невозможно было пересоздать QuikTrader. На самом деле, это ошибка, скорее следствие неправильного дизайна архитектуры. Не нужно делать автоматическое подключение в конструкторе. Поэтому, теперь метод Connect нужно вызывать отдельно, когда требуется произвести подключение к Квику.

  8. Расширил поддержку РТС Стандарт. Вкратце, проблема с этой площадкой в S# в том, что коды инструментов не уникальны. Но уникальна комбинация код инструмента + класс инструмента. Поэтому, теперь в таких таблицах как Все Сделки, Мои Сделки, Заявки, Стоп-Заявки передается класс инструмента. Более того, теперь и стакан должен иметь новый заголовок КОД-КЛАСС, что так же решает проблему получения стаканов для РТС Стандарт.

  9. Чуть модифицировал предыдущее нововведение (пункт 12). Я переименовал событие QuikTrader.FormatTransactionString в QuikTrader.FormatTransaction, и которое теперь передает не просто строку, а TransactionBuilder. С ним форматировать строку транзакции намного удобнее.

  10. Добавил свойство Strategy.TotalWorkingTime, которое показывает, сколько проработала стратегия. Именно проработала, то есть время простоя, когда стратегия не была запущена, или была приостановлена не учитываются. Только рабочее. Теперь можно следить за операторами (без них роботов пока еще опасно оставлять), сколько они реально наработали за день, и сколько они заработали гонорару.

  11. Добавил еще один тип менеджера - менеджер задержки LatencyManager. Учитывает, как быстро торговая система принимает заявки от робота. Вкратце, при создании заявки в свойство Order.InitializationTime записывается время создания заявки на клиенте (рассчитывается текущее время, так что те, кто находится вне временной зоны с биржей, нужно принудительно в коде изменять временной сдвиг). Как только придет подтверждение регистрации заявки по DDE, менеджер возьмет реальное время Order.Time, и рассчитает общее время задержки. Теперь можно следить и за брокерами, и за интернет-провайдерами, и за теми, кто из них родом из Эстонии.

  12. В предыдущей версии я начал направление кастомизации DDE метаданных. В этой версии я еще больше его расширил, сделал его объектно-ориентированным. Появились классы DdeColumn и DdeColumnList. Последний имеет очень интересное поведение. При добавлении, вставки или удалении колонки он автоматически пересчитывает индексы всех остальных колонок. Подробнее, показал в документации в разделе Модификация стандартных таблиц.

  13. Продолжив реализовывать предыдущий пункт, я сделал QuikTrader.QuotesTable. Аналогично таким настройкам, как QuikTrader.SecuritiesTable, позволяет изменять настройки стакана. Стакан - это довольно интимное место, и многие привыкли использовать допустим биды сверху, офера снизу, наоробот и т.д. Так что, сделал S# чуть дружелюбнее к стакану.

  14. Order.Direction теперь по умолчанию экспортируется. Раньше я думал о том, что это создаст лишнюю нагрузку, но открыв для себя опцию "Формальные названия" и произведя ряд тестов, я убедился - нужно включать по умолчанию экспорт направления заявки у сделки.

  15. Добавил возможность (забытую первоначально мною, но о которой вспомнили здесь) возможность задавать комментарий при регистрации. Свойство Order.Comment существовало, но оно заполнялось только при DDE экспорте, но не использовалось в ITrader.RegisterOrder.

  16. Логи в котирование QuotingStrategy теперь пишутся на русском языке. Просто небольшое улучшение.

  17. К слову о логах. Появился стандартный класс-логгер, который пишет в файл. Называется StrategyLogger. Давно пора было его вынести из своих роботов в S#. Не было бы таких вопросов.

  18. Сделал класс Strategy наследником класса Disposable. Вот тут описано, что такое очищение ресурсов в рамках .NET. Не забывайте их подчищать, если хотите, чтобы робот "жил" долго.

  19. Переделал метод Order.Message в Order.Messages, который теперь есть не просто строка, а коллекция строк. Дело в том, что торговая система в течении жизни заявки может посылать несколько сообщений относительно одной и той же заявки (при регистрации, при снятии, при неудавшемся снятии и т.д.). Логично не перетирать старое значение, а добавлять при этом новое, что и было сделано.

  20. Буквально в самый последний момент исправил ошибку с датами, которая обсуждалась здесь. В кратце. Квик оставляет с таблице всех сделок (да и не только в ней) сделки с предыдущего дня - вечерней сессии. Экспорт DDE, реализованный в S#, не предоставлял возможность получения даты, и учитывал лишь время. Из-за этого, записи вчерашнего дня интерпретировались как сегодняшние. Например, сделка от "1 апреля 19:30" 2-го апреля имела бы дату "2 апреля 19:30". Не очень хорошо. Поэтому, теперь таблицы Все Сделки, Мои Сделки, Заявки, Стоп-Заявки теперь содержат колонку Дата.
Два десятка изменений. S# бурлит.

11 комментариев:

  1. Илья,

    Из директории Exe или Sources?

    ОтветитьУдалить
  2. Mikhail Sukhov,
    Из директории Exe. Сейчас попробывал на другом компьютере - запустилось нормально.

    ОтветитьУдалить
  3. Думаю, на первом компьютере не был установлен .NET 3.5

    ОтветитьУдалить
  4. Есть планы добавить поддержку SmartTrade?
    COM-интерфейс брокер предоставляет.

    ОтветитьУдалить
  5. toyan,

    Планы есть, собственно, сейчас и занимаюсь написанием робота на S# с поддержкой SmartCOM. Получится - выпущу новую версию уже со Смартом. Но пока не все гладко. Смарт явно переоценен в сообществе как удобное средство для разработки роботов.

    ОтветитьУдалить
  6. Mikhail Sukhov,

    Мне для торговли в стиле неагрессивного скальпинга в Смарте остро нехватает разряженого стакана. Хотел писать сам, но с нуля тяжеловато. С помощию Ваших наработок это было бы сделать гораздо легче, поэтому буду ждать поддержку интерфейса SmartCOM. Надеюсь, что в долго-грядущей версии S# 2.0 она появится, тем более что номер версии будет отражать и количество поддерживаемых платформ ;-).

    ОтветитьУдалить
  7. Здравствуйте.

    Я использую S# весию 1.4.1.
    И решил наконец переидти к версии 1.8. Причина в том что в версии 1.4.1 Order только содержит DerivedOrderId, а в версии 1.8 DerivedOrder уже полноценный Order.
    Признаюсь, я переписал всю библиотеку Ecng.Trading.BusinessEntities для своих нужд, прокомпилировал ее, и успешно использовал.
    Весия 1.8 Ecng.Trading.BusinessEntities отличается от версии 1.4.1.

    Возможно ли получить Коды только этой библиотеки? Все так и она не содержит никаких алгоритмов, которых стоит скрывать.

    Большое спасибо.

    ОтветитьУдалить
  8. Alex,

    Мне бы SmartCOM зарелизить =)

    Об Алоре буду думать потом - пока я только прочитал документацию. В ближайшие месяцы точно не появится. А Вы сами с ним работали?

    ОтветитьУдалить
  9. Да, Михаил, работал. правда еще не использовал многопоточность. с одним инструментом хорошо работает.

    ОтветитьУдалить
  10. Alex,

    Может тогда скинете пример-код, если таковой имеется? Пока не вдавался в эти слоты, но чувствую - перемудрили.

    ОтветитьУдалить