← Zurück

Публичный бета тестинг

Выложил PlazaTrader на http://box.net/plaza Исходники самого PlazaTrader, исходники примера, Plaza dll и Plaza + S# dll (последнее не нужно, если уже используется S#).

В следствие бета тестирования буду обновлять только библиотеку Ecng.Trading.Plaza.dll. В релиз войдет все. Налетаем.🙂

upd Теперь PlazaTrader часть дистрибутива S#, поэтому просто качайте последнюю версию http://box.net/stocksharp/ . Сборка называется StockSharp.Plaza.dll

Kommentare (66)

Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen

Stanislav121
Stanislav121

Скажите пожалуйста, роботов написанных под Plaza 2 нужно будет сертифицировать на РТС?

esper
esper

Добрый день, несмотря на то, что класс PlazaErrors еще нигде не используется, по нему есть несколько предложений:

  1. наверное объявление _plazaErrorGroup должно быть последним, static-члены вроде инициализируются в порядке объявления
  2. заменить метод GetErrorText на такой

public static string GetErrorText(int errorCode)
{
    int key = (errorCode & 0x1FFFF) >> 4;
    int index = (errorCode & 0xFFF);
            
    if (_plazaErrorGroup.ContainsKey(key))
    {
        var group = _plazaErrorGroup[key];

        if (index <= group.Count)
            return group[index];
        else
            return "error type not found: " + errorCode;
    }
    else
        return "error type not found: " + errorCode;
}

и сдвинуть все ключи в _plazaErrorGroup на 4, так вроде понятнее и короче🙂

Mikhail Sukhov
Mikhail Sukhov Autor

esper: Добрый день, несмотря на то, что класс PlazaErrors еще нигде не используется, по нему есть несколько предложений:

А есть понимание того, что там вообще происходит в этом классе?🙂

esper
esper

Думаю, что есть. В COMException есть ErrorCode, вот по нему можно получить дополнительные данные по ошибке, а не просто "Couldn't connect to MQ"

Mikhail Sukhov
Mikhail Sukhov Autor

esper: Думаю, что есть. В COMException есть ErrorCode, вот по нему можно получить дополнительные данные по ошибке, а не просто "Couldn't connect to MQ"

Ок, тогда может я дам доступ и поправите самостоятельно?

esper
esper

Да, могу поправить.

esper
esper
  1. Внес изменения в PlazaErrors. Далее предлагаю в PlazaException вместо кода ошибки выводить ее краткое описание.

  2. PlazaException сейчас используется только в транзакциях, может в функциях подключения, отключения и т.д. стоит заменить InvalidOperationException на PlazaException?

  3. Сейчас для подключения к роутеру используется TCP? Если подключаемся на localhost, может стоит подключаться через LRPCQ?

aspirant
aspirant
aspirant

esper: PlazaException сейчас используется только в транзакциях, может в функциях подключения, отключения и т.д. стоит заменить InvalidOperationException на PlazaException?

Я как-то тоже поднимал этот вопрос. Предлагаю решить голосованием. Я за PlazaException.

esper: Сейчас для подключения к роутеру используется TCP? Если подключаемся на localhost, может стоит подключаться через LRPCQ?

Очень интересно, у меня была старая версия P2ClientGate.doc, где про LRPCQ ничего не было. Покопавшись в форуме РТС, нашел вот это.

Mikhail Sukhov
Mikhail Sukhov Autor

esper:

  1. Внес изменения в PlazaErrors.

Изначально PlazaErrors был создан с ошибкой. Если посмотреть документацию (в самом конце), то там есть некие числовые константы (некоторые равны друг другу). Так что, это вовсе не строчки. Строчки - это ошибка автора этого класса.

Mikhail Sukhov
Mikhail Sukhov Autor

aspirant: Я как-то тоже поднимал этот вопрос. Предлагаю решить голосованием. Я за PlazaException.

Я тоже за, если не лепить везде это исключение. Где его предлагаете применить?

esper
esper

Mikhail Sukhov: Изначально PlazaErrors был создан с ошибкой. Если посмотреть документацию (в самом конце), то там есть некие числовые константы (некоторые равны друг другу). Так что, это вовсе не строчки. Строчки - это ошибка автора этого класса.

Не совсем понял вышесказанное, в документации указано как по полученному коду ошибки можно получить символьный код ошибки, который для нас более понятен, что понимается под "строчкой"?

Mikhail Sukhov
Mikhail Sukhov Autor

esper:

Mikhail Sukhov: Изначально PlazaErrors был создан с ошибкой. Если посмотреть документацию (в самом конце), то там есть некие числовые константы (некоторые равны друг другу). Так что, это вовсе не строчки. Строчки - это ошибка автора этого класса.

Не совсем понял вышесказанное, в документации указано как по полученному коду ошибки можно получить символьный код ошибки, который для нас более понятен, что понимается под "строчкой"?

Например, выращежение P2ERR_MSG_FIELD_NOT_FOUND = P2ERR_MSG_BEGIN говорит о том, что идентификатор P2ERR_MSG_FIELD_NOT_FOUND равен началу блока P2ERR_MSG_BEGIN, который в свою очередь равен 0x8000.

В классе же PlazaErrors сейчас это представлено в виде строчки. Это так и должно быть? Я не 100% уверен, но думаю тут глюк в дизайне.

aspirant
aspirant

esper: Сейчас для подключения к роутеру используется TCP? Если подключаемся на localhost, может стоит подключаться через LRPCQ?

Сделал

Mikhail Sukhov
Mikhail Sukhov Autor

aspirant:

esper: Сейчас для подключения к роутеру используется TCP? Если подключаемся на localhost, может стоит подключаться через LRPCQ?

Сделал

Получил боевой логин. Если качать с нулевой ревизии как сейчас, то старт примера занимает около 10 минут. Поэтому, предлагаю сделать следующие:

  1. Для этой версии все таки ввернуть поддержку базового клиента (в виде опции). Надеюсь, это не сложно.
  2. Для следующей сделать собственную версию базы (чтобы хранить родные для S# торговые объекты, а не плазовские).
esper
esper

Mikhail Sukhov: Получил боевой логин. Если качать с нулевой ревизии как сейчас, то старт примера занимает около 10 минут. Поэтому, предлагаю сделать следующие:

  1. Для этой версии все таки ввернуть поддержку базового клиента (в виде опции). Надеюсь, это не сложно.
  2. Для следующей сделать собственную версию базы (чтобы хранить родные для S# торговые объекты, а не плазовские).

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

Mikhail Sukhov
Mikhail Sukhov Autor

esper: А если просто ревизии по таблицам сохранять между сессиями? Тогда при переподключении будем скачивать только новые данные.

Аспирант говорит, что так мы поимеем неправильный стакан. Плюс пропадут данные за текущую сессию.

esper
esper

Mikhail Sukhov: Аспирант говорит, что так мы поимеем неправильный стакан. Плюс пропадут данные за текущую сессию. Ревижины можно сохранять не для всех таблиц. Для агрегированых заявок можно не сохранять, записей там не очень много, т.е. данные там меняются часто, но число записей не велико, или не так?

aspirant
aspirant

Mikhail Sukhov: Для этой версии все таки ввернуть поддержку базового клиента (в виде опции). Надеюсь, это не сложно. Начал заниматься.

Mikhail Sukhov: Получил боевой логин. Интереса ради, что для этого нужно сделать и каких это стоит денег?

Mikhail Sukhov
Mikhail Sukhov Autor

aspirant:

Mikhail Sukhov: Получил боевой логин. Интереса ради, что для этого нужно сделать и каких это стоит денег?

Ты уже ответил, ради интереса. 2 штуки в месяц у Цериха.

aspirant
aspirant

aspirant:

Mikhail Sukhov: Для этой версии все таки ввернуть поддержку базового клиента (в виде опции). Надеюсь, это не сложно.Начал заниматься.

Привинчиваем к SQL Server'у (ODBC) или .db файлам (SQL3Lite)? Последние проще настроить, но я с ними раньше не имел дела вообще.

aspirant
aspirant

Mikhail Sukhov: 2 штуки в месяц у Цериха.

Подключение напрямую к серверу Плазы или через брокера?

Mikhail Sukhov
Mikhail Sukhov Autor

aspirant: Привинчиваем к SQL Server'у (ODBC) или .db файлам (SQL3Lite)? Последние проще настроить, но я с ними раньше не имел дела вообще.

Думаю, лучше последнее. Я тоже не работал, но меня прельщает название Lite🙂

Alexander
Alexander

aspirant:

aspirant:

Mikhail Sukhov: Для этой версии все таки ввернуть поддержку базового клиента (в виде опции). Надеюсь, это не сложно.Начал заниматься.

Привинчиваем к SQL Server'у (ODBC) или .db файлам (SQL3Lite)? Последние проще настроить, но я с ними раньше не имел дела вообще.

Лучше к SQLite.

aspirant
aspirant

Alexander: Лучше к SQLite. Хорошая штука. Уже скачал и интегрировал в VS2010. Теперь можно db-файлы смотреть.

aspirant
aspirant

esper:

Mikhail Sukhov:

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

Добавить одну строчку действительно было несложно:

this.DataStream.DBConnString = "P2DBSQLite3.dll;sqlite3.ini;{0}.db".Put(this.Table.UniqueName.Replace('\\', '_'));

Но при тестировании возникла проблема: если между сессиями меняешь набор колонок в таблице, приходится удалять db файл, и получать данные с нуля. То есть, если пользователь запустил PlazaTrader, инициализировал таблицу 1 с колонками 1,2,3,4, накачал данных, вышел. Подумал-подумал, понял, что нужна еще колонка 5, и добавил ее в инициализацию. Снова запустил PlazaTrader и получил исключение, потому что в db файле в таблице только колонки 1,2,3,4, а плазовсий роутер не умеет менять схему таблиц в db файлах, он только создает их с нуля.

Еще: я до конца не разобрался, но, вроде, вытаскивать данные из локальной базы данных (db файл или SQL Server) мы должны сами.

Подводя итог, предлагаю временный гибридный вариант:

  • стаканы: ЛИБО делаем все колонки обязательными (там только одна необязательная: Moment) и при старте получаем данные из локального хранилища, ЛИБО каждый раз получаем с нуля.
  • все остальное: храним ревижены между запусками.

Еще 2: у всех таблиц есть индексы (см. ini файлы-схемы). Для безбазового клиента они не нужны, поэтому я их не делал (нужно лопатить каждый класс в метаданных). Без индексов таблицы создаются, но они ведь не зря указываются в файлах-схемах.

esper
esper

Например, выращежение P2ERR_MSG_FIELD_NOT_FOUND = P2ERR_MSG_BEGIN говорит о том, что идентификатор P2ERR_MSG_FIELD_NOT_FOUND равен началу блока P2ERR_MSG_BEGIN, который в свою очередь равен 0x8000.

В классе же PlazaErrors сейчас это представлено в виде строчки. Это так и должно быть? Я не 100% уверен, но думаю тут глюк в дизайне.

Вопрос в том, какие преимущества будут при использовании enum-а, если основная задача класса представить код 0x8000 в более понятном формате

Mikhail Sukhov
Mikhail Sukhov Autor

Например, выращежение P2ERR_MSG_FIELD_NOT_FOUND = P2ERR_MSG_BEGIN говорит о том, что идентификатор P2ERR_MSG_FIELD_NOT_FOUND равен началу блока P2ERR_MSG_BEGIN, который в свою очередь равен 0x8000.

В классе же PlazaErrors сейчас это представлено в виде строчки. Это так и должно быть? Я не 100% уверен, но думаю тут глюк в дизайне.

Вопрос в том, какие преимущества будут при использовании enum-а, если основная задача класса представить код 0x8000 в более понятном формате

Никаких, наверное. Я пока для себя пытаюсь прояснить. У нас порядковый номер в листах то правильный, если искать по индексу? Скажем, если по коду ошибки можно будет получить строку P2ERR_ISAMSM_OPERATION_NOT_ALLOWED то это уже нормально.

Mikhail Sukhov
Mikhail Sukhov Autor

Например, выращежение P2ERR_MSG_FIELD_NOT_FOUND = P2ERR_MSG_BEGIN говорит о том, что идентификатор P2ERR_MSG_FIELD_NOT_FOUND равен началу блока P2ERR_MSG_BEGIN, который в свою очередь равен 0x8000.

В классе же PlazaErrors сейчас это представлено в виде строчки. Это так и должно быть? Я не 100% уверен, но думаю тут глюк в дизайне.

Вопрос в том, какие преимущества будут при использовании enum-а, если основная задача класса представить код 0x8000 в более понятном формате

Никаких, наверное. Я пока для себя пытаюсь прояснить. У нас порядковый номер в листах то правильный, если искать по индексу? Скажем, если по коду ошибки можно будет получить строку P2ERR_ISAMSM_OPERATION_NOT_ALLOWED то это уже нормально.

  • кто-нибудь знает как получить нормальное описание ошибки при отправке асинхронной транзакции? Сейчас текст получается только в синхронном режиме. А асинхронный режим только и пишет, что Invalid cast exception внутрях COM.
aspirant
aspirant

Mikhail Sukhov:

  • кто-нибудь знает как получить нормальное описание ошибки при отправке асинхронной транзакции? Сейчас текст получается только в синхронном режиме. А асинхронный режим только и пишет, что Invalid cast exception внутрях COM.

Сам на это натыкался, но руки не дошли. Сейчас поискал на форуме РТС. Похоже, нужно чтобы в нитке, откуда отправляется асинхронное сообщение, должен быть бесконечный цикл с ProcessMessage. Вот здесь про это написано + это есть в плазовском примере AsyncSend. У нас ведь сейчас сообщение отправляется из GUI-thread?

esper
esper

Mikhail Sukhov: У нас порядковый номер в листах то правильный, если искать по индексу? Скажем, если по коду ошибки можно будет получить строку P2ERR_ISAMSM_OPERATION_NOT_ALLOWED то это уже нормально. Выборочно проверял на нескольких ошибках, получаемые строки совпадали с логом.

Mikhail Sukhov:

  • кто-нибудь знает как получить нормальное описание ошибки при отправке асинхронной транзакции? Сейчас текст получается только в синхронном режиме. А асинхронный режим только и пишет, что Invalid cast exception внутрях COM. Думаю, стоит обрабатывать код ошибки, который приходит в callback. В документации было указано, что если код ошибки не 0, то заявка не выставлена/исполнена и надо смотреть описание ошибки с таким кодом. Где именно возникает Invalid cast exception, а то я с таким не сталкивался?

aspirant: Похоже, нужно чтобы в нитке, откуда отправляется асинхронное сообщение, должен быть бесконечный цикл с ProcessMessage. Не обязательно в той же нитке где отправляется сообщение, просто где-то для соединения, через которое отправляется сообщение, должна вызываться эта функция, для обработки ответа от сервера. Это, вроде как, справедливо не только для асинхронных сообщений, но и синхронных, в прочем как и для получения любого другого сообщения от сервера.

По PlazaException

Mikhail Sukhov: Я тоже за, если не лепить везде это исключение. Где его предлагаете применить? использовать его предлагаю там, где от плазы могут приходить COMException, чтобы можно было представить код пришедшей ошибки в более удобном виде, т.е. это в местах вызова CP2Connection.Connect, CP2Connection.Disconnect, CP2Connection.ProcessMessage, CP2DataStream.Open, CP2DataStream.Close и т.д.

aspirant
aspirant

А вот, кстати, почему нам самим нужно вручную "крутить" ProcessMessage.

TestPlaza
TestPlaza

Приветствую! Захотелось проверить старую разработку через Плазу. Переписал робота, получил боевой логин. При запуске программы бросается месседж: "Ошибка подключения к серверу Плазы" Может кто-нибудь написать небольшую инструкцию, как подготовить машину для работы с Плазой через Вашу библиотеку?

aspirant
aspirant

TestPlaza: Приветствую! Захотелось проверить старую разработку через Плазу. Переписал робота, получил боевой логин. При запуске программы бросается месседж: "Ошибка подключения к серверу Плазы" Может кто-нибудь написать небольшую инструкцию, как подготовить машину для работы с Плазой через Вашу библиотеку?

К какому серверу подключаетесь (см. файл client_router.ini)? Пришлите лог P2SimpleReplClient.log.

Инструкцию сейчас пишу. Как и вся документация, идет не так быстро, как хотелось бы😢

Mikhail Sukhov
Mikhail Sukhov Autor

TestPlaza: Приветствую! Захотелось проверить старую разработку через Плазу. Переписал робота, получил боевой логин. При запуске программы бросается месседж: "Ошибка подключения к серверу Плазы" Может кто-нибудь написать небольшую инструкцию, как подготовить машину для работы с Плазой через Вашу библиотеку?

Дайте угадаю, в примере ввели логин пароль в текстовый поля? Оставьте их пустыми и просто нажимайте кнопку Подключиться.

TestPlaza
TestPlaza

Подключаюсь на 194.247.133.25:4001. Нет, ваш пример я даже не собирал, сразу работаю со своим роботом. 2aspirant: Вечером на ваше мыло сброшу лог.

Может быть проблема с тtм, что я сам не ставил роутер. А использовал тот, который устанавливается с программой LTS Direct.

esper
esper

TestPlaza: Подключаюсь на 194.247.133.25:4001. Нет, ваш пример я даже не собирал, сразу работаю со своим роботом. 2aspirant: Вечером на ваше мыло сброшу лог.

Может быть проблема с тtм, что я сам не ставил роутер. А использовал тот, который устанавливается с программой LTS Direct. Лог так же можно сбросить на help@rts.ru, техподдержка у них достаточно оперативная

lkor
lkor

TestPlaza: Подключаюсь на 194.247.133.25:4001. Нет, ваш пример я даже не собирал, сразу работаю со своим роботом. 2aspirant: Вечером на ваше мыло сброшу лог.

Может быть проблема с тtм, что я сам не ставил роутер. А использовал тот, который устанавливается с программой LTS Direct.

Если вы подключаетесь к тестовому серверу то адрес должен быть 194.247.133.43:3001 (или beta-forts.rts.ru:3001 что одно и то же). Соберите пример, проверьте работает ли он. Если да, то проблема в вашем приложении, если нет, то нада искать проблему в роутере. Ссылки на установщики роутеров есть тут.

TestPlaza
TestPlaza

Я подключаюсь к боевоему серверу. С тех.поддержкой РТС не связывался, так как может проблема в неправильном использовании Вашего фреймворка. Удалил роутер который устанавливался с LTSD. Установил P2_ClientGate1.11.5_32.exe c ftp РТС. Это не решило проблему - "Ошибка подключения к серверу Плазы"

Лог роутера

[p2syslog:trace:p2mq-cli] MQ library started=1 info=1 New connection created;mq-conn 0x%X=0 Socket created;conn 0x%X;sock 0x%X=0 Socket connected;conn 0x%X;host '%s';port %u=1 Recv completed;;conn 0x%X;count %d; data %#.*Z=0 CConnectionRecvLLMsg();InHdr %d;recvLen %d;recvRem %d=0 CConnectionRecvLLMsg();system_type 0x%X=0 LLMsg received;mq-conn 0x%X;type 0x%X;ver 0x%X;len %u;flags 0x%X;sign 0x%X%X%X%X;body %#.*Z=0 RecvLLMsg() finished;res %X;inHdr %d;recvRem %d=0 Router status received;mq-conn 0x%X;state 0x%X;node_name '%s';login_id %u=0 LLMsg is sent;mq-conn 0x%X;type 0x%X;len %u;oper_num %d=0 Operation result received;mq-conn 0x%X;type 0x%X;len %u;oper_num %d;res 0x%X('%s')=0 Posting message: to '%s'; cat: '%s'; type %d; size %d; bodySize: %d=0 New message added to recvList. Size: %d=0 Socket closed;conn 0x%X=1 Connection released;mq-conn 0x%X=0 MQ library stopped=1 Socket closed by peer;conn 0x%X=1 Socket created;conn 0x%p;sock 0x%p=0 Socket connected;conn 0x%p;host '%s';port %u=1 Recv completed;;conn 0x%p;count %d; data %#.*Z=0 LLMsg received;mq-conn 0x%p;type 0x%X;ver 0x%X;len %u;flags 0x%X;sign 0x%X%X%X%X;body %#.*Z=0 Router status received;mq-conn 0x%p;state 0x%X;node_name '%s';login_id %u=0 LLMsg is sent;mq-conn 0x%p;type 0x%X;len %u;oper_num %d=0 Operation result received;mq-conn 0x%p;type 0x%X;len %u;oper_num %d;res 0x%X('%s')=0 Socket closed;conn 0x%p=1 Socket select finished with error in socket;conn 0x%p;sock_err %r=1 error=1 Couldn't connect socket;conn 0x%p;host '%s';port %u;timeout %u;sock_err %r=1

[p2syslog:trace:p2repl-cli] Client replication library started=1 info=1 Stream created;stream 0x%X=1 Stream opening started;stream 0x%X;type %d;name '%s';server_addr '%s';db_conn '%s'=1 Stream opened;stream 0x%X;channel 0x%I64X=1 Scheme setting started;stream 0x%X=1 Scheme is set;stream 0x%X;channel 0x%I64X=1 Statistics module '%s' was successfully registered=1 Statistics was registered;stream name %s=1 Data requested;stream 0x%X;channel 0x%I64X;session %d=1 CLEAR_DELETED message received;stream 0x%X=1 CLOSE message posted;stream 0x%X=1 Statistics module was unregistered, module name %s=1 Stream destroyed;stream 0x%X=1 Client replication library stopped=1 DATA message received;stream 0x%X=1 Begin transaction=1 Preprocessing received record;stream 0x%X;table_idx %u;rec_rev %I64u=0 Processing received record;stream 0x%X %s; table_idx %u;rec_rev %I64u=1 Commit transaction=1 ACK message posted;stream 0x%X=1 Stream is on-line;stream 0x%X=1 PING message posted;stream 0x%X=1 COUNTED_PING message received;stream 0x%X=0 Couldn't open db-connection;stream 0x%X;db_conn '%s'=1 error=1 Couldn't connect to DB;stream 0x%X;db_conn '%s'=1 Stream created;stream 0x%p=1 Stream opening started;stream 0x%p,type %d,name '%s',server_addr '%s'=1 Stream opened;stream 0x%p;channel 0x%I64X=1 Scheme setting started;stream 0x%p=1 Scheme is set;stream 0x%p;channel 0x%I64X=1 Statistics module for table '%s' was successfully registered=1 Data requested;stream 0x%p;channel 0x%I64X;session %d=1 CLOSE message received;stream 0x%p=1 Stream is being closed by server;stream 0x%p,reason 0x%X(%d)=1 CLEAR_DELETED message received;stream 0x%p=1 DATA message received;stream 0x%p=1 Stream is on-line;stream 0x%p=1 ACK message posted;stream 0x%p=1 CLOSE message posted;stream 0x%p=1 PING message posted;stream 0x%p=1 COUNTED_PING message received;stream 0x%p=1

[p2syslog:trace:db] connection with driver %s created=1 info=1

[p2syslog:trace:SQLLite] SQL: %s=0 info=0 Processing ini-file '%s' with additional connection settings=0

[p2syslog:trace:P2ClientGate] Notification not handled ; notif %I32d; datastream 0x%X=0 Couldn't set message body; message 0x%X=1 error=1 Before P2MQGetMsg for MQ conn %p=0 Before P2ReplProcessMessage for MQ conn %p and MQ msg %p=0 After P2ReplProcessMessage for MQ conn %p and MQ msg %p=0 Stream %s switched to snapshot server %s=1 info=1 Stream %s switched to online server %s=1

[p2syslog:trace:RETURN_P2ERR] Line %s:%d=0

[p2syslog:trace:Scheme] Opened db handles %d, opened table handles %d, opened fld handles %d=1 info=1

[p2syslog:trace:NULL Fields] Parse NULL fields %d=0

[p2syslog:trace:p2db-odbc] Couldn't establish connection;conn_str '%s';sql-error %d;descr '%s'=1 error=1 Connection established;conn_str '%s';dbc 0x%p=1 info=1 Connection closed;dbc 0x%p=1 Executing SQL-statement;sql '%s';stmt 0x%p=0 Couldn't execute prepared SQL-statement;stmt 0x%p;sql-error %d;descr '%s'=1 Preparing SQL-statement;sql '%s';stmt 0x%p=0 Executing prepared SQL-statement;stmt 0x%p=0

[p2syslog:trace:p2db] Startup statements from ini-file were successfully executed=0

[p2syslog:trace:P2ReplStorage] DB policy on conn-str created;stream 0x%p,policy 0x%p=1 info=1 DB policy on conn-str deleted;stream 0x%p,policy 0x%p=1 Preprocessing received record;stream 0x%X;table_idx %u;rec_rev %I64u=0 Processed received record;stream 0x%X %s; table_idx %u;rec_rev %I64u=1 Revision adjustment;stream 0x%X;table_idx %u;cur_rev %I64d; new_rev %I64d=1

[p2syslog:trace:ReplUtils] CLEAR_OLD_REV table %s; minRev %I64d; clearRev %I64d;deletion step %d=1 info=1

esper
esper

Это не лог роутера, а файл конфигурации логирования

transdex
transdex

Опыт установки: Исходные ингридиенты: Установщик роутера: P2_ClientGate1.11.5_32.exe PlazaTrader: отсюда: http://box.net/plaza версия от 30.05.2011

Как я понял этот вариант (в отличие от первого от 17.05.2011) сделан под базовую авторизацию: "Базовый способ: аутентификационная информация, т.е. имя пользователя и пароль, указывается в ini-файле роутера, например, при установке P2ClientGate из дистрибутива. При этом клиентский код ничего не знает про аутентификацию. В силу простоты – рекомендуемый метод." Соответственно пароль находится в открытом виде в .ini файле. Если роутер установлен не как сервис его надо запустить вручную. Плаза-трейдер просто тупо коннектится к локальному 4001 порту. Кстати почему-то все время подразумевается что локальный порт и удаленный одинаковы и равны 4001, что не всегда так. При установке Роутера вводим адреса и порты сервера Plaza(локальный порт можно изменить в .ini файле), выбираем MTA библиотеку, выбираем установку как сервис или отдельно запускаемое приложение по желанию,а также логин и пароль на подключение к плазе.

Если роутер установлен как сервис просто запускаем SampleGUI и жмем на кнопку подключить. Если роутер не сервис, предварительно запускаем роутер файликом start_router.cmd из папки куда установлен роутер. После чего как обычно пишут в Microsoft, можно откинуться на спинку стула и выпить чашечку кофе... В связи с последним на первое время не помешала бы галочка "Не загружать сделки и заявки при старте", аналогично как есть в Cofite SDK.

Mikhail Sukhov
Mikhail Sukhov Autor

transdex: Если роутер установлен как сервис просто запускаем SampleGUI и жмем на кнопку подключить. Если роутер не сервис, предварительно запускаем роутер файликом start_router.cmd из папки куда установлен роутер. После чего как обычно пишут в Microsoft, можно откинуться на спинку стула и выпить чашечку кофе... В связи с последним на первое время не помешала бы галочка "Не загружать сделки и заявки при старте", аналогично как есть в Cofite SDK.

Ага. Теперь осталось понятить самое зерно разработки. Это API для роботов. Тоесть то, что вы называете SampleGUI, на самом деле является демонстрацией возможностей API. Поэтому нельзя к PlazaTrader применять такие понятия как базовый, безбазовый, анонимная аутентификация и т.д. PlazaTrader работает в том режиме, в котором запрограмирован робот. SampleGUI - простой пример робота. Не требует логин пароль и коннектица к локальному роутера. В реальной системе так может и не быть. Поэтому нужны переделки. Чтобы их сделать как можно быстрее, можно взять код SampleGUI, который как раз для этого и был создан.

Что касается галочка "Не загружать сделки и заявки при старте", опять же, делается через перегрузку метода StartExport в коде робота.

transdex
transdex

SampleGUI - простой пример робота. Не требует логин пароль и коннектица к локальному роутера. Так об этом и речь, что в конкретном экземпляре SampleGUI PlazaTrader используется в качестве клиента с базовой аутентификацией, поэтому, чтоб SmartGUI заработал, роутер должен быть настроен на это и запущен. И соответственно если это какая-то другая установка роутера (от Cofite например) , то надо править конфиг роутера.

Mikhail Sukhov
Mikhail Sukhov Autor

SampleGUI - простой пример робота. Не требует логин пароль и коннектица к локальному роутера. Так об этом и речь, что в конкретном экземпляре SampleGUI PlazaTrader используется в качестве клиента с базовой аутентификацией, поэтому, чтоб SmartGUI заработал, роутер должен быть настроен на это и запущен. И соответственно если это какая-то другая установка роутера (от Cofite например) , то надо править конфиг роутера.

А у Кофите какие настройки?

transdex
transdex

У Кофите роутер по умолчанию ставится в другую папку ( что-то вроде "P2RouterForCFT") и аутентификация идет через клиента, поэтому то,что написано в .ini файле не так важно (пароля там точно нет).

carga
carga

Mikhail Sukhov: Налетаем.🙂

У меня роутер запущен на одной машине (сервер), а Ваш пример я запускаю на другой (Клиент).

Как мне объяснить SampleGUI, чтобы он коннектился к заданному МНОЙ роутеру на заданный МНОЙ порт? (При этом, разумеется, должен быть также способ задать локальный логин и пароль для подключения к роутеру [вписывается в client_router.ini]).

ПС Есть ещё одна проблема: если запустить SampleGUI и подключиться к роутеру (на локальной машине), затем запустить второй экземпляр SampleGUI, то при попытке подключиться второй экземпляр скажет "Ошибка подключения к серверу Плазы". И затем "System.TimeoutException: Соединение не бьыло установлено в отведенный отрезок времени".

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

frontman
frontman

Я много раз писал о проблеме получения данных при использовании версий библиотек старше версии 4.0. В результате только с помощью запуска профайленга мне удалось найти причину тормозов. Этой причиной к моему удивлению оказался метод

onnection.ProcessMessage(out cookie, (uint)PollTimeOut.TotalMilliseconds);

onnection - это экземпляр класса CP2ConnectionClass, который в свою очередь находить в библиотеке Interop.P2ClientGateMTA32.dll. После замены файла Interop.P2ClientGateMTA32.dll в новых версиях StockSharp на библиотеку используемую версии 4.0 все тормоза пропали. Может мне кто нибудь объяснит как так? Библиотека суде по всему одна и таже. Она стандартная. Но...

Alexander
Alexander

frontman: Я много раз писал о проблеме получения данных при использовании версий библиотек старше версии 4.0. В результате только с помощью запуска профайленга мне удалось найти причину тормозов. Этой причиной к моему удивлению оказался метод

onnection.ProcessMessage(out cookie, (uint)PollTimeOut.TotalMilliseconds);

> onnection - это экземпляр класса CP2ConnectionClass, который в свою очередь находить в библиотеке Interop.P2ClientGateMTA32.dll.
> После замены файла Interop.P2ClientGateMTA32.dll в новых версиях StockSharp на библиотеку используемую версии 4.0 все тормоза пропали.
> Может мне кто нибудь объяснит как так? Библиотека суде по всему одна и таже. Она стандартная.
> Но...

Не понял что на что вы заменили.
frontman
frontman

Ну это удивительно. Но проблема была не в StockSharp а в Interop.P2ClientGateMTA32.dll Тот Interop.P2ClientGateMTA32.dll что в новых релизах идет какой то бажный, а вот тот что в версии 4.0 норм работает. Хотя не размер не версия не изменена...

Alexander
Alexander

frontman: Ну это удивительно. Но проблема была не в StockSharp а в Interop.P2ClientGateMTA32.dll Тот Interop.P2ClientGateMTA32.dll что в новых релизах идет какой то бажный, а вот тот что в версии 4.0 норм работает. Хотя не размер не версия не изменена...

Попробуйте его сами у себя сгенерировать, из дистрибутива Plaza. В версии 4.0 - это какой? Interop.P2ClientGateMTA32.dll? Он не менялся со времён как появился.

frontman
frontman

Именно! И я это прекрасно понимаю. Но у меня новые библиотеки норм работают только если я Interop.P2ClientGateMTA32.dll заменяю на тот что был в версии 4.0 Ну вот не знаю я почему...

frontman
frontman

Я обычно рядом с такими вещами если они в коде пишу "It's magic" :D

Alexander
Alexander

frontman: Я обычно рядом с такими вещами если они в коде пишу "It's magic" :D

Как вы определяете тормоза \ задержки? Дайте конкретные цифры и логгирование событий, чтоб понимать о чём речь.

frontman
frontman

Александр. Я просто запускаю SampleGUI для версии 4.0 и более позних версий. И открываю окно заявок. И вот если в версии 4.0 новые заявки приходят даже раньше чем в квике(в программе) они появляются, то в версиях более поздних они приходям через несколько минут! Что для плазы вообще не приемлемо... Я и тот и тот проект профайлером просматривал. В версиях позднее 4.0 40% времени тратиться на строчку сonnection.ProcessMessage(...);

Alexander
Alexander

frontman: Александр. Я просто запускаю SampleGUI для версии 4.0 и более позних версий. И открываю окно заявок. И вот если в версии 4.0 новые заявки приходят даже раньше чем в квике(в программе) они появляются, то в версиях более поздних они приходям через несколько минут! Что для плазы вообще не приемлемо... Я и тот и тот проект профайлером просматривал. В версиях позднее 4.0 40% времени тратиться на строчку сonnection.ProcessMessage(...);

естественно ProcessMessage стал вызываться чаще, т.к. таймаут снизился.

  1. добавьте логирование прихода заявок чтоб было понятно. посмотрите сколько времени тратится от подачи заявки до её регистрации.
  2. попробуйте StreamTimeout установить не в 100мс, а побольше.
frontman
frontman
  1. Заявки регистрируются вне программы. Он не то что новые он старые не качает норм.
  2. А зачем? Код то не меняется. Я все го лишь заменяю библиотеку. Со старой библиотекой(на самом деле библиотека вроде та же на вид))) и 100 мс все норм работает , а с новой и 10мс не.
Alexander
Alexander

frontman:

  1. Заявки регистрируются вне программы. Он не то что новые он старые не качает норм.
  2. А зачем? Код то не меняется. Я все го лишь заменяю библиотеку. Со старой библиотекой(на самом деле библиотека вроде та же на вид))) и 100 мс все норм работает , а с новой и 10мс не.

Interop.P2ClientGateMTA32.dll не менялся ни разу с тех пор как положили в TFS. Посмотрите по хистори. Без логгирования и реальных результатов - пока лишь разговоры.

Нет тестов и логов - нет проблемы в данном случае :)

frontman
frontman

Согласен. И вашу позицию понимаю. Ну мне достаточно того что я теперь знаю как это испр и я если у кого то еще это будет то я написал как испр)

frontman
frontman

Тестировал плазу с утра. И заметил странное явление. При выполнении следующего кода

 _trader.StreamTimeOut = TimeSpan.FromMilliseconds(50);

            //_trader.ReConnectionSettings.Interval = TimeSpan.FromSeconds(10);

            _trader.NewSecurities +=
                securities => this.GuiAsync(() =>
                _context.Post(obj => _securities.AddRange(obj as IEnumerable<Security>), securities.Where(sec => sec.Code == "...")));

            _trader.NewPortfolios +=
                portfolios => this.GuiAsync(() =>
                     _context.Post(obj => _portfolios.AddRange(obj as IEnumerable<Portfolio>), portfolios.Where(sec => sec.Name == "...")));
            
            _trader.NewOrders += orders => this.GuiSync(() => textBox1.Text = orders.Last().Id.ToString());

            _trader.Connected += () => _trader.StartFutureExport();
           
            _trader.Connect();

Первые минуты 2 где то загрузка на процессор катастрофична. Причем даже после того как все портфели и инструменты загрузились она не начинает падать. Не падает она и после того как прогрузились старые заявки и начали поступать новые... Потом через какое то время нагрузка падает и такое состояние продолжается далее... Не могу понять что происходит в эти первые минуту...

Alexander
Alexander

Происходит подключение и прогрузка всей поступившей информации.

Причем даже после того как все портфели и инструменты загрузились как отслеживаете?

frontman
frontman

Просто смотрю изменяется ли название портфеля в текстовом поле куда я вывожу один из портфелей или инструментов поступивших при вызове события NewPortfolios или NewSecurities. И так же вижу что новые заявки начали поступать, а загрузка еще приличная. Потом проходит еще какое то время и нагрузка падает...

Alexander
Alexander

frontman: Просто смотрю изменяется ли название портфеля в текстовом поле куда я вывожу один из портфелей или инструментов поступивших при вызове события NewPortfolios или NewSecurities. И так же вижу что новые заявки начали поступать, а загрузка еще приличная. Потом проходит еще какое то время и нагрузка падает...

  1. строятся свечки может или ещё какая у вас катавасия с поступающими данными - вариантов тысячи
  2. NewPortfolios вызывается естественно 1 раз для каждого портфеля - когда он новый, т.е. создаётся.
frontman
frontman

Конечно что то я накрутил там явно с обработкой событий)) Но думаю это не является причиной. Сейчас упрощу и проверю еще...

frontman
frontman

А насчет свечек... Ну я точно этой инф не пользуюсь. Я показал код который принимает данные. Или они все равно строятся?)

Ortn
Ortn

А можно как нибудь подписаться на получение только некоторых потоков? (реплики они называются?) Очень долго подгружаются сделки (которые мне не нужны) хочется иметь только собственные сделки + стакан.

Ortn
Ortn

Обнаружил баг когда у активной заявки (которая была частично исполнена) статус Done. В PlazaTrader.cs есть такие строчки:


switch (action)
				{
					case 0: // удалена
						order.CancelTime = lastRecord.Get<DateTime>(metadata.Moment);
						order.State = OrderStates.Done;

						// у отмененной заявки оставшийся объем равен 0, а объем операции равен отмененному объему
						// http://forum.rts.ru/viewtopic.asp?t=21409
						order.Balance = lastRecord.Get<int>(metadata.AmountOperation);
						break;
					case 1: // добавлена
						break;
					case 2: // исполнена
						order.State = OrderStates.Done;
						order.Balance = lastRecord.Get<decimal>(metadata.AmountRest);
						break;
					default:
						throw new InvalidOperationException("Неизвестное действие заявки {0}.".Put(action));
				}

Это вообще правильно? Судя по форуму РТС action == 2 когда по заявке была хотя бы одна сделка. (т.е. она не обязана быть полностью сведенной)

http://forum.rts.ru/viewtopic.asp?t=19140

Интерпретация значения "2" в случае с OrderBook - "по данной заявке была как мин. одна сделка". Т.к. мы показываем некий срез во времени то больше никакой информации из action=2 не следует.

Вобщем факт, что у активной заявки был статус Done (в SampleGUI и в моем собственном приложении).

Alexander
Alexander

Обнаружил баг когда у активной заявки (которая была частично исполнена) статус Done. В PlazaTrader.cs есть такие строчки:


switch (action)
				{
					case 0: // удалена
						order.CancelTime = lastRecord.Get<DateTime>(metadata.Moment);
						order.State = OrderStates.Done;

						// у отмененной заявки оставшийся объем равен 0, а объем операции равен отмененному объему
						// http://forum.rts.ru/viewtopic.asp?t=21409
						order.Balance = lastRecord.Get<int>(metadata.AmountOperation);
						break;
					case 1: // добавлена
						break;
					case 2: // исполнена
						order.State = OrderStates.Done;
						order.Balance = lastRecord.Get<decimal>(metadata.AmountRest);
						break;
					default:
						throw new InvalidOperationException("Неизвестное действие заявки {0}.".Put(action));
				}

Это вообще правильно? Судя по форуму РТС action == 2 когда по заявке была хотя бы одна сделка. (т.е. она не обязана быть полностью сведенной)

http://forum.rts.ru/viewtopic.asp?t=19140

Интерпретация значения "2" в случае с OrderBook - "по данной заявке была как мин. одна сделка". Т.к. мы показываем некий срез во времени то больше никакой информации из action=2 не следует.

Вобщем факт, что у активной заявки был статус Done (в SampleGUI и в моем собственном приложении).

Это не верно, поэтому я ещё 28 октября поправил