CreateDataSource

Страницы: 1
RSS
CreateDataSource, не делает квик сильнее
 
Введение
Нужно экспортировать всю ТОС луа-скриптом. Дело не то чтобы сложное, если обязать юзера держать ТОС открытой. Но хочется покрасивше, давайте на старте подпишемся на все доступные инструменты? А давайте...

Глава первая, шапкозакидательская
Код
local SubscribeAllTrades = function()
   local cls = split(getClassesList(), ',')
   for k, v in pairs(cls) do
      local sec = split(getClassSecurities(v), ',')
      for kk, vv in pairs(sec) do
         local ds = CreateDataSource(v, vv, INTERVAL_TICK)
         if nil ~= ds then
            ds:SetEmptyCallback()
         else
            message(v .. ':' .. vv)
         end
         ds = nil
      end
   end
end

OnI nit = function()
   SubscribeAllTrades()
end
запускаем - и квик намертво виснет, загрузив одно ядро на 100%. Через час-другой экперимент прекращен через прибитие квика. В научных целях упражнение повторялось неоднократно, результат один.

Глава вторая, исследовательская
Добавляем логи, смотрим, что происходит. Квик резво создает датасорцы, добирается до класса с опционами (а их там ой как много) и процесс начинает постепенно замедляться. Моего терпения хватило до момента, когда создание одного датасорца занимало 6 секунд, проверить апорию об ахиллесе и черепахе не вышло, квик был снова прибит.

Глава третья, кулхацкерская
Где-то между неудачными запусками в волшебном INFO.ini была ручками очищена секция [ALL_TRADES_DATA], так что содержала только
Код
[ALL_TRADES_DATA]
req-all-trades-from-curr-moment=0
Запускаем наш недоскрипт снова и что мы видим? Квик по мере создания датасорцев пишет в эту секцию коды инструментов. Ну, это логично и ожидаемо, пока дело не доходит до секции с опционами. Их и так много, но квику все мало и он начинает добавлять и добавлять опционы по второму, третьему и так далее кругу. Удалось получить INFO.ini размером в 200 с лишним мегабайт, дальше ждать смысла не было. Весь этот объем был набран исключительно классом SPBOPT, остальные классы были "нормальные", хотя я бы и ожидал от квика чуть большего интеллекта, чтобы самому заменить исчерпывающий список класса на ALL (при выборе всех инструментов в диалоге настройки получаемых данных он же как-то догадывается).

Глава четвертая, предположительная
Судя по всему, при подписке на опционы (лучше сказать на класс с большим количеством инструментов) квик где-то попадает в бесконечный цикл. Предположительно из-за жесткого лимита на размер буфера, т.е. после достижения определенного размера строки с инструментами квик дальше уже не смотрит, делает вывод "инструмент не найден" и добавляет его еще раз. История с INFO.ini, скорее всего, лишь внешнее проявление внутренней проблемы, поскольку поведение не меняется даже если там для всех классов вручную выставлено ALL.

Глава пятая, вопросительная
Опуская множество сопутствующих вопросов, я спрошу:
1) как из скрипта при закрытой ТОС подписаться на все доступные инструменты, чтобы это было выполнено в обозримое время?
2) если я из скрипта залезу в INFO.ini и перепишу секцию [ALL_TRADES_DATA], дабы освободить юзера от ковыряния в диалоге заказа данных, это будет грязный хак или не очень?

Глава пятая, пожелательная
Уже было такое пожелание здесь, но и я добавлю. Пусть CreateDataSource со вторым параметром nil и третьим INTERVAL_TICK подписывается сразу на весь класс (и при необходимости выставляет в INFO.ini для этого класса ALL).
 
Немного конкретики. Квик 8.0.2.3, брокер настоящий (не демо), на момент запуска скрипта соединения с сервером нет, в квике открыта ТОС, в которой чуть меньше 2 млн вчерашних сделок. Полный код скрипта
Код
local split = function(str, delimiter)
   local t = {}
   local pat = "([^" .. delimiter .. "]+)"
   for s in string.gmatch(str, pat) do
      table.insert(t, s)
   end
   return t
end

local SubscribeAllTrades = function()
   local sublog = io.open(getScriptPath() .. "\\SUBLOG.txt", "w")
   local cls = split(getClassesList(), ',')
   local dss = {}
   for k, v in pairs(cls) do
      local sec = split(getClassSecurities(v), ',')
      sublog:write(string.format('%s (%u securities)', v, table.getn(sec)))
      sublog:flush()
      local tim = os.clock()
      for kk, vv in pairs(sec) do
         local ds = CreateDataSource(v, vv, INTERVAL_TICK)
         if nil == ds then
            sublog:write(string.format(' CreateDataSource failed on %s\n', vv))
            break
         end
         table.insert(dss, ds)
      end
      sublog:write(string.format(' subscribed in %u seconds\n', os.clock() - tim))
      sublog:flush()
   end
   for k, v in pairs(dss) do
      if not v:SetEmptyCallback() then
         sublog:write('SetEmptyCallback failed\n')
      end
   end
   sublog:close()
end

OnI nit = function()
   SubscribeAllTrades()
end
После ну очень долгого жужжания всеми вентиляторами компа получен следующий лог
Код
EQOB (1464 securities) subscribed in 556 seconds
EQDB (30 securities) subscribed in 11 seconds
SMAL (233 securities) subscribed in 89 seconds
INDX (52 securities) subscribed in 20 seconds
TQBR (264 securities) subscribed in 100 seconds
TQDE (12 securities) subscribed in 4 seconds
TQOB (43 securities) subscribed in 16 seconds
TQIF (69 securities) subscribed in 26 seconds
TQTF (26 securities) subscribed in 9 seconds
EQQI (0 securities) subscribed in 0 seconds
OQQI (12 securities) subscribed in 4 seconds
EQRP_INFO (2377 securities) subscribed in 909 seconds
TQQI (36 securities) subscribed in 13 seconds
TQOD (100 securities) subscribed in 37 seconds
CROSSRATE (7 securities) subscribed in 2 seconds
SPBFUT (212 securities) subscribed in 80 seconds
SPBOPT (10062 securities) subscribed in 3837 seconds
RTSIDX (261 securities) subscribed in 99 seconds
INSTR (4 securities) subscribed in 1 seconds
Опуская вопли и фейспалмы, резюмируем: для подписки на ТОС CreateDataSource не годится от слова совсем, слишком много ненужной работы (какой, интересно) выполняется внутри нее. Посему "ща буит пожелание" в соответствующем подфоруме.

Кстати говоря, есть пара любопытных замечаний, к делу прямо не относящихся.
1. То же самое, реализованное в длл на сях, работает чутка (ну так раза в два) быстрее. Хотя, казалось бы, какая разница.
2. Пока основной (с окнами) поток висит на нашей OnInit, другие потоки квика продолжают себе спокойно работать. В частности, если есть подключение к серверу, оно не рвется, в фоне нормально подъезжают все сделки, что видно по растущему файлу alltrade.dat. Откуда возникает интересный вопрос, а что происходит с OnAllTrade в это время? Вызываться она не должна, т.к. мы еще не вышли из OnInit, но данные-то едут, там какая-то очередь накапливается или приехавшие во время OnInit новые сделки не приведут к последующему вызову OnAllTrade? По моим наблюдениям пропусков не происходит, но тут нужны более тщательные исследования (либо авторитетное заявление разработчиков).
 
Зачем делать заказ в коллекции онинит?

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


делайте заказ из потока майн, и волосы будут крепкими и шелковистыми...  
 
Какая разница, он и в мейне полтора часа кряхтеть будет, только что юзеру не так заметно, юай не виснет.
 
В мейне тот же тайминг абсолютно (особо долго не ждал)
Код
EQOB (1464 securities) subscribed in 561 seconds
EQDB (30 securities) subscribed in 11 seconds
SMAL (233 securities) subscribed in 89 seconds
INDX (52 securities) subscribed in 19 seconds
TQBR (264 securities) subscribed in 100 seconds
TQDE (12 securities) subscribed in 4 seconds
TQOB (43 securities) subscribed in 16 seconds
TQIF (69 securities) subscribed in 25 seconds
TQTF (26 securities) subscribed in 9 seconds
EQQI (0 securities) subscribed in 0 seconds
OQQI (12 securities) subscribed in 4 seconds

и та же загрузка ядра на 100% с сопутствующим воем кулера. Это не то, что спасет отца русской демократии. Самое ж смешное, что "пожелание" можно реализовать, просто создавая невидимую ТОС (ну, без условий по невмешательству в фильтры, но это можно пережить). Это можно и из скрипта-длл сделать вообще-то, просто хачить не хочется, бо апдейтонеустойчиво.
 
Все правильно. Вы подписываетесь на тучу ТИКОВЫХ данных и  и хотите чего то сверх_естественного.

конечно процессор трудится в потери лица - ему сервер отваливает лопатой работу. Это ж не скрипт сжирает процессорную мощность, а терминал, которому нужно всю эту помойку по полочкам разложить.  
 
О том и речь в конечном итоге, CreateDataSource делает ненужную в данном случае работу. При открытии ТОС ничего же не виснет. Очевидно, что в ближайшие годы требование держать ТОС открытой снять не удастся, даже если прямо сейчас арка бросится теряя тапки реализовывать "просто подписку на ТОС".
 
s_mike@rambler.ru, однако ж спасибо за идею/ключевик, кое-что интересное вырисовывается. Главно дело чтобы это не пофиксили в "одной из будущих версий".
 
Цитата
Anton написал:
При открытии ТОС ничего же не виснет.
Вот когда откроете полторы тысячи тиковых TOC - тогда и будет смысл говорить про "ничего не виснет".
 
Цитата
swerg написал:
 Вот когда откроете полторы тысячи тиковых TOC - тогда и будет смысл говорить про "ничего не виснет".
И опять "об том и речь". Я прошу сделать ОДНУ ТОС из скрипта, но мне говорят, что это не фича а баг, поэтому не будем.
Страницы: 1
Читают тему (гостей: 1)
Наверх