QUIK не отправляет заявку, в которой цена представлена переменной
Пользователь
Сообщений: Регистрация: 22.10.2020
16.03.2021 19:23:04
Всем привет! Объясните мне, пожалуйста, нижеследующий завих QLUA. Вот так заявка отправляется:
Код
function main()
Transaction={
["TRANS_ID"] = "1005001",
["ACTION"] = "NEW_ORDER",
["CLASSCODE"] = "SPBFUT",
["SECCODE"] = "RIH1",
["OPERATION"] = "B", -- операция ("B" - buy, или "S" - sell)
["TYPE"] = "L", -- L - лимитная
["QUANTITY"] = "1", -- количество
["ACCOUNT"] = "SPBFUT001bm",
["PRICE"] = "155500"
}
sendTransaction(Transaction)
end
А вот так игнорирует заявку:
Код
function main()
local PRCStr = tostring(tonumber(getParamEx("SPBFUT", "RIH1", "LAST").param_value) + 50 * tonumber(getParamEx("SPBFUT", "RIH1", "SEC_PRICE_STEP").param_value))
Transaction={
["TRANS_ID"] = "1005001",
["ACTION"] = "NEW_ORDER",
["CLASSCODE"] = "SPBFUT",
["SECCODE"] = "RIH1",
["OPERATION"] = "B", -- операция ("B" - buy, или "S" - sell)
["TYPE"] = "L", -- L - лимитная
["QUANTITY"] = "1", -- количество
["ACCOUNT"] = "SPBFUT001bm",
["PRICE"] = PRCStr
}
sendTransaction(Transaction)
end
В двух словах: в первом примере цена лимитника задана непосредственно строкой в поле, во втором варианте цена задана переменной. Цена во втором случае высчитывается нормально и выводится в окно оповещений, но заявка не отправляется. Скрипт просто проходит по коду без какой-либо реакции. Ошибок также не выводит. Кто-нибудь знает ЧТО ЭТО ЗА БРЕД? Терминал обновлял. Демо версия 8.11.0.66. Счет зарегистрирован у ARQA. Перезагружался. Монитор протирал.))) Мышку гладил.))) Мастдай не переустанавливал. Не предлагать.
Пользователь
Сообщений: Регистрация: 02.02.2015
миру мир!
16.03.2021 19:44:42
Цитата
Андрей написал: Цена во втором случае высчитывается нормально
Что такое нормально? Что выводится в окно сообщений, какое значение имеет PRCStr ?
Пользователь
Сообщений: Регистрация: 22.10.2020
16.03.2021 20:00:11
В дополнение: OnTransReply не выводит своей таблицы, когда цена задана переменной. Прописал цикл сна до получения статуса транзакции, но скрипт выходит из цикла по истечению установленного времени (20с) так и не получив никакого статуса транзакции. Это явно проблема на стороне клиента. Если бы заявки на сервер уходили, ответ бы возвращался. Только вот в чем может быть проблема я не пойму.
Знаю, сталкивался с этим. В переменной PRCStr у тебя строка типа "12345.0" А в транзакцию цену надо передавать строку с учетом шага цены "12345"
Короче, точку с нулем из строки похерь и будет счастье
Код
function cut_zero(str)
local num=tonumber(str)
local zero=string.byte("0",1)
local point=string.byte(".",1)
if(string.find(num,'%.')) then -- Имеется точка в числе
for n=string.len(num),1,-1 do -- Перебор справа налево
if(string.byte(num,n)==point) then return string.sub(num,1,n-1) end
if(string.byte(num,n)~=zero) then return string.sub(num,1,n) end
end
end
return num
end
Пользователь
Сообщений: Регистрация: 22.10.2020
16.03.2021 21:11:07
В общем решена проблема. При запросе последней цены и шага цены QUIK зачем-то выводит еще и дробную часть числа, которой в таблице и на бирже и в помине нет и, соответственно, сервер дробные числа также не принимает. В частности по фьючерсу РТС вместо цены 155310 выводит 155310,0. То же самое и с шагом цены вместо 10 выводит 10,0.
Код
tonumber(getParamEx("SPBFUT", "RIH1", "LAST").param_value) -- Выводит десятичное число
tonumber(getParamEx("SPBFUT", "RIH1", "SEC_PRICE_STEP").param_value) -- Выводит десятичное число
Поэтому если работаете с ценами, которые заведомо не имеют дробных частей, то округляйте все запросы к таблицам до целого на всякий случай. Кто знает, где системой еще самостоятельно типы будут преобразовываться.
PS Вопрос к разработчикам, неужели нельзя было включить элементарную проверку типов в функции запроса данных из таблиц? Принцип программирования - что запросил то и получил здесь нарушен. В таблицах по фьючу РТС явно целочисленные значения приводятся, да и биржа тоже целые транслирует, а система QUIK их самостоятельно выводит как десятичные. Я понимаю, что в недоязыке LUA непредусмотрено целочисленных значений, но раз у вас на сервере они фигурируют, то и клиентская сторона должна уметь их ретранслировать.
Знаю, сталкивался с этим. В переменной PRCStr у тебя строка типа "12345.0" А в транзакцию цену надо передавать строку с учетом шага цены "12345"
Короче, точку с нулем из строки похерь и будет счастье
Код
function cut_zero (str)
local num = tonumber(str)
local zero = string.byte ( "0" , 1 )
local point = string.byte ( "." , 1 )
if ( string.find (num,'%.')) then -- Имеется точка в числе
for n = string.len (num), 1 , - 1 do -- Перебор справа налево
if ( string.byte (num,n) = = point) then return string.sub (num, 1 ,n - 1 ) end
if ( string.byte (num,n)~ = zero) then return string.sub (num, 1 ,n) end
end
end
return num
end
Не успел прочитать)))
Пользователь
Сообщений: Регистрация: 02.02.2015
миру мир!
16.03.2021 21:34:39
Цитата
Андрей написал: Принцип программирования - что запросил то и получил здесь нарушен.
Ничего здесь как раз не нарушено. Запрошена цена - её значение возвращается как double. Все логично.
Цитата
Андрей написал: В таблицах по фьючу РТС явно целочисленные значения приводятся, да и биржа тоже целые транслирует
Это не так. Вы путаете транслируемые и отображаемые значения. Просто QUIK в таблицах при отображении учитывает еще параметр "точность цены", отображая лишь то значение цифр после запятой, которое соответствует указанному параметру.
Цитата
Андрей написал: Я понимаю, что в недоязыке LUA непредусмотрено целочисленных значений
И это не так. Добавление .0 после чисел с типом double появилось в Lua5.3, где есть отдельный целочисленный тип. Но он здесь не применим, т.к. бывают инструменты с дробной ценой. Так что цена универсально возвращается как double, а tostring() приписывает при конвертации .0 в таким аргументам (при целом значении).
Вопрос к разработчикам ровно один и простой: неужели до сих пор нельзя сделать так, чтобы параметр Transaction["PRICE"] можно было задавать числом, а не строкой?!
Вопрос к разработчикам ровно один и простой: неужели до сих пор нельзя сделать так, чтобы параметр Transaction["PRICE"] можно было задавать числом, а не строкой?!
Вроде в инструкции указано что все параметры транзакции - строковые.
Пользователь
Сообщений: Регистрация: 03.02.2021
16.03.2021 22:20:21
А собственно: инструкция "Интерпретатор языка Lua", раздел 3.11 "Функции для работы с заявками", пункт 1 функция "sendTransaction", примечание жирным текстом:
Цитата
ВАЖНО! Для корректной обработки данных числовые значения (цена, количество, идентификатор транзакции и т.д.) должны передаваться в виде строковых значений.
Тут собственно ваша ошибка/лень. Протокол - строковый, конвертируйте ваши значения в строки.
Пользователь
Сообщений: Регистрация: 02.02.2015
миру мир!
17.03.2021 19:51:53
На документацию тут ссылаться не совсем точно, ибо вообще не очевидно, что строка числового значения "500" подходит, а "500.0" - не подходит. Хотя это одно и тоже числовое значение, представленное строками.
Пользователь
Сообщений: Регистрация: 03.02.2021
17.03.2021 21:39:06
swerg, тут видимо суть в том, чтобы работало по принципу "пропущена запятая - отказ", чтобы надёжно - с реальными деньгами таки дело идёт, так что мало ли. Благо дело при создании формы программным путём, сделать её идальной это невелика проблема.
Код
function TradePriceFormat ( value, accuracy )
return string.format ( string.format ( "%%.%df", accuracy ), value )
end
Тут конечно с неявным округлением последнего знака, но кашу после него всё равно надо как-то округлять в любом случае.
написал: Принцип программирования - что запросил то и получил здесь нарушен.
Ничего здесь как раз не нарушено. Запрошена цена - её значение возвращается как double. Все логично.
Цитата
написал: В таблицах по фьючу РТС явно целочисленные значения приводятся, да и биржа тоже целые транслирует
Это не так. Вы путаете транслируемые и отображаемые значения. Просто QUIK в таблицах при отображении учитывает еще параметр "точность цены", отображая лишь то значение цифр после запятой, которое соответствует указанному параметру.
Цитата
написал: Я понимаю, что в недоязыке LUA непредусмотрено целочисленных значений
И это не так. Добавление .0 после чисел с типом double появилось в Lua5.3, где есть отдельный целочисленный тип. Но он здесь не применим, т.к. бывают инструменты с дробной ценой. Так что цена универсально возвращается как double, а tostring() приписывает при конвертации .0 в таким аргументам (при целом значении).
Цитата
написал: Вопрос к разработчикам
Вопрос к разработчикам ровно один и простой: неужели до сих пор нельзя сделать так, чтобы параметр Transaction["PRICE"] можно было задавать числом, а не строкой?!
Спасибо за разъяснения
Пользователь
Сообщений: Регистрация: 22.10.2020
24.03.2021 17:14:41
Тут собственно говоря проблема была даже не в том, что запятая пропущена, а в том, что клиент не способен корректно пересылать данные на сервер. обратите внимание на строку ниже: она напрямую запрашивает данные с сервера
А потом просто ретранслирует их обратно через переменную
Код
["PRICE"] = PRCStr
В этом и состоял вопрос: почему клиент не умеет корректно работать с данными сервера. А это уже вопрос к разработчикам. Хотя тоже прав: почему они до сих пор все переводится в строковый вариант)))))) Времена ДОС прям-таки)))))
Пользователь
Сообщений: Регистрация: 22.10.2020
24.03.2021 17:23:12
В любом случае в программе есть скрытая функциональность не прописанная в документации (преобразование типов). Проверки типов между клиентом и сервером нет - это точно. И нигде это не прописано.
Пользователь
Сообщений: Регистрация: 25.09.2020
24.03.2021 18:29:31
Андрей, Ну, во-первых, приведённая строка НЕ "запрашивает данные с сервера" - она берёт их из Квика. Во-вторых, во "времена ДОС" софт был на порядки более эффективным и менее глючным. В-третьих, за эту долбаную "динамическую типизацию" я бы разработчикам яйца пообрывал. В-четвёртых, заворачивание в tostring помогает в 9 случаях из 10.
Пользователь
Сообщений: Регистрация: 22.10.2020
24.03.2021 19:24:22
Цитата
Владимир написал: , Ну, во-первых, приведённая строка НЕ "запрашивает данные с сервера" - она берёт их из Квика. Во-вторых, во "времена ДОС" софт был на порядки более эффективным и менее глючным. В-третьих, за эту долбаную "динамическую типизацию" я бы разработчикам яйца пообрывал. В-четвёртых, заворачивание в tostring помогает в 9 случаях из 10.
Я понимаю, что команда обращается к стеку клиента, но ведь потом она пересылает эти данные на сервер. Другими словами в цепи сервер-клиент-сервер присутствует несогласованность в типе данных. То, что делает клиент с типами данных, не воспринимается сервером. А это уже ПРОБЛЕМА. И проблема говорит о том, что сопровождение софта отсутствует полностью.
И вообще, я не понимаю, зачем надо было выбирать глючный LUA, на котором можно только скрипты для игрушек писать, в ущерб тому же несчастному питону. У которого в тысячу раз больше возможностей и который тоже на С (если так нравится разрабам)... Это при том, что LUA изначально не предназначен для точных вычислений и пр. математики (за исключением арифметики).
Пользователь
Сообщений: Регистрация: 27.01.2017
24.03.2021 19:57:27
Питон тоже самое, только тяжелее, медленнее и со своими проблемами.
Что касается клиент серверного взаимодействия, то вне зависимости от языка, прежде чем проводить операции с данными, полученными с сервера, из принято проверять. Они могут быть не получены, они могут быть некорректными. В вашем примере Вы сразу пытаетесь привести значение к числу, не убедившись, что они есть. Если вернется что-то не то, tonumber вернет nil. А далее Вы с этим будете арифметические действия выполнять.
Пользователь
Сообщений: Регистрация: 02.02.2015
миру мир!
24.03.2021 20:06:18
Цитата
Андрей написал: И вообще, я не понимаю, зачем надо было выбирать глючный LUA
В чем его глючность? Вот как языка?
Цитата
Андрей написал: в ущерб тому же несчастному питону
Питона тогда почти не было, когда в QUIK прикручивали Lua. Во всяком случае - он еще не взлетел так массово.
Цитата
Андрей написал: Это при том, что LUA изначально не предназначен для точных вычислений и пр. математики (за исключением арифметики).
Могли бы пояснить эту фразу? в чем заключается "неприспособленность" для указанного?
Пользователь
Сообщений: Регистрация: 22.10.2020
24.03.2021 20:08:14
Цитата
Nikolay написал: Питон тоже самое, только тяжелее, медленнее и со своими проблемами.
Что касается клиент серверного взаимодействия, то вне зависимости от языка, прежде чем проводить операции с данными, полученными с сервера, из принято проверять. Они могут быть не получены, они могут быть некорректными. В вашем примере Вы сразу пытаетесь привести значение к числу, не убедившись, что они есть. Если вернется что-то не то, tonumber вернет nil. А далее Вы с этим будете арифметические действия выполнять.
В данном случае я упростил код. Не буду же я две страницы сюда кидать, заблаговременно зная в чем примерно причина))) Но элементарная проверка типов должна быть на стороне сервера. Программа не должна молчать в случае ввода не типизированных данных.
Пользователь
Сообщений: Регистрация: 22.10.2020
24.03.2021 20:10:56
И это при условии того, что нормального дебагера на LUA нет. И пользуются в квике только функцией message/
Пользователь
Сообщений: Регистрация: 27.01.2017
24.03.2021 20:30:16
А причем здесь сервер? Сервер дает что попросили. getParamEx из кеша теримнала данные вернет, если они есть. А если их заказали с сервера, то они будут обновляться в кеш.
А что программа должна делать, если с сервера не получен ответ. Она просто возвращает в поле result возвращаемой таблицы = "0", что условно и соответствует ошибке получения данных. Это он как раз и говорит - ничего нет. А message - это средство оповещения.
Дебаг - это либо вывод в лог отладочной информации с level = debug. Либо использовать PrintDbgStr. При этом код должен содержать ассерты на входящие данные, чтобы сразу и понять где ошибка.
Пользователь
Сообщений: Регистрация: 25.09.2020
24.03.2021 21:08:53
Андрей, А какая разница, куда там Квик что посылает? Представьте, что вся торговля происходит прямо в Квике! Код упростится в разы, да и надёжность повысится.
У меня прямо противоположное мнение: сопровождение софта неприлично высокое! Только за полгода только на моей памяти три версии сменилось! Нафиг нужно такое сопровождение?
Согласен: Lua - редкостное дерьмо, но раз уж так сложилось, то искать что-либо ещё нет ни малейшего желания! Свой "скрипт для игрушек" я написал, и теперь желаю лишь одного: оставьте всё как есть, хватит улучшать! Версию стабильную даждь нам днесь и избави нас от дебаггера!
Пользователь
Сообщений: Регистрация: 03.02.2021
25.03.2021 12:02:13
Цитата
Андрей написал: Тут собственно говоря проблема была даже не в том, что запятая пропущена, а в том, что клиент не способен корректно пересылать данные на сервер. обратите внимание на строку ниже: она напрямую запрашивает данные с сервера
А потом просто ретранслирует их обратно через переменную
Код
[ "PRICE" ] = PRCStr
В этом и состоял вопрос: почему клиент не умеет корректно работать с данными сервера. А это уже вопрос к разработчикам. Хотя тоже прав: почему они до сих пор все переводится в строковый вариант)))))) Времена ДОС прям-таки)))))
Смею предположить что PRCStr у вас содержит число вида "123.50000000002" в силу особенностей IEEE 64-битных чисел с плавающей запятой. Опытным путём установлено, что даже просто наличие большего количества нулей чем точность цены тоже отвергает транзакцию. Я выше уже написал функцию которая правильно составляет строковое выражение цены.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
25.03.2021 13:05:40
Цитата
swerg написал: неужели до сих пор нельзя сделать так, чтобы параметр Transaction["PRICE"] можно было задавать числом, а не строкой?
Давно можно было, если кто не знал. Но QUIK всё одно преобразует аргумент в строку по своему усмотрению. А считает он, что надо 6 знаков после запятой, не меньше. И плевать он хотел на точность шага.
Тут не надо ничё предполагать. Операции сложении и умножения над целыми числами, как в данном конкретном примере, не влекут потерю точности. А поскольку getParamEx отдаёт всегда сырые данные во float, а sendTransaction принимает строго с точность шага цены, то варианта тут два: 1) Если работаем только с целыми, перед арифметикой преобразуем все операнды в int либо 2) На вход в sendTransaction подаём отформатированную строку, с учётом количества знаков.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 03.02.2021
25.03.2021 13:26:03
Цитата
Старатель написал: Но QUIK всё одно преобразует аргумент в строку по своему усмотрению. А считает он, что надо 6 знаков после запятой, не меньше. И плевать он хотел на точность шага.
tostring ( ) это стандартная функция Lua и она в свою очередь вызывает стандартную функцию C. В инструкции sprintf():
Цитата
.precision: For a, A, e, E, f and F specifiers: this is the number of digits to be printed after the decimal point (by default, this is 6).
Ну ви таки понели, да? Чтобы вывести число нужным форматом надо использовать форматирование строки.
Знаю, сталкивался с этим. В переменной PRCStr у тебя строка типа "12345.0" А в транзакцию цену надо передавать строку с учетом шага цены "12345"
Короче, точку с нулем из строки похерь и будет счастье
Код
function cut_zero (str)
local num = tonumber(str)
local zero = string.byte ( "0" , 1 )
local point = string.byte ( "." , 1 )
if ( string.find (num,'%.')) then -- Имеется точка в числе
for n = string.len (num), 1 , - 1 do -- Перебор справа налево
if ( string.byte (num,n) = = point) then return string.sub (num, 1 ,n - 1 ) end
if ( string.byte (num,n)~ = zero) then return string.sub (num, 1 ,n) end
end
end
return num
end
Можно и проще, зачем такие сложности. Можно округлить до целого и убрать точку с нулём через math.ceil().
Пользователь
Сообщений: Регистрация: 25.09.2020
31.08.2021 08:02:05
Функция обрезки концевых нулей здесь не раз приводилась. Прекрасно работает и для целых, и для дробных значений.
Пользователь
Сообщений: Регистрация: 20.12.2020
01.09.2021 16:35:55
Цитата
вадим написал: Можно и проще, зачем такие сложности. Можно округлить до целого и убрать точку с нулём через math.ceil().
Если вы присмотритесь, то увидите, что смысл приведенной функции не в округлении до целого, а в обрезании концевых нулей.