Список задач
Atom
29.12.2010
Mikhail Sukhov


И так, предлагаю подытожить то, что нужно сделать и в каком порядке.

Задачи сгруппировал по группам (копировал из соседней ветки http://stocksharp.com/forum/1275/&p=2). Первая группа - самая приоритетная. Без нее делать задачи из следующей бессмысленно. Сами задачи внутри этой группы так же выстроены по очередности.

Базовая группа:

  1. Описать основные метаданные, как это сделано для Квика (DdeSecurityColumns, DdeTradeColumns и т.д.). Я это уже показал на примере класса PlazaFutureColumns, но там колонки не реальные. Предлагаю прямо разобрать по названию таблиц потоков, кто за какие будет отвечать (описывать в коде). Таблицы только основные: инструменты, заявки, сделки и т.д.
  2. Подписываться на произвольные потоки + отписываться.
  3. Получать стаканы. Производная от предыдущей задача. Выделил ее отдельно.
  4. Заявки (регистрация, снятие и перемещение). Я уже сделал через класс Message заполнение полей для отправки транзакций. Это дело надо доделать.
  5. Парсинг ответа от транзакций (внимание! всех транзакций, а не только, что в предыдущем пункте). Я не знаю, в каком виде они приходят, но могу сказать, какой результат должен быть. Это должно быть PlazaException с кодом ошибки (чтобы не мучится сравнение строчек в коде). И код не ввиде числа (что не так уж лучше строчки), а нормального перечисления (enum).


Первую задачу предлагаю сделать сообща. Остальные - разбираем по тем признакам, кто какие таблицы описывал (например, кто описал стакан, тот занимается задачей 3, кто инструменты - задачей 2, кто заявки - задачей 4).

Второстепенная группа:

  1. Дописать все остальные метаданные (позиции, счета, волатильность, маржа, клиринг, доп информация о деривативах, индексы).
  2. Фильтрация потоков. Так как Плаза не дает фильтр (камрад skuvv написал об этом), но в клиентском коде прописывать фильтры дело не благодарное, предлагаю это симулировать через RegisterXXX + UnRegisterXXX.
  3. Возможность задавать глубину стакана (как я понял, это влияет на то, к какому потоку необходимо цепляться).
  4. Поддержка агрегированного стакана и обычного. Для этого можно использовать GroupedQuote (внутри себя он будет содержать не агрегированные котировки).


Третьестепенная группа:

  1. С помощью метаданных научиться строить конфиги ini. Как вариант, через PlazaTable (куда собственно и будут добавляться колонки из пункта 1 пред группы). Сейчас ini файлы программно редактировать нельзя. И если роботу нужны спец колонки нужно менять формат ini схем. Я предлагаю до загрузки этих схем давать возможность менять из программно (парсить и менять ini файлы на лету). + как фича автоматически сканировать директорию при старте и создавать с правильным набором колонок сами PlazaTable. Возможно, здесь поможет TableSet.
  2. Время биржи.
  3. Все остальные транзакции (FutChangeClientMoney, OptChangeExpiration и т.д.).
  4. Составные инструменты.
  5. На форуме доступна x64 версия. Нужна прозрачная поддержка (без перекомпиляции) x86 и x64.
  6. Обертка над роутером (чтобы так же, не ручками править конфиги, а программно).
  7. Документация (как xml, так и обычная). Если нужно сделать как у S#, то необходимо использовать Sandcastle.


Особенности в работе.

Старайтесь писать так, как это принято в .NET и в частности C# коде.
Публичные методы классы и т.д. описывайте xml комментариями (лучше не сочинять, а копировать из документации Плазы, чтобы быть не с планеты Юпитер, а ближе к тем, кто будет это использовать и вторым глазом подглядывать в документацию).
Предлагаю использовать R# как средство для контроля качества кода.
Пишите юнит тесты (заведите отдельный проект в sln).

Теги:


Спасибо:


<< < 4 5 6 7 8  >
Mikhail Sukhov

Фотография
Дата: 24.01.2011
Ответить


aspirant

Дело в том, что работа с плазовским стримом построена по принципу windows message loop: в неком методе программа вызывает метод CP2ConnectionClass.ProcessMessage(out cookie, PollInterval) в бесконечном цикле, а вся информация приходит через события. Если выводить создание и управление thread'ами, это нужно делать в отдельном классе. Иначе, если придется подключаться к стримам в нескольких местах, придется дублировать много кода.


Дубляж - это плохо. И плохо, когда стрим создает потоки (кол-во потоков не должно расти с количеством стримов). Плохо делать системный класс слишком уж умным. Код должен быть один и чтобы он управлял всеми стримами.

aspirant

Я помню о настраиваемости. Пока в черновом варианте я передаю путь к файлу, чтобы сразу можно было протестировать логику подключения, опроса, получения сообщений и т.д.
С метаданными такая вещь: стримы в Плазе настраиваются из файлов, даже по умолчанию (методы TableSet.InitFromIni / TableSet.InitFromIni2). Если передавать классу PlazaStream в конструкторе PlazaTable, тогда внутри PlazaStream некий класс TableConfigParser должен будет генерить файл с нужной схемой, чтобы передать ее TableSet.InitFromIni. Здесь такой момент: предлагаю в SpecialFolder.ApplicationData создать путь Stocksharp\PlazaTrader\Scheme, в котором хранить свои конфиг-схемы-файлы или их создавать в папке TEMP. Создавать их в подпапке самой Плазы не стоит: требуется админский доступ.


В папке самого плаза шлюза вообще лучше ничего не править. По умолчанию лучше создавать пути в текущем каталоге (я думаю большинству этого будет достаточно). Плюс сделать путь настраиваемым. Вообщем, логика мне виделась такая (если такое невозможно, то поправьте):


  1. Создание PlazaTrader.
  2. Опционально. Модификация таблиц с метаданными.
  3. PlazaTrader.Connect.

    • Проверка, есть ли ini файлы, соответствующие запрашиваемым метаданным.
    • Если нет, то они создаются на основе PlazaTable.
    • Есть, но с другими полями, то модифицируются.
    • Подключение к Плазе и запуск вечного цикла.



aspirant

Чтобы понимать в будущем, в каких случаях мы выкидываем PlazaException?


Только когда приходит плазовская ошибка (заявки, потоки или еще что).

aspirant

Насколько я понял, есть два варианта:


Одна особенность, все форматирование лучше помещать в PlazaFormatter. Потому как он уже используется для .NET -> Plaza при отправке транзакций. Не плохо было бы туда поместить и обратную трансформацию.

aspirant

На мой взгляд вызовы GetValAsХХХ(string fieldName) / GetValAsХХХByIndex(uint fieldIndex) нужно реализовать внутри PlazaStream, а мне чтобы дальше писать это класс нужно понимать:
  1. PlazaStream - это служебный класс, или им смогут пользоваться клиенты (читай, сторонние разработчики, использующие PlazaTrader)?
  2. В каком виде выдавать данные классам, которые будут использовать PlazaStream? Через события по одной строчке с конвертацией CP2Record в массив object'ов? Или попробовать сделать что-то типа реализации интерфейса IDataReader с использованием CP2DataBufferClass?



1. Считаю, что нужно сделать внутренним, до тех пор, пока не попросят вынуть его наружу.[smile]
2. А нельзя просто выбрать данные в коллекцию и передавать уже ввиде родной .NET коллекции?

aspirant

И последнее насчет фильтрации данных в потоке. Есть предложение это тоже сделать внутри PlazaStream. Тогда при конвертации данных с помощью GetValAsХХХ() / GetValAsХХХByIndex() можно будет проверять только колонки, по которым идет фильтрация, и, если запись не подходит, не выдавать ее клиентскому коду.


Насчет оптимизации согласен, но опять получается ситуация со слишком умным PlazaStream.
Спасибо:

Mikhail Sukhov

Фотография
Дата: 24.01.2011
Ответить


aspirant
Вчера разбирался со схемами таблиц потоков. Хочу выложить мои соображения:


Да, с точностью получился косяк. Надо исправлять.

skuvv, вы все еще на метаданных? Тогда не пропустите момент, который указал aspirant.
Спасибо:

skuvv

Фотография
Дата: 24.01.2011
Ответить


Mikhail Sukhov
aspirant
Вчера разбирался со схемами таблиц потоков. Хочу выложить мои соображения:


Да, с точностью получился косяк. Надо исправлять.

skuvv, вы все еще на метаданных? Тогда не пропустите момент, который указал aspirant.

Добавил для всех сделанных мета-таблиц соответствующий PlazaType для decemical и string
Спасибо:

aspirant

Фотография
Дата: 24.01.2011
Ответить


Mikhail Sukhov
Вообщем, логика мне виделась такая (если такое невозможно, то поправьте):
  1. Создание PlazaTrader.
  2. Опционально. Модификация таблиц с метаданными.
  3. PlazaTrader.Connect.

    • Проверка, есть ли ini файлы, соответствующие запрашиваемым метаданным.
    • Если нет, то они создаются на основе PlazaTable.
    • Есть, но с другими полями, то модифицируются.
    • Подключение к Плазе и запуск вечного цикла.




Этап 2 (опционально): создание таблиц PlazaTable кодом клиента (либо нужный набор колонок, либо все) + наш код парсит все ini файлов в заданной директории для создании на их основе таблиц PlazaTable (через метод PlazaTableSerializer.Deserialize(string fileName) + отслеживаем изменения/добавления файлов в этой директории. Здесь, кстати, уточнение: в предыдущем посте я был не прав. вот, что написано в документации (P2ClientGate.doc стр. 18): "Клиент также может не указывать никакой схемы при открытии потока, в этом случае сервер будет отдавать все данные, которые публикуются в потоке (далее этот режим будет называться «получение данных по схеме сервера»)." Т.е., если в потоке несколько таблиц, будут выдаваться данные по всем таблицам.

Для управления стримами (PlazaStream) я создам PlazaStreamManager, который будет внутри себя создавать стримы, подписываться на их события и управлять их подключением / отключением (т.е. внутри него будет бесконечный цикл). В PlazaStreamManager код пользователя передает коллекцию таблиц (по одной или сразу IEnumerable<PlazaTable>) из предыдущего пункта.

Этап 3 (PlazaTrader.Connect): если в PlazaStreamManager есть стримы, запускаем его. Все стримы будут вертеться в одном потоке (thread). Как дополнительную опцию (третьестепенная / четвертостепенная задача), добавить возможность создания приоритетных стримов в отдельном потоке (thread). Не знаю, нужно ли это?

Mikhail Sukhov

2. А нельзя просто выбрать данные в коллекцию и передавать уже ввиде родной .NET коллекции?


Насколько я понял, принцип работы со стримами в Плазе следующий: создаем и инициализируем CP2DataStream, затем CP2TableSet (у каждого стрима только один CP2TableSet). Далее подписываемся на события, открываем стрим. После "рукопожатия" (StreamLifeNumChanged) приходит событие StreamDataBegin - данные пошли. Они идут через StreamDataInserted по одной строке. Когда некий объем данных заканчивается, приходит StreamDataEnd. Мне интересно, как часто Plaza выдает событие StreamDataEnd. Хочу в ближайшие пару дней запустить какую-нибудь тестовую программу на пару часов и посмотреть. Если прерывания случаются часто, то действительно можно копить строки (записи) в PlazaStreamManager и выдавать клиенту, например, DataTable или DataRow[] и т.д. Вместе с этим, мне кажется, нужно дать возможность клиенту тоже получать наш вариант StreamDataInserted, тем более что кроме него там еще есть StreamDataUpdated и StreamDataDeleted. В этих событиях можно через PlazaFormatter конвертировать данные в .Net'овские, помещать их в List<object> и выдавать последний клиенту, как object[].

Последнее, насчет фильтрации. Можно будет предусмотреть некий интерфейс IPlazaFilter с методом bool Validate(CP2Record rec, + что-нибудь еще). В методе PlazaStreamManager, который создает новый стрим, можно передавать IEnumerable<IPlazaFilter> или null, который будет привязываться к конкретному стриму. Тогда PlazaStreamManager будет перебирать для каждого стрима его IEnumerable<IPlazaFilter> в событиях StreamDataInserted / StreamDataUpdated / StreamDataDeleted, и если какой-то IPlazaFilter возвращает false, не выдавать событие с данными клиенту.
Спасибо:

aspirant

Фотография
Дата: 24.01.2011
Ответить


skuvv
Mikhail Sukhov
aspirant
Вчера разбирался со схемами таблиц потоков. Хочу выложить мои соображения:


Да, с точностью получился косяк. Надо исправлять.

skuvv, вы все еще на метаданных? Тогда не пропустите момент, который указал aspirant.

Добавил для всех сделанных мета-таблиц соответствующий PlazaType для decemical и string


Круто[biggrin]. Я только собрался писать об этом изменении. Даже сам еще свои таблицы не исправил.
Спасибо:

aspirant

Фотография
Дата: 29.01.2011
Ответить


Только что залил изменения. Хотел поделиться промежуточными итогами:
  1. В класс PlazaColumns добавил три поля:
    ReplicationStream ReplicationStream { get; }
    string Table { get; }
    ReplicationScheme ReplicationScheme { get; }
    Пока сделал их все virtual, чтобы код компилировался, но вообще первые два поля должны быть abstract, чтобы все классы-наследники их переписали для себя. Правильные объявления я пока закомментил. Эти три поля часть метаданных (у каждого наследника PlazaColumns может быть только один набор значений ReplicationStream - ReplicationScheme - Table) и нужны для инициализации PlazaTable, чтобы потом можно его было передать в PlazaStream или просто сохранить на диск через PlazaTableSerializer.
  2. Написал первый вариант PlazaStreamManager: пока только создает / удаляет объекты PlazaStream и перехватывает их события. Весь "ум" из класса PlazaStream убрал. Теперь это по сути обертка для CP2DataStreamClass. Его нужно будет протестировать со всеми наследниками наследника PlazaColumns на предмет правильности описания метаданных. Я его тестировал с PlazaRtsIndexColumns и еще парой классов. Кстати, при запуске метода Start() PlazaStreamManager начинает заметно подтормаживать GUI-поток .Net'овскго тестового проекта.
  3. Получение данных пока только получалось тестировать после работы: приходит сразу некая порция строк плазовского потока репликации и все. Днем один раз получилось запустить PlazaStream + PlazaRtsIndexColumns: данные сыпались непрерывно где-то минут пять точно, потом мне нужно было идти.

Хотелось получить ваши комментарии, рекомендации и т.д., после чего продолжу работу на PlazaStreamManager. Там еще полно дел. Кроме того еще нужно дописать PlazaTableSerializer.
Спасибо:

aspirant

Фотография
Дата: 29.01.2011
Ответить


Кстати, только что заметил, что мой PlazaRtsIndexColumns дублируется с PlazaIndexColumns. Сейчас удалю свое детище[sad]
Спасибо:

skuvv

Фотография
Дата: 30.01.2011
Ответить


Добавил класс с кодами ошибок плазы - PlazaErrors
парсит код ошибки и возвращает текст
ps ктото начал заниматься ошибками - пользуйтесь
Спасибо:

Mikhail Sukhov

Фотография
Дата: 30.01.2011
Ответить


aspirant
Кстати, только что заметил, что мой PlazaRtsIndexColumns дублируется с PlazaIndexColumns. Сейчас удалю свое детище[sad]


А csproj до сих пор на него ссылается. Коммитить нужно все атомарно.
Спасибо:

Mikhail Sukhov

Фотография
Дата: 30.01.2011
Ответить


aspirant

Хотелось получить ваши комментарии, рекомендации и т.д., после чего продолжу работу на PlazaStreamManager. Там еще полно дел. Кроме того еще нужно дописать PlazaTableSerializer.


1. Плохой код.

Код
try
{
    _dataStream.Close();
}
catch (System.Runtime.InteropServices.COMException e)    
{
    // Исправить обработку исключения
    System.Diagnostics.Trace.WriteLine("Exception {0:X}: {1}".Put(e.ErrorCode, e.Message));
}


Исключения нужно перехватывать как можно выше. Кто будет вызывать Close, тот пусть и этим занимается. А так ошибка просто проглотиться.

3.
Код
_dataStream.TableSet.set_rev(plazaTable.Name, _currentRevision++);
Это меняется на более элегантное, как подсказал R#:
Код
_dataStream.TableSet.rev[plazaTable.Name] = _currentRevision++;


4. ReplicationStream и ReplicationScheme явно как то не так используется. Это же уровень метаданных, а именно таблица PlazaTable (таблица олицетворяет стрим данных, PlazaStream по этом олицетворению производит подключение). А получилось так, что эти два перечисления размазались по всем практически классам в Плазе. Нехорошо. Конструктора PlazaStream(PlazaTable plazaTable, TRequestType requestType) более чем достаточно. Зачем нужен еще один я не понял.

5. public void AddStream(string key, PlazaColumns schema, IEnumerable<PlazaColumn> columns) Выглядит как то не так. Зачем столько аргументов? Можно же ведь передать один PlazaTable и уже по нему создать стрим, и уже оперировать им в дальнейшем.
Спасибо:
<< < 4 5 6 7 8  >

Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy