Nikolay написал: Только вот использование этой функции будет таким же неудобным, т.к. придется писать постоянный вызов этой функции, Вы же не значете когда придет ответ. Это синхронный подход. Он плохо работает.
Наличие флага "ответ от сервера получен" не лишает вас возможности использовать колбек.
Надо делать так, как надо. А как не надо - делать не надо.
Nikolay, не могу похвастаться уровнем работы с высокими материями, новичёк ещё. Поэтому, если позволите, взгляд со стороны, неопытного программиста.
Цитата
Nikolay написал: Ваша фнкция DS:Чё_Есть_На_Сервере_Брокера() обращается к справочной информации, т.к. Вы просто хотите получить данные о признаке наличия данных, а не их количестве. Эта информация итак приходит вместе со всеми информационными таблицами.
Не хватает признака отсутствия данных, мы об этом.
Цитата
Nikolay написал: Вы просто хотите получить данные о признаке наличия данных, а не их количестве.
Хотите туда количество? Да, пожалуйста, просите разработчиков. Как будете использовать - ваше дело.
Цитата
Nikolay написал: Если CreateDataSource выполнился, значит информация есть в локальном кеше. Как же она к нам попала, если на сервер ничего нет.
Конечно, информация есть, как минимум список классов, но не обязательно график. Чтоб вы понимали, как это работает (на примере графика цены и объёма): Когда вы вызываете CreateDataSource, она проверяет валидность класса, и, в случае успеха, тут же выплёвывает вам data_source. Причём, возможны несколько вариантов: 1) Если график уже открыт, то CreateDataSource сразу выдаст вам заполненный data_source. Если график не открыт, то: 2) Если клиент оффлайн и находит в кеше нужный бинарник, то в data_source будут свечи из этого бинарника. 3) Если клиент оффлайн и графика в кеше нет, то data_source будет пустой (Size = 0). 4) Если клиент онлайн, то data_source будет пустой (Size = 0) до тех пор, пока не получит хоть одну свечу.
Цитата
Nikolay написал: Если их 0, то что? Не было торгов?
Может, не было, а может, было, не узнаешь, пока не пройдёт хоть одна сделка. См. выше, четвёртый пункт.
Цитата
Nikolay написал: тип ошибки: 404 или 204 и д.р.. А я как раз хотел бы видеть коды ответа сервера. А не просто ничего нет на сервере.
Здравая мысль, просите разработчиков. Но, насколько мне известно, до недавнего времени у сервера отсутствовала функция мониторинга "почему сломался график." Не знаю, может, появилось что-то.
Цитата
Nikolay написал: Если сервер ничего не прислал, то это не значит, что там ничего нет - это значит, что идет процесс передачи, обработка запроса.
А кто с этим спорит? Мы пока не знаем, что "там" есть.
Надо делать так, как надо. А как не надо - делать не надо.
Nikolay написал: Size - это число баров. Оно тоже не может быть nil, т.к. если их нет, то это 0. А что такое nil баров, если проверка на корректность потока прошла?
DS = {
['есть чё?'] = nil,
SuperFunc = function(self)
return self['есть чё?']
end
}
function main()
while DS:SuperFunc() == nil do
-- Ждём пока сервер ответит
sleep(1000)
end
message('Ответ получен: ' .. DS:SuperFunc())
end
function OnParam()
-- Сервер отвечает:
-- Свечей не имею, но, ежели, они когда появятся, я вам маякну, если подписка не будет закрыта,
-- а пока пишем:
DS['есть чё?'] = 'нет ничё'
end
Надо делать так, как надо. А как не надо - делать не надо.
И вдогонку (учитывая опыт), а то опять не поймёте: то что написано в OnParam, заполнение нашего поля, делает естественно сам терминал по приходу ответа от сервера на запрос CreateDataSource, мы ведь об нём тему мусолим.
Надо делать так, как надо. А как не надо - делать не надо.
DS:Чё_Есть_На_Сервере_Брокера() обращается к объекту DS (data_source), только возвращает нам не какую-то лабуду, а честный ответ: если сервер ещё ничё не прислал, то и ответ будет буквально "ничё", nil. Ежели с сервера уже получили ответ, то там будет признак наличия/отсутствия свечей на сервере.
Надо делать так, как надо. А как не надо - делать не надо.
Anton написал: Либо на сервере нет свечей, тогда ds:ExpectedSize() возвращает 0 и мы знаем, что ждать в данный момент больше нечего. Либо мы получили все что есть и ds:ExpectedSize() == ds:Size(), дальше, если хотим реалтайму, никто не запрещает поллить периодически или настроить колбек. В чем-то перекликается с предложениями от Nikolay выше.
Anton, я вот тут подумал, это тогда, когда клиент хранил историю в 3000+ свечей количество свечей на сервере могло пригодиться. Сейчас, когда сервер хранит 3000+, а клиент 65 тыс. количество свечей на сервере не особо то поможет, скорее навредит. Важен только сам факт есть там свечи или нет.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: В связи с чем возникает резонный вопрос, в какой ситуации сервер (именно сервер а не терминал) должен ответить nil функции "Чё_Есть_На_Сервере_Брокера" на ее запрос?
Старатель написал: 2) Если data_source создан, то клиент чё-то там отправляет серверу, в ответ последний отправляет клиенту запрашиваемые свечи или флаг, что свечей сервер не имеет.
Или количество свечей на сервере (вместо флага) в предыдущей редакции. (Ну запамятовал я, что такое пожелание уже было.)
Цитата
Старатель написал: 3) После получения данных с сервера клиент заполняет у себя data_source (если свечи имеются) и флаги true/false
А до получения данных - нечего возвращать, там пусто, nil, понимаете?
Цитата
Старатель написал: Ежели мы запросим DS:Чё_Есть_На_Сервере_Брокера() между 2 и 3, то получим nil, потому что флаги ещё не пришли с сервера, про биты помните?
Если так не понятно, я не знаю, как ещё объяснить. Вот человек постарался расписал для самых маленьких, читайте, может поймёте откуда nil.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: И суть этого предложения как раз и вызывает вопросы.
К сожалению, у вас так и останутся вопросы пока, наконец, вы не поймёте, что ds:Size() не обращается напрямую к серверу, а возвращает количество свечей на рабочем месте.
Цитата
Sergey Gorokhov написал: чем оно отличается от предложения зарегистрированного 3года назад.
Признаться, я уже и запамятовал, что там регистрировалось 3 года назад. Случайно вчера наткнулся на старую тему.
Надо делать так, как надо. А как не надо - делать не надо.
Nikolay написал: Причем видно, что это происходит при подсвечивании ячейки таблицы. Относительно помогает сгладить замирания - увеличение периода подсветки до 1000 мс.
Да, Highlight, конечно жёстко тормозит вывод. Но у меня получается наоборот, чем меньше timeout в Highlight, тем плавнее обновляется вторая строка.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: Функция которая лезет на сервер для проверки того что есть на сервере, никак не может одновременно смотреть на клиента.Функция такая взяла залезла на сервер, посмотрела что там есть и вернула клиенту какой-то результат, без какого-либо участия клиента.
Кажется, я понял. Sergey Gorokhov, похоже, вы думаете, что ds:Size() напрямую обращается к серверу. Поверьте, это не так. Size() возвращает то количество свечей, которое получил и для него посчитал клиент на месте и участливо положил в датасорс. Можете спросить у старших.
Надо делать так, как надо. А как не надо - делать не надо.
Не вижу логики. Сервер отправляет ответ по транзакции автору этой транзакции, а не другому клиенту. Если сервер не повторил отправку неподтверждённого пакета, то вопрос к серверу, почему? Если же это клиент получил, но не вызвал колбек, - то к клиенту.
Цитата
Anton написал: Скорей вопрос, почему квик после команды дисконнекта позволяет еще что-то отправить.
У меня больше вопрос, почему, если поставить sleep побольше и транзакция не успевает отправиться до дисконекта, то нет сообщения об ошибке. Скорее всего, sendTransaction только проверяет валидность параметров и доступность указанной транзакции и сразу возвращает результат этой проверки, а саму транзакцию ставит в очередь на отправку. А когда доходит до отправки, то уже дисконект. Но в этом случае клиент должен уведомить, хотя бы вызовом того же OnTransReply с соответсвующим сообщением.
Цитата
Nikolay написал: С тиками еще сложнее - их много пройдет после заказа данных и до "окончания" загрузки. В связи с этим хотелось бы понять: первый size отличный от 0 - это что? Как его интерпретировать?
На рабочее место загружено такое-то количество свечей. По другому - никак. Я и не настаиваю на интерпретации "окончания загрузки". Об "окончании загрузки" можно с уверенностью говорить только по завершении торгов, когда известно, что свечей не прибавится. Дадут ds:ServerSize() будем с ним работать )) Вариант
Код
while ds:Size() ~= ds:ServerSize() do sleep end
тоже вполне рабочий для определённых целей.
Цитата
Anton написал: Они едут в ТВС всей (заказанной) толпой, по отдельным датасорцам их клиент должен разбирать, так что серверу тут нечего отправить в качестве текущего количества свечей по конкретному тикеру. Можно даже предположить, что он и по всей ТВС затруднился бы сказать, сколько у него тиков в моменте.
Серверу ведь не составило бы труда посчитать каждый тик по приходу и положить результат на полочку, если он уже этого не делает.
Надо делать так, как надо. А как не надо - делать не надо.
Anton написал: Дык он не теряется, насколько мне известно, в потоке ответ есть, колбек не дергается почему-то.
Можете проверить, если будет желание. Имитация разрыва соединения с сервером:
Код
w32 = require('w32')
run = true
trans_id = 123
function OnStop()
run = nil
end
function main()
-- Разорвать соединение с сервером
w32.PostMessage(w32.FindWindow('InfoClass', ''), 0x0111, 101, 0)
sleep(100) -- Тут надо отрегулировать задержку, чтобы транзакция гарантированно была отправлена серверу
-- При большой задержке sendTransaction отрабатывает без ошибки, хотя по факту транзакция не отправлена (?)
if not isConnected() == 1 then
message('Not connected', 3)
return
end
local transaction = {
TRANS_ID = ""..trans_id,
ACTION = "NEW_ORDER",
ACCOUNT = account,
CLIENT_CODE = client,
CLASSCODE = class_code,
SECCODE = sec_code,
OPERATION = "B",
TYPE = "L",
PRICE = price,
QUANTITY = "1"
}
local err = sendTransaction(transaction)
if err == "" then message('sendTransaction: OK', 2)
else message(err, 3) end
while run do sleep(1000) end
end
function OnDisconnected()
message('OnDisconnected', 2)
end
function OnTransReply(trans_reply)
message('OnTransReply:\n' .. trans_reply.result_msg, 2)
end
function OnOrder(order)
if order.trans_id == trans_id then
message('OnOrder: OK', 2)
end
end
После восстановления соединения получаем OnOrder. OnTransReply не вызывается. Повторяет ли сервер отправку неподтвержденного OnTransReply не знаю.
Скрытый текст
Anton, вот здесь конкретная формулировка, аналогичная вашему предложению. Следующий комментарий от Sergey Gorokhov показывает отсутствие понимания, что данные не могут мгновенно появиться, для него сервер - что-то локальное.
Цитата
Anton написал: как эту схему на тики распространить.
А что с тиками не так?
Надо делать так, как надо. А как не надо - делать не надо.
Проблема в том, что Sergey Gorokhov, не понимает, что данные по сетям передаются не мгновенно, требуется какое-то время, пока клиент их получит. Конечно, откуда ему знать, он же в одной сети со своим игровым сервером QUIK Junior сидит. У него всё приходит, как с локального сервера, быстрее, чем он может подумать. Да и нет там такого объёма трафика, чтобы были задержки какие-то. Вот и говорит Sergey Gorokhov, вот вам ds:Size(). Если там ноль, значит свечей нет. И невдомёк ему, что в реальном мире всё не так. А пока Sergey Gorokhov, предложение не одобрит, оно не будет принято. Модератор, однако.
Надо делать так, как надо. А как не надо - делать не надо.
Anton написал: можно бы предложить возвращать из ds:Size nil вместо нуля, пока с сервера что-нибудь не приехало (хоть бы и ноль).
Три года назад я это предлагал. Вообще моё предложение, вроде, как не противоречит механизму клиент-серверного общения по протоколу TCP "Запрос-Ответ": Клиент посылает запрос серверу, тот в ответ либо сразу пушит данные, если они есть, либо отвечает, что данных нет. Пока нет. Они, может быть, и появятся когда-нибудь, но мы этого не знаем. А что делать с этой информацией вы уже решаете сами.
Скрытый текст
И если немного отвлечься от темы, то механизм TCP гарантирует уведомление отправителя о результатах передачи. И почему ответ OnTransReply на транзакцию может потеряться - сие остаётся загадка.
Надо делать так, как надо. А как не надо - делать не надо.
Anton, задачи, ведь, могут быть разные, как считаете? Есть, скажем, задача обработать стотыщ графов: отрыть каждый, посчитать чё-то там, закрыть, чтоб память не жрал, выдать результат. Может быть такая задача? Почему нет? Можно, конечно, работать и в колбеках, наплодить стотыщ data_source и ждать когда Квик рухнет с нехваткой памяти. Ну это как спорить: как правильно, делать всю работу в main или в колбеках. Нет однозначного ответа. Для каждой задачи нужен свой подход.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель написал: Последние два поста я вам пишу о ситуации, когда задан валидный инструмент, но графика нет по нему.
Посмотрел историю на форуме, пожелание регистрировали более трёх назад. И даже признали потенциально целесообразным. Так, что, надеемся, в ближайшем десятилетии реализуют. Sergey Gorokhov, можете расслабиться, более объяснять не буду, что для того, чтобы скачать график исторических (прошлых) данных, машина времени с заглядыванием в будущее не нужна.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: Функция которая лезет на сервер для проверки того что есть на сервере, никак не может одновременно смотреть на клиента.Функция такая взяла залезла на сервер, посмотрела что там есть и вернула клиенту какой-то результат, без какого-либо участия клиента.
Ничего не понял, что вы тут написали. Попробую на пальцах схеме: 1) Вызываем CreateDataSource(). Клиент либо создаёт объект, либо сообщает об ошибке. При этом он не только проверяет валидность всех параметров, но и успешность подписки. Под успешность я также понимаю, что в интерфейсе должны также проставиться все галочки: если я запрашиваю параметр, то он должен добавиться в список принимаемых либо сообщить об ошибке.
2) Если data_source создан, то клиент чё-то там отправляет серверу, в ответ последний отправляет клиенту запрашиваемые свечи или флаг, что свечей сервер не имеет.
3) После получения данных с сервера клиент заполняет у себя data_source (если свечи имеются) и флаги true/false.
Ежели мы запросим DS:Чё_Есть_На_Сервере_Брокера() между 2 и 3, то получим nil, потому что флаги ещё не пришли с сервера, про биты помните?
Цитата
Sergey Gorokhov написал: включая "инструмента нет", но сразу возникает вопрос, а если инструмент спустя мгновение возьмет и появится?
Тут же, вроде, и объект не должен создаваться и CreateDataSource вернёт ошибку, не?
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: про nil не понятно, при каких обстоятельствах он по Вашему должен проявляться.
nil - это, когда вы запрашиваете DS:Чё_Есть_На_Сервере_Брокера() до того, как клиент получил информацию с сервера. Биты, они, ведь, не мгновенно передаются, понимаете?
Цитата
Sergey Gorokhov написал: и не понятно, как сервер должен понять что информация "обязательно" будет
Из понимания, как оно должно работать. Сервер обязан уведомить клиента как о наличии свечей (тогда он сразу передаёт сами свечи), так и об отсутствии свечей (флаг false). Вы же сами пишите:
Цитата
Sergey Gorokhov написал: По идее он должен вернуть пустые значения
А вот мы не знаем, возвращает ли сервер что-то, если графика нет. Клиент сразу создаёт пустой объект. Как понять, что сервер уже чё-то вернул? В вашем случае ожидание
Код
while DS:Size() == 0 do sleep end
может привести к бесконечному циклу.
Сравните:
Код
while DS:Чё_Есть_На_Сервере_Брокера() == nil do sleep end
if DS:Чё_Есть_На_Сервере_Брокера() == true then
-- свечи есть, работаем дальше
else
-- свечей нет, идём по своим делам
end
Цитата
Sergey Gorokhov написал: Вы сейчас про "все данные загружены" или про nil?
Про false
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov, Рассмотрите на примере http-сервера. Когда запрашиваемой страницы нет, но есть заглушка, вы видите страницу 404. Если заглушки нет, то вы будете целый день сидеть перед пустым монитором или пока не надоест. Придумали в прошлом веке, а вы говорите "десятки лет"...
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: По идее он должен вернуть пустые значения, разве нет?
А как понять, что сервер уже вернул эти пустые значения? Они ведь у вас по дефолту и так возвращаются. Пусть, скажет, что у него нет свечей, чтоб не ждать понапрасну.
Типа такой функции что ли:
DS:Чё_Есть_На_Сервере_Брокера() true - свечи есть false - нет свечей nil - информации о наличии свечей пока нет, но она обязательно будет, приходите позже
Надо делать так, как надо. А как не надо - делать не надо.
s_mike@rambler.ru написал: нет возможности отследить, почему нет котировок. Или нет свечей в принципе,
да такой возможности нет, и сам сервер этого не знает. От куда серверу знать будут ли торги по инструменту или трейдеры вообще ничего сегодня не купят?
Машину времени изобретаете? Об этом никто и не спрашивал. Пусть сервер скажет: у меня свечей нет сейчас, узбагойся чувак. Но он же ж молчит, аки партизан. А ты крутись, программер, как хошь.
Надо делать так, как надо. А как не надо - делать не надо.
Если залогиниться в QUIK под другим пользователем (не закрывая программу), то на открытых графиках остаются треугольники от сделок и линии заявок от предыдущего пользователя.
Надо делать так, как надо. А как не надо - делать не надо.
Я так понимаю, вопрос возник, когда в os.time() был передан какой-нибудь квиковский datetime = {year=1601, month=1, day=1, hour=0} Если в 5.1 тут возвращался nil, и с ним можно было работать, то теперь перед вызовом os.time надо проверить, как минимум год, чтобы не получить исключение
Надо делать так, как надо. А как не надо - делать не надо.
Часовой пояс, как бы, ни при чём. В 5.1 если дата была меньше 0, os.time возвращал nil, с которым в общем-то можно было работать. В 5.3 в этом случае вы увидите "time result cannot be represented in this installation".
Надо делать так, как надо. А как не надо - делать не надо.
e2e4 написал: сделал проверку, что если скрипт останавливается вручную, то вывода из main в таблицу не будет, а будет из OnStop и наоборот
Но, если есть обращения к таблице в main внутри цикла while isRun do, тут уже сложнее. Чтобы QUIK не подвисал при остановке, и скрипт корректно завершался, первым делом в OnStop удаляю идентификатор таблицы.
Надо делать так, как надо. А как не надо - делать не надо.
Заявка на покупку акции после определённого отката вниз от определённой цены., Заявка на покупку акции после определённого отката вниз от определённой цены.
Старатель написал: ставьте квик в Users\%USERNAME%
И любой скрипт от этого юзернейма (даже не бинарник) может заменить info.exe на что угодно, делающее что угодно.
Тогда вот:
Цитата
swerg написал: QUIK вполне себе работает на несколько пользователей на машине за счет того, что все настроечные файлы читает из "рабочего каталога", а не оттуда, где лежит info.exe И туда же и пишет
Сделать ярлык LNK с указанием Рабочей папки и работай хоть от сотни юзеров. Только не забывайте, что если вы хотите, чтобы
Цитата
Anton написал: в домене юзер сможет запускаться с любого компа организации и получать свой личный профиль
то на всех компах должна быть одинаковая версия QUIK.
Надо делать так, как надо. А как не надо - делать не надо.
Anton написал: Тогда можно запустить один квик от двух пользователей, у каждого будет своя копия данных и все будет работать независимо друг от друга.
От двух пользователей, на одном компе, одновременно. Интересно, зачем это может понадобиться? Да пожалуйста, ставьте квик в Users\%USERNAME%
Цитата
Anton написал: roaming это место для перемещаемых профилей, в домене юзер сможет запускаться с любого компа организации и получать свой личный профиль.
Ответ тот же.
Скрытый текст
Ещё не хватало, чтобы Арка заморачивалась с профилями, групповыми политиками и прочая
Надо делать так, как надо. А как не надо - делать не надо.
Ну, например, если бумага не маржинальная или не шортовая. Вы купили несколько лотов и тут же выставляете их на продажу, а баланс ещё не успел измениться, вот и отклоняет сервер вашу заявку. А вообще в ответе на транзакцию обычно указывается причина.
Надо делать так, как надо. А как не надо - делать не надо.
Было бы неплохо, если бы наконец устранили древнюю проблему, когда цвета таблицы, установленные из скрипта в SetColor, сбрасываются при применении фильтра.
Надо делать так, как надо. А как не надо - делать не надо.
Ответ в категориях "наверное", "по идее" и т.п. не устраивает. Мы с вами не баллистические ракеты проектируем Можете пригласить тов. Nikolay Pavlov, надеюсь он сможет что-то конкретное сказать.
Надо делать так, как надо. А как не надо - делать не надо.
getTradeDate() в OnCleanUp всегда даёт актуальную дату торговой сессии или это у меня так совпало?
Скрытый текст
Чтобы не вставать два раза, поясню: В данной теме обсуждается проблема получения в OnCleanUp параметра "Дата торгов" через запрос getInfoParam("TRADEDATE"). И действительно данный запрос в OnCleanUp возвращает дату предыдущей торговой сессии. Как обстоит дело с getTradeDate()?
Надо делать так, как надо. А как не надо - делать не надо.
Evgeniy Karnaukhov написал: Если SetCell сработает между этими вызовами, то, так как строка уже удалена и не найдена, она будет добавлена вновь.
Зачем?
Цитата
Evgeniy Karnaukhov написал: возможна ситуация, при которой строка уже удалена, но новая не вставлена.
Пример без InsertRow:
Код
rows = 20
function OnParam()
if not run then return end
rows = rows - 1
DeleteRow(id, 1)
if rows == 10 then run = nil end
end
function main()
id = AllocTable()
AddColumn(id, 1, 'row', true, QTABLE_INT_TYPE, 15)
CreateWindow(id)
SetWindowPos(id, 0, 0, 110, 350)
for i = 1, rows do InsertRow(id, -1) end
run = true
while run do
SetCell(id, 5, 1, tostring(rows))
sleep(1)
end
for row = 0, GetTableSize(id) do
SetCell(id, row, 1, tostring(row))
end
end
Результат:
Обсуждаемая проблема может возникнуть в любом скрипте, в котором в одном потоке пишутся данные в таблицу, а в другом удаляется строка из начала/середины таблицы. Предложение Антона создать пользовательский колбек выглядит разумным. Да и в других ситуациях такой колбек не помешал бы.
Надо делать так, как надо. А как не надо - делать не надо.