Комментарии и предложения


Комментарии и предложения
Atom
3/11/2011


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

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

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

"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 У меня несколько сместились приоритеты - придется задержаться на квике, но постораюсь не пропадать.

Tags:


Thanks:


< 1 2 3 4 5  > >>
Mikhail Sukhov

Avatar
Date: 3/26/2011
Reply


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


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

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

aspirant

Avatar
Date: 3/26/2011
Reply


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


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

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


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

Mikhail Sukhov

Avatar
Date: 3/26/2011
Reply


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


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

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

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

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

Thanks:

skuvv

Avatar
Date: 3/26/2011
Reply


aspirant Go to
skuvv Go to

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


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

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

Mikhail Sukhov

Avatar
Date: 3/26/2011
Reply


skuvv Go to
aspirant Go to
skuvv Go to

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


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

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


Может выложить это ввиде отдельного теста для сравнения перфоманса? Насчет OnNewSecurityChanged - конечно. Если вместо поиска по словарю устраивать Exist Find и т.д., то я не удивлюсь и пол минутными задержками.[smile]
Thanks:

aspirant

Avatar
Date: 3/26/2011
Reply


Mikhail Sukhov Go to
Сейчас PlazaListener создается в самом начале со всеми колонками. Как я уже писал, использовать надо только те колонки, что определены схемами PlazaTable.Columns.

Как клиентский код создает таблицу с колонками и схемами? Твое видение с куском кода.

Mikhail Sukhov Go to
enum TableName лучше сделать статическим классом со строковыми константами. Я так понял, такие безобразные названия нужны лишь для того, чтобы ini файлы создавать? Если да, то по логике простой. Мы создаем текстовый файл, используем string. Вся логика в имени полей TableName - приведение в string... Так может тогда сразу сделать string?

Этот enum был служебным, для внутреннего пользования. Клиенту его можно не показывать. Зачем я его сделал? Когда нужно набить пару десятков классов, enum + intellisense здорово помогает. Потом подстраховка от случайное опечатки в string. Сам я его не набивал: вместо этого пропарсил папку со всеми схемами.

Вообще PlazaTable сейчас и есть то, что ты предлагаешь. За исключением полей метаданных все остальные методы закомментены (причем, делал это не я). Можно сделать вот так:
Code
// вместо: public TableName SystemName { get; private set; }
public string SystemName { get{ _systemName.ToString(); }


Mikhail Sukhov Go to
Давайте подумаем насчет фильтрации. Сейчас это выглядит как то не очень.

Я вообще собирался это делать внутри PlazaListener, но пока думал, skuvv успел привинтить свой фильтр[smile]. Что насчет методов RegisterSecurity/UnRegisterSecurity? С помощью них будем включать фильтрацию или они нужно для чего-то другого?

Mikhail Sukhov Go to
PlazaSchemaParser предлагаю упрятать в PlazaTableSerializer

Сделаю, когда устаканится модель метаданных. С тех пор как я написал PlazaSchemaParser, модель уже раза-три менялась, и я решил отложить доделку этого класса на самый конец.
Thanks:

skuvv

Avatar
Date: 3/26/2011
Reply


Mikhail Sukhov Go to
skuvv Go to
aspirant Go to
skuvv Go to

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


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

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


Может выложить это ввиде отдельного теста для сравнения перфоманса? Насчет OnNewSecurityChanged - конечно. Если вместо поиска по словарю устраивать Exist Find и т.д., то я не удивлюсь и пол минутными задержками.[smile]

Code

void m_conn4_StreamDataInserted(CP2DataStream stream, String tableName, CP2Record rec)
{
try
{
if (stream.StreamName == streamFutCommonID)
{
int index = instruments.GetIndex(rec.GetValAsLong("isin_id"));
if(index>=0)
{
double best_sell = Convert.ToDouble(rec.GetValAsVariant("best_sell"));
double best_buy = Convert.ToDouble(rec.GetValAsVariant("best_buy"));
if (best_buy != 0 && best_sell != 0)
{
instruments._bestask[index] = best_sell;
instruments._bestask_vol[index] = rec.GetValAsLong("amount_sell");
instruments._bestbid[index] = best_buy;
instruments._bestbid_vol[index] = rec.GetValAsLong("amount_buy");
instruments._lasttrade[index] = Convert.ToDouble(rec.GetValAsVariant("price"));
instruments._lasttrade_vol[index] = rec.GetValAsLong("amount");
instruments._lasttrade_time[index] = Convert.ToDateTime(rec.GetValAsString("deal_time"));
instruments._bidask_time[index] = DateTime.Now;

curr_rev_futcommon = rec.GetValAsLong("replRev");

log_buffer.Add(t4.Name, rec.GetValAsString("replID") + ";" + rec.GetValAsString("replRev") + ";" + instruments._isin_id[index] + ";" + instruments._bestask[index] + ";" + instruments._bestask_vol[index] + ";" +
instruments._bestbid[index] + ";" + instruments._bestbid_vol[index] + ";" + instruments._lasttrade[index] + ";" + instruments._lasttrade_vol[index] + ";" + instruments._lasttrade_time[index].ToString(timefmt) + ";" + rec.GetValAsString("deal_count") + ";" + rec.GetValAsString("pos"));
}
}
}
}
catch (Exception e)
{
log_buffer.Add("error", "[" + t4.Name + "] " + e.ToString());
}
}

Event datainserted
Все типы таблицы я получал в соответсвующих им win thread.
Событий никаких нет [biggrin], заполняется статик массив instruments,а роботы на каждом прогоне его чекают.
Ну и в конце запись в текстовики, через самописный логгер.
ps фильтрация опять же массиву instruments
Thanks:

Mikhail Sukhov

Avatar
Date: 3/27/2011
Reply


aspirant Go to
Mikhail Sukhov Go to
Сейчас PlazaListener создается в самом начале со всеми колонками. Как я уже писал, использовать надо только те колонки, что определены схемами PlazaTable.Columns.

Как клиентский код создает таблицу с колонками и схемами? Твое видение с куском кода.


Взял за основу отсюда:

Code
PlazaTableRegistry.FutCommon.Columns.Add(PlazaColumnRegistry.FuturesCommon.CurKotir);

PlazaTableRegistry.FutAggr5.Columns.Add(PlazaColumnRegistry.FuturesAggregation5.Moment);


aspirant Go to

Mikhail Sukhov Go to
enum TableName лучше сделать статическим классом со строковыми константами. Я так понял, такие безобразные названия нужны лишь для того, чтобы ini файлы создавать? Если да, то по логике простой. Мы создаем текстовый файл, используем string. Вся логика в имени полей TableName - приведение в string... Так может тогда сразу сделать string?

Этот enum был служебным, для внутреннего пользования. Клиенту его можно не показывать. Зачем я его сделал? Когда нужно набить пару десятков классов, enum + intellisense здорово помогает. Потом подстраховка от случайное опечатки в string. Сам я его не набивал: вместо этого пропарсил папку со всеми схемами.


Ок, не поняли друг друга. Тогда ремарка и код. Если enum используется для задания строковых констант, то используется класс со строками:

Code
static class TableName
{
public const string BaseContractsParams = "base_contracts_params";
..
}

public static PlazaTable FutAggr50 = new PlazaTable(TableName.BaseContractsParams, ReplicationStream.FutAggr50, "Фьючерсы: стакан глубиной 50 котировок");


На этом примере сразу видно недостаток именования перечислений (не ReplicationStreams, а ReplicationStream). Сходу кажется, что идет работа с потоком. А на самом деле к потокам это имеет о посредственное значение.

aspirant Go to

Вообще PlazaTable сейчас и есть то, что ты предлагаешь. За исключением полей метаданных все остальные методы закомментены (причем, делал это не я). Можно сделать вот так:
Code
// вместо: public TableName SystemName { get; private set; }
public string SystemName { get{ _systemName.ToString(); }



Не понял, что за рокировка.

aspirant Go to

Mikhail Sukhov Go to
Давайте подумаем насчет фильтрации. Сейчас это выглядит как то не очень.

Я вообще собирался это делать внутри PlazaListener, но пока думал, skuvv успел привинтить свой фильтр[smile]. Что насчет методов RegisterSecurity/UnRegisterSecurity? С помощью них будем включать фильтрацию или они нужно для чего-то другого?


Да, именно включение фильтра. Во всех АПИ (и я думаю в Плазе тоже рано или поздно сделают), фильтрация идет на серверной стороне и этот фильтра изменяется через методы, аналогичные Register Unregister.
Thanks:

aspirant

Avatar
Date: 3/28/2011
Reply


Mikhail Sukhov Go to
Code
PlazaTableRegistry.FutCommon.Columns.Add(PlazaColumnRegistry.FuturesCommon.CurKotir);

PlazaTableRegistry.FutAggr5.Columns.Add(PlazaColumnRegistry.FuturesAggregation5.Moment);


Вопросы:
  1. То есть мы исходим из того, что клиент подписывается на каждый поток только один раз? Напоминаю, у Плазы можно подписываться на один поток несколько раз. Клиенты не будут спрашивать? Когда проект будет зарелизен, изменить архитекутру будет сложно.
  2. Что делать с нашими стандартными потоками, которые нужны, чтобы мапить объекты. Мы договорились, что их скроем от клиента, чтобы гарантировать в них нужный набор колоннок. Придется все равно создавать какие-то отдельные таблицы.


Mikhail Sukhov Go to
Если enum используется для задания строковых констант, то используется класс со строками:
Code
static class TableName...


OK, сделаю после фильтрации. Сейчас все работает, а это рефакторинг функционала не добавит, только эстетику.

Mikhail Sukhov Go to
Не понял, что за рокировка.

Теперь она уже не нужна.

Mikhail Sukhov Go to
На этом примере сразу видно недостаток именования перечислений (не ReplicationStreams, а ReplicationStream)


Не знаю, дело вкуса. Я уже привык к единственному числу. Вот, кстати, MSDN'овский guideline.
Thanks:

Mikhail Sukhov

Avatar
Date: 3/28/2011
Reply


aspirant Go to

Вопросы:
  1. То есть мы исходим из того, что клиент подписывается на каждый поток только один раз? Напоминаю, у Плазы можно подписываться на один поток несколько раз. Клиенты не будут спрашивать? Когда проект будет зарелизен, изменить архитекутру будет сложно.
  2. Что делать с нашими стандартными потоками, которые нужны, чтобы мапить объекты. Мы договорились, что их скроем от клиента, чтобы гарантировать в них нужный набор колоннок. Придется все равно создавать какие-то отдельные таблицы.



1. Давай еще раз обсудим. С точки зрения практики - зачем это нужно?
2. Хм, а почему бы просто не оставить как есть сейчас?
Thanks:
< 1 2 3 4 5  > >>

Attach files by dragging & dropping, , or pasting from the clipboard.

loading
clippy