понедельник, 5 июля 2010 г.

Stock# 2.1

И так, вышла новая версия - Stock# 2.1. Это не просто фикс предыдущей версии 2.0.1, а значительное расширение функциональности, как можно судить по списку ниже. Но обо все по-порядку.

Фичи:
  1. Я решил полностью пересмотреть подход с экспортом произвольных таблиц. В ранних версиях принцип работы строился на использовании события ProcessWellKnownDdeData, через которое в программу поступали массивы данных, представляющие собой строчки таблиц. Теперь, через специальное преобразование данных QuikTrader сам отдает готовые бизнес объекты. Вся магия заключается в методе QuikTrader.AddCustomTableMapping и событие QuikTrader.ProcessCustomTable. Подробнее в документации. В качестве демонстрации приведу два куска кода. Сверху новый подход, снизу старый. Решение задачи одно и тоже - экспорт портфеля:


    this.Trader.AddCustomTableMapping(typeof(CustomPortfolio));
    
    this.Trader.ProcessCustomTables += (type, objects) =>
    {
      // нас интересует только CustomPortfolio
      if (type == typeof(CustomPortfolio))
        _portfolioWindow.Portfolios.AddRange(objects.Cast());
    };
    
    
    this.Trader.ProcessUnknownDdeData += (name, rows) =>
    {
      // узнаем, что пришедшие данные отвечают за портфель
      if (string.Compare(name, "portfolio", true) == 0)
      {
        foreach (var row in rows)
        {
          var client = (string)row[0];
          var portfolio = _portfolioWindow.Portfolios.FirstOrDefault(p => p.Client == client);
    
          if (portfolio == null)
          {
            portfolio = new Portfolio { Client = client };
            _portfolioWindow.Portfolios.Add(portfolio);
          }
    
          portfolio.Shorts = (double)row[1];
          portfolio.Longs = (double)row[2];
          portfolio.Collateral = (double)row[3];
          portfolio.Margin = (double)row[4];
          portfolio.Money = (double)row[5];
          portfolio.PnL = (double)row[6];
        }
      }
    }
    


    Результат, как говорится, не лицо.

  2. Переделал и ProcessWellKnownDdeDataa. Теперь вообще не нужно использовать данное событие. Достаточно лишь расширить таблицу в Quik и задать необходимые колонки в коде. Все будет экспортироваться само. Подробное описание.

  3. По следам этого топика переделал процесс обработки данных. Теперь, если на какой-то строчке таблицы происходит затык (например, как часто это бывает, появился инструмент, у которого отсутствует что-то необходимое), то это не приводит к остановке всего экспорта. Вместо этого такая строчка просто пропускается, а ошибка выводится через ProcessDataError.

  4. Для предыдущего пункта добавил DdeSecurityColumns.LastTradeVolume2.

  5. Внимание! Колонка DdeSecurityColumns.LastChangeTime по умолчанию выключена для экспорта. Это важное изменения я сделал из-за двух причин. Первая, не все торгую на нескольких рынках одновременно. Вторая, из-за пункта 4 (для единообразия, если кто-то торгует на нескольких рынках, то он должен включать для себя необходимые колонки). Так что, теперь колонка с временем последней сделки только одна (по-умолчанию).

  6. В дистрибутиве теперь идут три файла настроек Quik: info_rts.wnd, info_micex.wnd и info_rts_micex.wnd (совмещает первое и второе). Названия говорят сами за себя. Подробнее, об этом я написал в переделанной документации.

  7. Теперь QuikTrader умеет экспортировать позиции (Position). Ранее это был внутренний класс для SmartTrader. Теперь и для Quik. Соответственно, добавил и функционал для работы с позициями - ITrader.Positions, ITrader.NewPositions и Trader.PositionsChanged. Подробнее, как включать экспорт по позициям, описал в документации.

  8. Делая предыдущий пункт, я дополнительно реализовал экспорт портфелей и для QuikTrader. Сам по себе экспорт данных не идет (для этого все также нужно делать экспорт самостоятельно, как я показал в примере SampleDdeCustomTable), но сама сущность с номером счета создается и выводится через ITrader.NewPortfolios.

  9. Для Position и для Portfolio создал методы расчета PnL TraderHelper.GetPnL.

  10. Дополнительно, для удобства получения позиций добавил возможность получать их по инструменту или портфелю через метод ITrader.GetPositions.

  11. Убрал событие MarketDepth.Changed и заменил его двумя: MarketDepth.QuotesChanged, которое показывает, какие именно котировки внутри стакана изменились, и MarketDepth.DepthChanged, которое говорит об изменении глубины стакана.

  12. Добавил возможность сохранять и загружать настройки таблиц через методы DdeTable.Save и DdeTable.Load. Это удобно в тех случаях, если программа распространяется среди пользователей.

  13. Внедрил код получения времени сервера как написали здесь. В принципе, теперь необходимость для QuikTrader в MarketTimeOffset отпала. Спасибо HaMMeR-у!

  14. Сделал возможность менять у уже созданного QuikTrader путь к Quik - QuikTrader.Path. Аналогично сделал и для SmartTrader с Address, Login и Password. Одно но. Перед изменениями необходимо сделать Disconnect(если было произведено соединение). Иначе, будет выбрасываться исключение.

  15. Добавил интерфейс IExtendableEntity, в которое есть только одной свойство ExtensionInfo. Сделал это для удобства работы в написании универсального кода, который работает с любой торговой сущностью.

  16. Для SmartTrader добавил специальное перечисление - Extensions. Это ключ, по которому можно получить специфичную для SmartCOM данные из ExtensionInfo.

  17. Опять по DDE. Теперь название категорий (в Quik это называется Рабочая книга) указывается такое же, как и DdeTable.Caption.

  18. Наконец-то доделал обещанное - сделал котирование по асинхронному режиму QuikTrader.IsAsyncMode (http://stockmarketdotnet.blogspot.com/2010/03/stock-18.html пункт 1). Автоматически, эта вещь заработала и для SmartTrader, потому что он умеет работать только в асинхронном режиме. Ура!

  19. Убрал метод Strategy.AddOrder и изменил логику регистрации заявок из стратегий. Теперь регистрировать заявки необходимо через метод Strategy.RegisterOrder, который автоматически после успешного принятия заявки биржей добавляет ее в стратегию. Собственно, в такому случае Strategy.AddOrder стал рудиментом, что и привело к его исчезновению. Замену заявок так же нужно производить через новый метод Strategy.ReRegisterOrder. Собственно, новое котирование как раз и основанно на этих новых методах.

  20. TraderHelper.ReRegisterOrder теперь исчез - перекочевал в Strategy.ReRegisterOrder.

  21. Сделал возможность работать с Currency как с обычными числами. Тоесть, можно складывать, вычитать, умножать и делить.

  22. Добавил в Order поле Portfolio. Пока это как опциональное поле. Но в дальнейшем планирую его сделать обязательным к заполнению, которое заменит собой поле Account (и, надеюсь, строковое представление счета исчезнет навсегда из S#).

  23. В документации добавил страницу с примерами. Показывает, какие вообще есть примеры, и что они делают (цель их обучения).

  24. Специально запрятал в самый конец, чтобы меньше сил на протесты осталось =). Переделал состояние заявок. Понятно, что изменение значительное (пожалуй, самое часто использующееся свойство). Но прогресс должен быть, и рудименты должны исправляться. Иначе библиотека зарастет архаизмами... Есть только три свойства - None, Active и Done. Все. Именно они однозначно говорят о состоянии заявки, жива или нет. Если нужно узнать, исполнена или отклонена, то пункт 25.

  25. Для отслеживания того, полностью ли исполнена заявка, или частично, или вообще не исполнена надо вызывать методы TraderHelper.IsMatched, TraderHelper.IsFilledPartially и TraderHelper.IsFilledEmpty соответственно. Если нужно узнать, отменена ли была заявка, то нужно вызывать метод TraderHelper.IsCanceled. С учетом пункта 24 у нас вместо прежних 4-ех состояний (напомню, было None, Active, Matched и Cancelled) теперь есть комбинации. Намного информативнее.


И, конечно же, фиксы:

  1. DDE экспорт не запускается, если открыта другая закладка с развернутым графиком во весь экран.

  2. Исправил старую "добрую" ошибку с запуском экспорта. Иногда он не запускался с первого раза. Причина - окно с запуском DDE в Quik не всегда быстро появляется. Теперь гарантированно дожидается появление данного окна. Экспорт стартует чуть дольше, зато гарантированно работает.

  3. Пофиксил в MarketDepth неправильный порядок вывода котировок.

  4. Исправил ошибку с отсутствием регистрации новой заявки в котировании.

  5. В том же топике, что и в пункте 4 была проблема с буферизацией вывода логов через StrategyLogger. Буферизацию убрал - теперь все выводится сразу.

  6. Снятие группу заявок в асинронном режиме не всегда работает.


Итого, 25 нововведений и 6 фиксов. Неплохо, неплохо.

3 комментария:

  1. Заставляете Вами восхищаться! :)
    Постоянно слежу за развитием.
    Пока еще не пользуюсь возможностями Вашего проекта но все больше этого хочу.
    Спасибо!

    Вопрос 1: есть ли возможность с помощью Вашего проекта реализовать приложение с набором роботов (примерно так как это сделано в ЛивТрейд СДК)? либо как заставить несколько роботов работать с одним квиком?

    Вопрос 2: как можно помочь проекту?

    ОтветитьУдалить
  2. Большое спасибо. Ваша библиотека просто жизнь спасла )

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