_sk_ (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: Пред. 1 2 3 4 5 6 7 8 9 10
QUIK (версия 7.0.1.5), function OnTrade(trade), трехкратный вызов на одно событие.
 
Цитата
Чисто технически, да могут поменяться Чисто практически, такая ситуация маловероятна
Это плохо, если разработчики говорят в терминах вероятностей о поведении программы.

Представим, что пришла информация о сделке, где комиссии указаны нулевые. Это может произойти, если сделки по фьючерсу идут внутри дня. Адекватная торговая программа пишет в какой-нибудь лог информацию о сделке с нулевой комиссией, а потом ВНЕЗАПНО обнаруживается, после прихода ещё одного коллбэка, что комиссии-то ненулевые! Вот засада и головная боль для программиста! Надо либо в лог дописать, что, мол, фигня вышла, вот правильная информация о сделке, либо действовать по принципу: хочешь записать что-то в лог -- подожди некоторое время в надежде, что вдруг всё не так на самом деле.

А хорошо -- это описать, что такие-то и такие-то блоки данных изменяются атомарно и однократно. В документации это будет?
QUIK (версия 7.0.1.5), function OnTrade(trade), трехкратный вызов на одно событие.
 
Хотелось бы увидеть ответы на мои вопросы выше по теме от сотрудников техподдержки.
QUIK (версия 7.0.1.5), function OnTrade(trade), трехкратный вызов на одно событие.
 
Цитата
Серверу чтобы проставить эти обновленные параметры приходится отправлять сделку несколько раз.
Т.е. это зависит от сервера и подобная засада может образоваться и для пользователей Quik 6-й версии?  :shock:
QUIK (версия 7.0.1.5), function OnTrade(trade), трехкратный вызов на одно событие.
 
Осталось надеяться, что если мы в очередной коллбэк OnTrade увидели установленные поля
  • class_code,
  • sec_code,
  • price,
  • qty (или как он там теперь будет называться),
  • order_num (или как он там теперь будет называться),
  • trade_num,
  • clearing_comission,
  • exchange_comission,
  • tech_center_comission,
  • datetime,
  • settle_date,
то при последующих коллбэках эти поля уже не поменяют свои значения.

Или могут и поменять?  :shock:   :cry:   :evil:
несколько транзакций за одну секунду
 
Цитата
stime = tostring(GetInfoParam("SERVERTIME"))
base_time = "12:15:50"
someflag = 0
if stime == base_time then ...
Иногда бывает (я с этим реально встречался не раз), что stime сначала равен 12:15:49, а потом сразу 12:15:51, и робот пропустит сигнал. Поэтому логика должна быть несколько другая. Словами можно описать так: если base_time <= stime <= base_time + несколько секунд и ещё не было срабатывания, то исполнить, что надо, и поднять флаг срабатывания. Флаг срабатывания также нужно сбросить, если stime > base_time + несколько секунд.
Как быть с ошибками вида "function: 94A71D38"
 
Это хорошо, что Вам удалось воспроизвести ошибку. Только я не понял, это недоработка в QUIK или ошибка в Lua.

Цитата
Попробуйте на время избавиться от использования socket, если она Вам нужна только для получения системного времени, и понаблюдать за поведением.
Мне в программе нужно получать время с точностью до миллисекунд. У луа стандартная функция os.time() не даёт миллисекунд. Если бы в QLua была функция gettime() с миллисекундами, то можно было бы обойтись и без socket.
Как быть с ошибками вида "function: 94A71D38"
 
Код прислать не могу, т.к. политика безопасности не позволяет. Как написать короткий провоцирующий код, мне пока неясно, т.к. источник проблемы непонятен.

Исходя из того, что пишется в лог, происходит следующее.
1) При выполнении кода ... возникает ошибка, но почему-то до обработчика ошибок дело не доходит, иначе в логе было бы как минимум две строки: причина ошибки + трасса стека.
2) Обработчик ошибок ничего не возвращает, поэтому по спецификации луа переменная errMessage должна быть nil.
3) Однако, функция xpcall возвращает в качестве результатов пару false, "function: 94A71D38", поэтому срабатывает if и в лог печатается одна строка.

Выглядит это как внутренняя ошибка луа-машины, поскольку спецификация не соблюдена, а внутри своего кода я использую только стандартный луа-код (без dll, C API и пр.) и одну библиотеку Socket для получения времени с помощью функции gettime(). Возможно, что ошибка произошла при попытке вызвать обработчик ошибок, и так проявилась. Возможно, что это какой-то компьютерный сбой, не относящийся к QUIK и луа.

Я могу парсить errMessage и если он имеет вид "function.*", то выводить в свой лог ещё какие-то подробности о внутренностях луа-машины. Только я не знаю, что именно надо выводить. Если есть предложения -- напишите.

В остальном, предлагаю поставить эту тему на паузу до повторной эскалации. В сравнении с этой ошибкой в последнее время глюки биржи идут заметно чаще и доставляют больше проблем.
Как быть с ошибками вида "function: 94A71D38"
 
Цитата
Старатель пишет:
В скрипте используются какие-то сторонние библиотеки?
Так при использовании сторонних библиотек, скрипты в QUIK иногда могут падать с ошибкой "Unknown error."
Применяется только gettime() из библиотеки Socket. Остальное всё самописное.
Цитата
Николай Камынин пишет:
попробуйте убрать свой перехват ошибок.
возможно тогда ошибка вывалится в dump,
либо получите больше сообщений из перехвата луа машины.
Такой вариант не удобен, т.к. свои ошибки тоже нужно контролировать с подробностями (трасса стека не пишется в окно об ошибках скриптов).

Вряд ли без помощи разработчиков QUIK и сохранения ошибок луа-машины в некий дамп можно что-то конструктивное сделать. (В Java, например, если виртуальная машина по какой-то причине падает с внутренней ошибкой, пишется некий err-файл, где хоть какие-то подробности приводятся.)
CreateDataSource
 
Цитата
_sk_ пишет:
1) В одном скрипте создаются несколько объектов DataSource по одному инструменту на одном таймфрейме. Внутри QUIK это будут независимые объекты, каждый из которых хранит свои данные, или объекты, имеющие ссылку на общий массив свечных данных?
Сам спросил, сам провёл эксперимент, создав 10 000 экземпляров DataSource, имеющих по 3000 свечей, в рамках одного скрипта. Использованная память практически не изменилась, так что у всех этих объектов один массив свечных данных.
Вопрос о целостности данных при работе с таблицей из разных вычислительных потоков
 
Спасибо, можно считать, что тема закрыта.
Вопрос о целостности данных при работе с таблицей из разных вычислительных потоков
 
Я понимаю, почему функции table.sinsert и table.sremove введены в QLua: надо не только вставить/удалить один элемент, но ещё и сдвинуть остальные элементы таблицы по номерам.

Как написано выше по ссылке, я сам так делаю при передаче данных из коллбэков в main. Вопрос был про одиночное добавление/удаление элементов в таблицу без сдвига всех остальных. По идее, он должен работать, иначе будет рушиться даже этот алгоритм.
Как быть с ошибками вида "function: 94A71D38"
 
В первом сообщении темы написан фрагмент функции main(). В скрипте только один xpcall, перехватывающий ошибки на самом последнем уровне. Вместо многоточия идут вызовы инициализации скрипта, цикл while is_running, закрытие ресурсов. Поэтому предоставить содержательный код не могу.

Было бы неплохо при таком как у меня падении скрипта, создавать что-то типа dump-файла с внутренним состоянием lua-машины, чтобы разработчики могли хоть как-то понять, что пошло не так.
CreateDataSource
 
Есть вопросы по внутренней реализации DataSource.

1) В одном скрипте создаются несколько объектов DataSource по одному инструменту на одном таймфрейме. Внутри QUIK это будут независимые объекты, каждый из которых хранит свои данные, или объекты, имеющие ссылку на общий массив свечных данных?

2) В разных скриптах создаются объекты DataSource. Вопрос тот же.

Спрашиваю потому, что по моим наблюдениям при переходе от использования данных с графиков на использование данных из DataSource выросло использование памяти терминалом QUIK и были прецеденты, когда вылетало окно о нехватке памяти. Хочется стабильности и приходится понимать, при какой реализации потребуется меньше памяти.

Нет ли в QUIK ситуации, когда сборщик мусора не может избавиться от каких-то старых данных DataSource из-за того, что не все ссылки сброшены в nil?
Как быть с ошибками вида "function: 94A71D38"
 
Версия терминала 6.17.3.6. Ошибка возникла при торговле на десятке счетов при параллельной работе порядка 8 скриптов. Пример кода я предоставить не могу: реально эксплуатирующуюся систему показать невозможно, а модельного кода, где воспроизводится ошибка, у меня нет.
Вопрос о целостности данных при работе с таблицей из разных вычислительных потоков
 
Предположим, что в скрипте заведена таблица t. В потоке коллбэков в функции OnAllTrade() в таблицу t вставляются элементы. Пусть ключом будет цена, а значением -- номер сделки. В потоке main из этой таблицы происходит чтение данных по ключу. Поскольку потоки работают параллельно, то не исключена, например, такая ситуация.

1) В потоке коллбэка в таблицу вставляется новый элемент, что приводит к необходимости перестройки внутренней структуры таблицы t (не знаю, как реализована таблица внутри Lua, но по аналогии c реализацией хэш-таблиц в Java допускаю, что иногда при вставках приходится существенно поменять внутренности объекта).

2) Процесс внутренней перестройки таблицы ещё не закончен, её внутреннее состояние неконсистентно, а в параллельном потоке main() начинается чтение из таблицы t по какому-то ключу.

Вопросы:

а) Есть ли гарантия, что из таблицы будет корректно прочитан элемент (возможно, nil), а не произойдёт какая-то ошибка?

б) А если в п.1 элементы удаляются из таблицы?

Спрашиваю потому, что одно дело обеспечить целостность примитивных данных, другое дело -- объектов со сложной внутренней структурой. Разработчики QLua не зря добавили специальные "Потокобезопасные функции для работы с таблицами Lua". Если добавление/удаление данных из lua-таблиц в самой lua-машине реализовано потокобезопасно, то это положительно отвечает на вопросы а) и б). Если нет -- тогда беда.
Как быть с ошибками вида "function: 94A71D38"
 
Цитата
Николай Камынин пишет:
по-моему это ошибка не квик, а луа скрипта, либо ,в крайнем случае , луа машины.
у меня так не падает, поэтому делаю вывод, что проблема в Вашем скрипте.
Похоже, что это ошибка луа-машины. Выяснить бы, что является причиной: ошибки в самой луа-машине или недоработки в реализации связки QUIK + LUA. Во втором случае можно было бы надеяться на то, что такие недоработки будут исправлены. Жаль, что разработчики QUIK молчат по первому вопросу этой темы. Наверное, действительно, ничем не могут помочь.
Добавить функцию getServerTime()
 
Время сервера и время последней записи имеют один источник времени -- сервер QUIK. Локальное время компьютера тут не причем, оно идёт само по себе.

Рекомендуется:

1) синхронизировать время на локальном компьютере с помощью соответствующих программ;

2) отслеживать разницу во времени между локальными часами и временем сервера: если она больше нескольких секунд, то, возможно, информация из QUIK показывает заметно устаревшую картину рынка.
Как быть с ошибками вида "function: 94A71D38"
 
В моих скриптах реализован перехват ошибок и печать информации об их причинах следующим образом:

Код
local status, errMessage = xpcall(function()
...
end, function(err)
  logger:error(tostring(err))
  logger:error(debug.traceback())
end)
if not status and errMessage ~= nil then
  logger:error(errMessage)
end

В обычных ситуациях возникновения ошибок по вине программиста в лог печатается информация об ошибке и трасса стека типа:

Код
2015-09-01 12:00:00.123 [ERROR] D:\Quik\lua\ScriptName.lua:123: Attempt to call method 'MethodName' (a nil value).
2015-09-01 12:00:00.123 [ERROR] stack traceback:
.....

Иногда (скажем, раз в неделю) скрипты падают с сообщениями вида:

Код
2015-09-01 12:00:00.123 [ERROR] function: 94A71D38
Поскольку трассы стека нет и сообщение об ошибке весьма краткое, полагаю, что это внутренняя ошибка QUIK. Как быть с ошибками такого вида? В идеале хотелось бы понять, что их вызывает и как быть, чтобы их больше не было.

Воспроизведение таких ошибок, по-видимому, весьма проблематично.

Разработчики QUIK могут как-нибудь помочь в этом деле?
Получение данных с помощью getParamEx
 
Старатель,спасибо за разъяснения. По-хорошему, это должно быть указано разработчиками QUIK в документации явным образом.
Получение данных с помощью getParamEx
 
Гипотеза такая была, которую я не проверил. В документации написано:
Цитата
Функция предназначена для получения значений всех параметров биржевой информации из Таблицы текущих значений параметров. С помощью этой функции можно получить любое из значений Таблицы текущих значений параметров для заданных кодов класса и бумаги.
Я понял буквально.

Выходит, что если в ТТП нет инструмента или все ТТП вообще закрыты, то данные всё равно доступны через getParamEx, если их получение настроено через "Связь -> Списки"?
Получение данных с помощью getParamEx
 
Чтобы получить свечные данные, можно использовать открытый график и getCandlesByIndex, а можно не открывать график и применять DataSource. Второй способ лучше, т.к. пользователь может случайно закрыть график и скрипт перестанет получать данные.

Чтобы получить данные стакана, можно открыть стакан, а можно не открывать стакан, а вызвать функцию Subscribe_Level_II_Quotes. Второй способ лучше, т.к. пользователь может случайно закрыть стакан и скрипт перестанет получать данные.

По аналогии, хочется, чтобы функция getParamEx выдавала данные по инструменту всегда, вне зависимости от того, открыта ТТП с этим инструментом и нужными полями или нет. Можно ли как-то гарантировать эту функциональность? Если нет, то может имеет смысл добавить функцию Subscribe_Param(classCode, secCode)?
CreateDataSource()
 
Вопрос был про начальную загрузку данных, ведь для них callback-функции не вызываются. Потом, нужные операции я произвожу в callback-функции.

Сообщение от Constantinа пугает. Неужели при разрыве связи и её восстановлении через несколько минут не все callback-функции будут вызваны для вновь поступивших 1-минутных свечей? Если это так, это обязательно нужно указать в документации.
CreateDataSource()
 
В документации по QLua про это не написано, поэтому спрошу тут.

Предположим, что запускается скрипт, в котором создаётся dataSource ds и задаётся callback-функция. Сначала ds:Size() возвращает 0, скрипт в цикле ждёт, пока с сервера закачаются данные. Потом, через некоторое время, ds:Size() возвращает положительное число. Есть ли гарантия, что после этого для всех обновляющихся старых и новых свечей будет вызываться callback-функция?

Не хотелось бы иметь ситуацию типа, когда значение ds:Size() сначала равно 0, потом прыгает на 1500 (закачалась часть данных), потом становится равным 3000 (закачался остаток данных), после чего идут callback-функции для свечей с номерами 3000 и выше.

Вопрос к разработчикам: есть ли такая гарантия?
Добавить функцию getServerTime()
 
В QUIK есть функция getTradeDate() для получения даты торговой сессии. Эту же информацию можно получить в виде строки с помощью функции getInfoParam("TRADEDATE"). Также с помощью getInfoParam("SERVERTIME") можно получить текущее время сервера в виде строки. Скомбинировав дату и время, и учтя переход через 24:00, можно получить текущую дату/время сервера.

Кажется, что этот способ несколько мудрёный для рядового lua-пользователя.

Предлагается добавить в qlua функцию getServerTime(), которая возвращает текущее время сервера в виде числа (примерно то же самое возвращает os.time()). Если при этом будет возвращаться время с миллисекундами/микросекундами после десятичной запятой, то будет совсем хорошо.

Время в виде числа  таблицу с полями year, month, day, hour, min, sec, isdst можно будет перевести с помощью стандартной функции os.date("*t", time). Либо можно добавить аргумент в функцию getServerTime() по смыслу аналогичный аргументу стандартной функции os.date(), чтобы получать не только таблицы, но и строки времени различного формата.

Если будете добавлять эту функцию, обеспечьте, пожалуйста, монотонность течения времени (к примеру, результаты getInfoParam("LASTRECORDTIME") этому свойству не удовлетворяют).
Логирование ошибок выполнения скрипта
 
Вот пример. Предполагается, что у Вас уже реализован некий логгер logger для записи сообщений в файл. Можно вместо этого открыть файл file и писать туда с помощью функции file:write().
Код
function main()
    logger:info("STARTED") -- Ваш логгер
    local status, errMessage = xpcall(function()
     -- Код Вашего скрипта
    end, function(err)
     logger:error(tostring(err))
     logger:error(debug.traceback())
    end)
    if not status and errMessage ~= nil then
     logger:error(errMessage)
    end
    logger:info("SHUTDOWN\n")
    logger:close()
end
getCandleByTime
 
Уже существует функция getCandlesByIndex, которая выдаёт несколько последовательных свечей с графика. Иногда хотелось бы получать свечу по её времени. Скажем, пусть будет что-то вроде функции getCandleByTime(datetime), которая выдаёт свечу либо с указанным временем, либо, если именно такого времени нет, то самую последнюю свечу, время которой ещё меньше указанного момента в datetime. Если такой свечи нет, пусть выдаётся nil.

Можно это реализовать с помощью двоичного поиска, запрашивая по одной свече с помощью getCandlesByIndex, но это недружественно для пользователя. Возможно, что разработчики QUIK могут сделать более эффективную реализацию (не знаю, как устроены графики внутри QUIK).

Предлагается обсудить это предложение. Возможно, доработать его, чтобы было как можно более удобно такой функциональностью пользоваться как можно более широкому кругу пользователей. А потом пусть будет зарегистрировано такое пожелание для дальнейшей реализации.
Страницы: Пред. 1 2 3 4 5 6 7 8 9 10
Наверх