Комментарии и предложения
Atom Ответить
11.03.2011


Заметил пару нюансов по PlazaTrader:
1)
Код

_plazaStreamManager = new PlazaStreamManager(_plazaConnectionPool, TRequestType.RT_COMBINED_DYNAMIC, 1000);

Почему рекваест тайп фиксированный? надо конкретно задавать, например у меня так было:
Цитата:

"FORTS_FUTAGGR20_REPL" - RT_REMOTE_ONLINE
"FORTS_FUTTRADE_REPL" - RT_REMOTE_ONLINE
"FORTS_FUTINFO_REPL" - RT_COMBINED_DYNAMIC
"FORTS_FUTCOMMON_REPL" - RT_REMOTE_ONLINE
"FORTS_POS_REPL" - RT_COMBINED_DYNAMIC
"FORTS_PART_REPL" - RT_COMBINED_DYNAMIC
"FORTS_VM_REPL" - RT_COMBINED_DYNAMIC

Допустим если FORTS_FUTCOMMON_REPL задать в RT_COMBINED_DYNAMIC, то при реконнекте будет перекачиваться весь поток заново.
+Revision тоже надо указывать в некоторых потоках.
2) в PlazaStreamManager void Run()
Не обрабатывает состояния типа DS_STATE_ERROR или DS_STATE_CLOSE, те в случае чего будет затык и поток будет висеть закрытым или с ошибкой.
Я для себя брал реализацию с примера(могу выложить если что)
PS У меня несколько сместились приоритеты - придется задержаться на квике, но постораюсь не пропадать.

Теги:


Спасибо:




60 Ответов
1 2 3  >
aspirant

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


skuvv Перейти
Почему рекваест тайп фиксированный?

Посмотрю в документации, спасибо за то, что обратил внимание.

skuvv Перейти

2) в PlazaStreamManager void Run()
Не обрабатывает состояния типа DS_STATE_ERROR или DS_STATE_CLOSE, те в случае чего будет затык и поток будет висеть закрытым или с ошибкой.
Я для себя брал реализацию с примера(могу выложить если что)

Эти состояния обрабатываются методом PlazaStream.Poll(CP2ConnectionClass connection). См. строчку 174
Код
item.Stream.Poll(item.Connection);

Я тоже брал реализацию с примераSmile. При тесте некоторые потоки открывались не с первого раза: затыков не было.
Спасибо:

skuvv

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


aspirant

Я тоже брал реализацию с примераSmile. При тесте некоторые потоки открывались не с первого раза: затыков не было.

Тогда все ок Smile
Автор топика
Спасибо:

skuvv

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


Вопрос по _PlazaTrader.StartListeners()
Каким образом планируется добавлять потоки? Сейчас по общему типу PlazaMarketData.
Не лучше ли явно задавать (StreamName,TableName,TRequestType) ?
допустим все StreamName в списке - просто выбираем из enum списке,
потом на основе выбронного StreamName, выбираем из Dictionary<enum StreamName,enum TableName> выбираем TableName
подготавлием метаданные(default загатовку для соответсвующей TableName) и подписываем поток.
StreamName и TableName подготовить не проблема и народу понятно по документации будет, что где.
PS Средней руки юзер типа меня не осилит процесс подписки(то что идет внутри StartListeners()), слишком замудренно BigGrin
Автор топика
Спасибо:

skuvv

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


С выбором Dictionary я ошибся...
Тогда как вариант - единый enum список с названиями типа StreamName_TableName.
Чтото Например FORTS_FUTTRADE_REPL_orders_log
А уже на приеме парсить сроку, все стримы оканчиваются на REPL.
Автор топика
Спасибо:

aspirant

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


skuvv Перейти
Вопрос по _PlazaTrader.StartListeners()


Это был пока черновой вариант. Сегодня появились мысли, как все это сделать попроще. Надеюсь выложить новую версию с комментариями в ближайшие дни.
Спасибо:

aspirant

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


aspirant Перейти
Сегодня появились мысли, как все это сделать попроще.


Только что залил коммит:
  1. Удалил всякий мусор (PlazaDataBuffer, PlazaColumnSet)
  2. Переименовал PlazaTable в PlazaSystemTable.
  3. Добавил класс PlazaTable для клиентской подписки к потокам. Внутри него есть массив PlazaRecord[], в который попадают данные из потоков.
  4. Добавил в PlazaTrader метод public void StartListeners(params PlazaTable[] tables) для подписки на любые таблицы. Вот код клиентской подписки к двум потокам:
    Код
    var optSessionTable = new PlazaTable(PlazaColumns.OptionSessionContents);
    var rtsIndexTable = new PlazaTable(PlazaColumns.RtsIndex);
    _plazaTrader.StartListeners(rtsIndexTable, optSessionTable);

    В обоих случаях запрашиваются все колонки (поля) таблиц потоков Плазы. Если нужны не все колонки, можно использовать другой конструктор PlazaTable, в котором есть параметр IEnumerable<PlazaColumn> columns. Данные отлавливаются в событии public event Action<PlazaRecord[]> DataReceived; класса PlazaTable


Теперь насчет метода public void StartListeners(PlazaMarketData marketData). Он нужен для перегонки данных потоков в стандартные объекты, например создания коллекций инструментов и т.д., и поэтому нам необходимо контроллировать, какие подписки создаются и с каким набором колонок (полей). Любые другие предложения приветствуются.
Спасибо:

skuvv

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


Я это и имел ввидуThumpUp
в блоке
Код

            foreach (var fieldInfo in this.GetType().GetFields().Where(x => x.FieldType == typeof(PlazaColumn)))
            {
                if (!(fieldInfo.Name == "ReplId" || fieldInfo.Name == "ReplRev" || fieldInfo.Name == "ReplAct"))
                    result.Add((PlazaColumn)fieldInfo.GetValue(this));
            }

В некоторых таблицах добавляются одинаковые поля, например таблица FuturesSessionContents, поле MinStep
Автор топика
Спасибо:

aspirant

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


skuvv Перейти
В некоторых таблицах добавляются одинаковые поля, например таблица FuturesSessionContents, поле MinStep


Потому что тот (не я BigGrin), кто расписывал класс PlazaFuturesSessionContentsColumns, забыл исправить название поля Плазы, когда копировал переменные:
Код
this.StepPrice = new PlazaColumn(PlazaTableRegistry.FutSessionContents, "min_step", typeof(decimal), "d16.5", true);


Я только что залил исправление.

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

Спасибо:

skuvv

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


aspirant Перейти
skuvv Перейти
В некоторых таблицах добавляются одинаковые поля, например таблица FuturesSessionContents, поле MinStep


Потому что тот (не я BigGrin), кто расписывал класс PlazaFuturesSessionContentsColumns, забыл исправить название поля Плазы, когда копировал переменные:
Код
this.StepPrice = new PlazaColumn(PlazaTableRegistry.FutSessionContents, "min_step", typeof(decimal), "d16.5", true);


Я только что залил исправление.

Не заметил ночью BigGrin
Цитата:

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

Займусь этим

Автор топика
Спасибо:

skuvv

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


потоки FuturesAggregation не работают(не получают данные после выхода в онлайн режим), в логах клиента error:
есть подозрение на lifenumber метатаблицы
Цитата:

2011-03-18 15:28:05.305;p2mq-cli;;MQ library started.
2011-03-18 15:28:05.309;p2repl-cli;;Client replication library started
2011-03-18 15:28:05.321;p2mq-cli;;Socket connected;conn 0x911DC14;host 'localhost';port 4001
2011-03-18 15:28:05.323;p2mq-cli;;Connection 0x911DB30 connected; connID 1
2011-03-18 15:28:07.085;p2mq-cli;;Socket connected;conn 0x9139B64;host '127.0.0.1';port 4001
2011-03-18 15:28:07.087;p2mq-cli;;Connection 0x9139A80 connected; connID 2
2011-03-18 15:28:07.096;p2repl-cli;;Stream created;stream 0xA442FA8
2011-03-18 15:28:07.096;P2ReplStorage;;Revs were inited; stream 0x0; cnt 1
2011-03-18 15:28:07.096;P2ReplStorage;; tbl_idx 0; cur_rev 1
2011-03-18 15:28:07.097;P2ReplStorage;;Basic policy created;stream 0x0,policy 0xA440EB8
2011-03-18 15:28:07.116;p2repl-cli;;Stream opening started;stream 0xA442FA8,type 2,name 'FORTS_FUTAGGR5_REPL',server_addr 'FINTER_FORTS3.inter_futaggr5'
2011-03-18 15:28:07.135;p2repl-cli;;Stream opened;stream 0xA442FA8;channel 0x4CF4F0D1358
2011-03-18 15:28:07.135;P2ReplStorage;;Revs were cleared after lifenum change; stream 0xA442FA8; cnt 1
2011-03-18 15:28:07.135;P2ReplStorage;; tbl_idx 0; cur_rev 0
2011-03-18 15:28:07.140;p2repl-cli;;CLOSE message posted;stream 0xA442FA8
2011-03-18 15:28:07.142;p2repl-cli;error;p2err 40962=0xA002 - 'REPL:OBJECT_CHANGED__';Stream state was changed;stream 0xA442FA8
2011-03-18 15:28:07.142;p2repl-cli;error;p2err 40962=0xA002 - 'REPL:OBJECT_CHANGED__';Couldn't start scheme setting (auto);stream 0xA442FA8
2011-03-18 15:28:07.143;P2ReplStorage;;Basic policy deleted;stream 0xA442FA8,policy 0xA440EB8
2011-03-18 15:28:07.148;P2ReplStorage;;Revs were inited; stream 0x0; cnt 1
2011-03-18 15:28:07.148;P2ReplStorage;; tbl_idx 0; cur_rev 2
2011-03-18 15:28:07.148;P2ReplStorage;;Basic policy created;stream 0x0,policy 0xA448968
2011-03-18 15:28:07.169;p2repl-cli;;Stream opening started;stream 0xA442FA8,type 2,name 'FORTS_FUTAGGR5_REPL',server_addr 'FINTER_FORTS3.inter_futaggr5'
2011-03-18 15:28:07.189;p2repl-cli;;Stream opened;stream 0xA442FA8;channel 0x4D04F0D1358
2011-03-18 15:28:07.190;p2repl-cli;;Scheme setting started;stream 0xA442FA8
2011-03-18 15:28:07.209;p2repl-cli;;Scheme is set;stream 0xA442FA8;channel 0x4D04F0D1358
2011-03-18 15:28:07.209;p2repl-cli;;Statistics module for table 'orders_aggr' was successfully registered
2011-03-18 15:28:07.210;p2repl-cli;;Statistics was registered;stream name FORTS_FUTAGGR5_REPL
2011-03-18 15:28:07.213;p2repl-cli;;Data requested;stream 0xA442FA8;channel 0x4D04F0D1358;session 0
2011-03-18 15:28:07.232;p2repl-cli;;DATA message received;stream 0xA442FA8
2011-03-18 15:28:07.232;p2repl-cli;;Stream is on-line;stream 0xA442FA8
Автор топика
Спасибо:

skuvv

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


Пофиксил
_dataStream.Close(); не нужно в OnStreamLifeNumChanged
Автор топика
Спасибо:

skuvv

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


Проверил и пофиксил все таблицы(метаданные) начинающиеся на Futures. Можно принимать.
Автор топика
Спасибо:

skuvv

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


События OnNewDataFromFuturesSessionContents и OnNewDataFromOptionSessionContents
иногда не заполняют полностью Security - только создается new Security по id.
Возможно метод GetSecurity не thread safe
Автор топика
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 25.03.2011
Ответить


skuvv Перейти
События OnNewDataFromFuturesSessionContents и OnNewDataFromOptionSessionContents
иногда не заполняют полностью Security - только создается new Security по id.
Возможно метод GetSecurity не thread safe


Больше вероятность, что при инициализации происходит ошибка. А GetSecurity сначала добавляется Security, и только уже потом вызывается делегат на заполнение полей. Вот там видимо и падает. Подозреваю, что не все понял проводятся. Например:

Код
sec.MaxPrice = record[metadata.LimitUp].To<double>();


может упасть, если неправильный тип данных (например, РТС прислала пустое значение). Посмотрите на ProcessDataError.
Спасибо:

aspirant

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


Mikhail Sukhov Перейти
может упасть, если неправильный тип данных (например, РТС прислала пустое значение)

Если будет неправильный тип данных, внутри обработчиков OnNewDataFromFuturesSessionContents и OnNewDataFromOptionSessionContents произойдет исключение. Я сначала пытался конвертировать данные из потока в DateTime через extenstion-метод To<DateTime>(). У меня срабатывало исключение. Потому уже воспользовался любезно кем-то добавленным PlazaRecord.GetAsDateTime().

Еще: надо было мне конечно предупредить, что я еще не дописал методы StartExport и StopExport. Сейчас, когда начал заливать PlazaTrader, увидел обновления skuvv'a. Вроде все вместе смержил.

Вопросы: все стандартные потоки добавлены?
Предложенная skuvv'ом фильтрация подойдет? Я вроде видел, что у PlazaTrader есть свой стандартный интерфейс влкючения/выключения фильтрации (RegisterSecurity/UnregisterSecurity)?
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 25.03.2011
Ответить


aspirant Перейти

Предложенная skuvv'ом фильтрация подойдет? Я вроде видел, что у PlazaTrader есть свой стандартный интерфейс влкючения/выключения фильтрации (RegisterSecurity/UnregisterSecurity)?


Мне не нравиться:

1. Делается тоже самое, что и через RegisterXXX, но требует изменение внешнего контракта.
2. Я думал фильтр передается внутрь стрима. Делать фильтр в самой PlazaTrader как-то не очень.
3. Операция Exists очень медленная (фактически там полный перебор). На потоке тиков и стаканов все помрет.
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 25.03.2011
Ответить


aspirant Перейти
Я сначала пытался конвертировать данные из потока в DateTime через extenstion-метод To<DateTime>(). У меня срабатывало исключение. Потому уже воспользовался любезно кем-то добавленным PlazaRecord.GetAsDateTime().



  1. Все методы по переводу в и из плазовский формат нужно переносить в специальный класс - PlazaFormatter.
  2. Работа с PlazaRecord требует рефакторинг (прямо таки кричит):

    1. Код
      readonly List<KeyValuePair<string, object>> _data = new List<KeyValuePair<string, object>>();
      Это кто так учил писать?Smile Нужно заменить на Dictionary.
    2. PlazaColumnList.Names не нужно ни в коем случае. Мы не работает со строчками. Мы работает с колонками - PlazaColumn. Соответственно, ключом в _data должен быть не string а PlazaColumn.
    3. Индексаторы у PlazaRecord не нужны. Лучше сделать в нем метод вида T Get<T>(PlazaColumn), который бы конвертировал значение и при возникновении ошибки, перехватывал бы ее и выбрасывал свою с описанием того, что за колонка, что пришло на вход. Так пользователю будет проще понять ошибку (да и нам).

  3. Опять возвращаемся к метаданным. Не нужно передавать в PlazaListener PlazaColumns. PlazaColumns - это абстрактный базовый класс для всех колонок. Для ограничения колонок необходимым нам множеством полей нужно использовать PlazaTable.Columns. Еще раз. PlazaTable - это как раз те настройки, которые описываю наши схемы на клиенте. PlazaColumns - базовый вспомогательный класс. PlazaColumnRegistry - коллекция всех возможных колонок. PlazaTableRegistry - коллекция всех возможных таблиц.
Спасибо:

skuvv

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


aspirant

Вопросы: все стандартные потоки добавлены?
Предложенная skuvv'ом фильтрация подойдет? Я вроде видел, что у PlazaTrader есть свой стандартный интерфейс влкючения/выключения фильтрации (RegisterSecurity/UnregisterSecurity)?

Это наброски, понятно что надо все напильником доделывать.
К примеру я сравнил проект со своей старой программой plaza2, данные в текущий s# проект поступают медленнее на 6-10мс(время снимал с OnNewSecurityChanged к примеру). А если включить реал плазу и стаканы глубиной 50, проект может не взлететь вообще )

Автор топика
Спасибо:

aspirant

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


Mikhail Sukhov Перейти
Все методы по переводу в и из плазовский формат нужно переносить в специальный класс - PlazaFormatter.


Добавил для плазовской даты. Так подойдет:
Код
sec.ExpiryDate = record[metadata.DateEndTrade].ToString().FromPlazaString<DateTime>();
// или сделать:
sec.ExpiryDate = record[metadata.DateEndTrade].FromPlazaType<DateTime>();


Mikhail Sukhov Перейти
Код
readonly List<KeyValuePair<string, object>> _data = new List<KeyValuePair<string, object>>();
Это кто так учил писать?Smile Нужно заменить на Dictionary.
PlazaColumnList.Names не нужно ни в коем случае. Мы не работает со строчками. Мы работает с колонками - PlazaColumn. Соответственно, ключом в _data должен быть не string а PlazaColumn.


Знаю, что кричит. Но когда ключом был string, нужно было использовать такого монстра, чтобы работал индексатор по номеру колонки. Dictionary отсортировал бы свои элементы по алфавиту (ключи ведь string).

Сейчас я переделал на Dictionary с ключом PlazaColumn. Крик ушелSmile

Mikhail Sukhov Перейти
Индексаторы у PlazaRecord не нужны. Лучше сделать в нем метод вида T Get<T>(PlazaColumn)

Добавил. Посмотри, пожалуйста. Кстати, я все-таки оставил индексатор по PlazaColumn.

Mikhail Sukhov Перейти
Опять возвращаемся к метаданным...

Я изменил класс PlazaListener. Посмотри, пожалуйста, нужны твои комментарии + желательно кусок псевдокода - твое видение, как пользователь создает таблицу с набором колонок для передачи ее в PlazaListener.
Спасибо:

aspirant

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


skuvv Перейти

К примеру я сравнил проект со своей старой программой plaza2, данные в текущий s# проект поступают медленнее на 6-10мс(время снимал с OnNewSecurityChanged к примеру).


Получается, ты делал свою реализацию PlazaTrader?
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 26.03.2011
Ответить


aspirant Перейти
Dictionary отсортировал бы свои элементы по алфавиту (ключи ведь string).


Ты путаешь с SortedDictionary. И то там не по алфавиту... Это хеш алгоритм. Там сортировка не нужна. Группировка значения идет по хэшу ключа. Соответственно, когда обращаемся по ключу, сначала берется его хэш (PlazaColumn.GetHashCode) и получаются все значения, соответствующие хэшу. Операция O(1). И далее, если у нас коллизия, перебором всех ключей идет сравнение (PlazaColumn.Equals) и находится первый попавшийся (ага, уникальность там не проверяется).

Итого, в лучшем варианте O(1). В худшем O(n). Но чтобы добиться последнее, надо еще постараться.Smile
Спасибо:

aspirant

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


Mikhail Sukhov Перейти
aspirant Перейти
Dictionary отсортировал бы свои элементы по алфавиту (ключи ведь string).


Ты путаешь с SortedDictionary. И то там не по алфавиту... Это хеш алгоритм. Там сортировка не нужна. Группировка значения идет по хэшу ключа. Соответственно, когда обращаемся по ключу, сначала берется его хэш (PlazaColumn.GetHashCode) и получаются все значения, соответствующие хэшу. Операция O(1). И далее, если у нас коллизия, перебором всех ключей идет сравнение (PlazaColumn.Equals) и находится первый попавшийся (ага, уникальность там не проверяется).

Итого, в лучшем варианте O(1). В худшем O(n). Но чтобы добиться последнее, надо еще постараться.Smile


Да, насчет сортировки я был не прав.
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 26.03.2011
Ответить


aspirant Перейти
Я изменил класс PlazaListener. Посмотри, пожалуйста, нужны твои комментарии + желательно кусок псевдокода - твое видение, как пользователь создает таблицу с набором колонок для передачи ее в PlazaListener.


Посмотрел и доделал кое-что.

Рассмешило название PlazaPartColumns. Долго думал, что за "часть". Оказалось, это Партфэл, дарагой!

Что осталось до переделать:

  1. Сейчас PlazaListener создается в самом начале со всеми колонками. Как я уже писал, использовать надо только те колонки, что определены схемами PlazaTable.Columns.
  2. PlazaListener выглядит как лишний класс (возможно, что в него потом будет засунута еще какая-то логика, если да, то какая?). Что он делает сейчас. Берет данные из PlazaStream и передает их в PlazaTrader. Тоесть, такой бюрократически посредник, который бумажки из стола на стол несет.
  3. enum TableName лучше сделать статическим классом со строковыми константами. Я так понял, такие безобразные названия нужны лишь для того, чтобы ini файлы создавать? Если да, то по логике простой. Мы создаем текстовый файл, используем string. Вся логика в имени полей TableName - приведение в string... Так может тогда сразу сделать string?
  4. Давайте подумаем насчет фильтрации. Сейчас это выглядит как то не очень. Аспирант, ты же вроде как уже что-то делал по фильтрам?
  5. PlazaSchemaParser предлагаю упрятать в PlazaTableSerializer.

Спасибо:

skuvv

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


aspirant Перейти
skuvv Перейти

К примеру я сравнил проект со своей старой программой plaza2, данные в текущий s# проект поступают медленнее на 6-10мс(время снимал с OnNewSecurityChanged к примеру).


Получается, ты делал свою реализацию PlazaTrader?

Нет у меня не интерфейс как в s#, а напрямую работа c потоками и событиями
Автор топика
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 26.03.2011
Ответить


skuvv Перейти
aspirant Перейти
skuvv Перейти

К примеру я сравнил проект со своей старой программой plaza2, данные в текущий s# проект поступают медленнее на 6-10мс(время снимал с OnNewSecurityChanged к примеру).


Получается, ты делал свою реализацию PlazaTrader?

Нет у меня не интерфейс как в s#, а напрямую работа c потоками и событиями


Может выложить это ввиде отдельного теста для сравнения перфоманса? Насчет OnNewSecurityChanged - конечно. Если вместо поиска по словарю устраивать Exist Find и т.д., то я не удивлюсь и пол минутными задержками.Smile
Спасибо:
1 2 3  >

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

loading
clippy