QUIK не отправляет заявку, в которой цена представлена переменной

Страницы: 1
RSS
QUIK не отправляет заявку, в которой цена представлена переменной
 
Всем привет!
Объясните мне, пожалуйста, нижеследующий завих 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.
Перезагружался.
Монитор протирал.)))
Мышку гладил.)))
Мастдай не переустанавливал. Не предлагать.
 
Цитата
Андрей написал:
Цена во втором случае высчитывается нормально

Что такое нормально? Что выводится в окно сообщений, какое значение имеет PRCStr  ?
 
В дополнение:
OnTransReply не выводит своей таблицы, когда цена задана переменной. Прописал цикл сна до получения статуса транзакции, но скрипт выходит из цикла по истечению установленного времени (20с) так и не получив никакого статуса транзакции. Это явно проблема на стороне клиента. Если бы заявки на сервер уходили, ответ бы возвращался. Только вот в чем может быть проблема я не пойму.
 
Цитата
swerg написал:
Цитата
Андрей написал:
Цена во втором случае высчитывается нормально

Что такое нормально? Что выводится в окно сообщений, какое значение имеет PRCStr  ?
В сообщении выводится последняя цена + 50 шагов цены. Все в соответствии с этой строкой:
Код
local PRCStr = tostring(tonumber(getParamEx("SPBFUT", "RIH1", "LAST").param_value) + 50 * tonumber(getParamEx("SPBFUT", "RIH1", "SEC_PRICE_STEP").param_value))
 
Надо точно ответить на простой вопрос: какое именно значение имеет переменная PRCStr  ?
Ну если вам требуется решить проблему, конечно.
 
Цитата
Андрей написал:
Кто-нибудь знает ЧТО ЭТО ЗА БРЕД?
Знаю, сталкивался с этим.
В переменной 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
 
В общем решена проблема.
При запросе последней цены и шага цены 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 непредусмотрено целочисленных значений, но раз у вас на сервере они фигурируют, то и клиентская сторона должна уметь их ретранслировать.
 
Цитата
BlaZed написал:
Цитата
Андрей написал:
Кто-нибудь знает ЧТО ЭТО ЗА БРЕД?
Знаю, сталкивался с этим.
В переменной 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 
  
Не успел прочитать)))
 
Цитата
Андрей написал:
Принцип программирования - что запросил то и получил здесь нарушен.

Ничего здесь как раз не нарушено. Запрошена цена - её значение возвращается как double. Все логично.

Цитата
Андрей написал:
В таблицах по фьючу РТС явно целочисленные значения приводятся, да и биржа тоже целые транслирует

Это не так. Вы путаете транслируемые и отображаемые значения. Просто QUIK в таблицах при отображении учитывает еще параметр "точность цены", отображая лишь то значение цифр после запятой, которое соответствует указанному параметру.

Цитата
Андрей написал:
Я понимаю, что в недоязыке LUA непредусмотрено целочисленных значений

И это не так. Добавление .0 после чисел с типом double появилось в Lua5.3, где есть отдельный целочисленный тип.
Но он здесь не применим, т.к. бывают инструменты с дробной ценой. Так что цена универсально возвращается как double, а tostring() приписывает при конвертации .0 в таким аргументам (при целом значении).

Цитата
Андрей написал:
Вопрос к разработчикам

Вопрос к разработчикам ровно один и простой: неужели до сих пор нельзя сделать так, чтобы параметр Transaction["PRICE"] можно было задавать числом, а не строкой?!
 
Цитата
swerg написал:

Вопрос к разработчикам ровно один и простой: неужели до сих пор нельзя сделать так, чтобы параметр Transaction["PRICE"] можно было задавать числом, а не строкой?!
Вроде в инструкции указано что все параметры транзакции - строковые.
 
А собственно: инструкция "Интерпретатор языка Lua", раздел 3.11 "Функции для работы с заявками", пункт 1 функция "sendTransaction", примечание жирным текстом:

Цитата
ВАЖНО!
Для корректной обработки данных числовые значения (цена, количество, идентификатор транзакции и т.д.) должны передаваться в виде строковых значений.

Тут собственно ваша ошибка/лень. Протокол - строковый, конвертируйте ваши значения в строки.
 
На документацию тут ссылаться не совсем точно, ибо вообще не очевидно, что строка числового значения "500" подходит, а "500.0" - не подходит. Хотя это одно и тоже числовое значение, представленное строками.
 
swerg, тут видимо суть в том, чтобы работало по принципу "пропущена запятая - отказ", чтобы надёжно - с реальными деньгами таки дело идёт, так что мало ли. Благо дело при создании формы программным путём, сделать её идальной это невелика проблема.

Код
function TradePriceFormat ( value, accuracy ) 
  return string.format ( string.format ( "%%.%df", accuracy ), value )
end
Тут конечно с неявным округлением последнего знака, но кашу после него всё равно надо как-то округлять в любом случае.
 
Цитата
swerg написал:
Цитата
Андрей написал:
Принцип программирования - что запросил то и получил здесь нарушен.

Ничего здесь как раз не нарушено. Запрошена цена - её значение возвращается как double. Все логично.

Цитата
Андрей написал:
В таблицах по фьючу РТС явно целочисленные значения приводятся, да и биржа тоже целые транслирует

Это не так. Вы путаете транслируемые и отображаемые значения. Просто QUIK в таблицах при отображении учитывает еще параметр "точность цены", отображая лишь то значение цифр после запятой, которое соответствует указанному параметру.

Цитата
Андрей написал:
Я понимаю, что в недоязыке LUA непредусмотрено целочисленных значений

И это не так. Добавление .0 после чисел с типом double появилось в Lua5.3, где есть отдельный целочисленный тип.
Но он здесь не применим, т.к. бывают инструменты с дробной ценой. Так что цена универсально возвращается как double, а tostring() приписывает при конвертации .0 в таким аргументам (при целом значении).

Цитата
Андрей написал:
Вопрос к разработчикам

Вопрос к разработчикам ровно один и простой: неужели до сих пор нельзя сделать так, чтобы параметр Transaction["PRICE"] можно было задавать числом, а не строкой?!


Спасибо за разъяснения
 
Тут собственно говоря проблема была даже не в том, что запятая пропущена, а в том, что клиент не способен корректно пересылать данные на сервер.
обратите внимание на строку ниже: она напрямую запрашивает данные с сервера
Код
local PRCStr = tostring(tonumber(getParamEx("SPBFUT", "RIH1", "LAST").param_value) + 50 * tonumber(getParamEx("SPBFUT", "RIH1", "SEC_PRICE_STEP").param_value))

А потом просто ретранслирует их обратно через переменную

Код
["PRICE"]      = PRCStr

В этом и состоял вопрос: почему клиент не умеет корректно работать с данными сервера. А это уже вопрос к разработчикам. Хотя swerg тоже прав: почему они до сих пор все переводится в строковый вариант))))))
Времена ДОС прям-таки)))))
 
В любом случае в программе есть скрытая функциональность не прописанная в документации (преобразование типов). Проверки типов между клиентом и сервером нет - это точно. И нигде это не прописано.
 
Андрей, Ну, во-первых, приведённая строка НЕ "запрашивает данные с сервера" - она берёт их из Квика. Во-вторых, во "времена ДОС" софт был на порядки более эффективным и менее глючным. В-третьих, за эту долбаную "динамическую типизацию" я бы разработчикам яйца пообрывал. В-четвёртых, заворачивание в tostring помогает в 9 случаях из 10.
 
Цитата
Владимир написал:
Андрей, Ну, во-первых, приведённая строка НЕ "запрашивает данные с сервера" - она берёт их из Квика. Во-вторых, во "времена ДОС" софт был на порядки более эффективным и менее глючным. В-третьих, за эту долбаную "динамическую типизацию" я бы разработчикам яйца пообрывал. В-четвёртых, заворачивание в tostring помогает в 9 случаях из 10.
Я понимаю, что команда обращается к стеку клиента, но ведь потом она пересылает эти данные на сервер. Другими словами в цепи сервер-клиент-сервер присутствует несогласованность в типе данных. То, что делает клиент с типами данных, не воспринимается сервером. А это уже ПРОБЛЕМА. И проблема говорит о том, что сопровождение софта отсутствует полностью.

И вообще, я не понимаю, зачем надо было выбирать глючный LUA, на котором можно только скрипты для игрушек писать, в ущерб тому же несчастному питону. У которого в тысячу раз больше возможностей и который тоже на С (если так нравится разрабам)... Это при том, что LUA изначально не предназначен для точных вычислений и пр. математики (за исключением арифметики).
 
Питон тоже самое, только тяжелее, медленнее и со своими проблемами.

Что касается клиент серверного взаимодействия, то вне зависимости от языка, прежде чем проводить операции с данными, полученными с сервера, из принято проверять.
Они могут быть не получены, они могут быть некорректными. В вашем примере Вы сразу пытаетесь привести значение к числу, не убедившись, что они есть.
Если вернется что-то не то, tonumber вернет nil. А далее Вы с этим будете арифметические действия выполнять.
 
Цитата
Андрей написал:
И вообще, я не понимаю, зачем надо было выбирать глючный LUA

В чем его глючность? Вот как языка?

Цитата
Андрей написал:
в ущерб тому же несчастному питону

Питона тогда почти не было, когда в QUIK прикручивали Lua. Во всяком случае - он еще не взлетел так массово.

Цитата
Андрей написал:
Это при том, что LUA изначально не предназначен для точных вычислений и пр. математики (за исключением арифметики).

Могли бы пояснить эту фразу? в чем заключается "неприспособленность" для указанного?
 
Цитата
Nikolay написал:
Питон тоже самое, только тяжелее, медленнее и со своими проблемами.

Что касается клиент серверного взаимодействия, то вне зависимости от языка, прежде чем проводить операции с данными, полученными с сервера, из принято проверять.
Они могут быть не получены, они могут быть некорректными. В вашем примере Вы сразу пытаетесь привести значение к числу, не убедившись, что они есть.
Если вернется что-то не то, tonumber вернет nil. А далее Вы с этим будете арифметические действия выполнять.
В данном случае я упростил код.
Не буду же я две страницы сюда кидать, заблаговременно зная в чем примерно причина)))
Но элементарная проверка типов должна быть на стороне сервера. Программа не должна молчать в случае ввода не типизированных данных.
 
И это при условии того, что нормального дебагера на LUA нет. И пользуются в квике только функцией message/
 
А причем здесь сервер? Сервер дает что попросили.
getParamEx из кеша теримнала данные вернет, если они есть. А если их заказали с сервера, то они будут обновляться в кеш.

А что программа должна делать, если с сервера не получен ответ. Она просто возвращает в поле result возвращаемой таблицы = "0", что условно и соответствует ошибке получения данных. Это он как раз и говорит - ничего нет.
А message - это средство оповещения.

Дебаг - это либо вывод в лог отладочной информации с level = debug. Либо использовать PrintDbgStr. При этом код должен содержать ассерты на входящие данные, чтобы сразу и понять где ошибка.
 
Андрей, А какая разница, куда там Квик что посылает? Представьте, что вся торговля происходит прямо в Квике! Код упростится в разы, да и надёжность повысится.

У меня прямо противоположное мнение: сопровождение софта неприлично высокое! Только за полгода только на моей памяти три версии сменилось! Нафиг нужно такое сопровождение?

Согласен: Lua - редкостное дерьмо, но раз уж так сложилось, то искать что-либо ещё нет ни малейшего желания! Свой "скрипт для игрушек" я написал, и теперь желаю лишь одного: оставьте всё как есть, хватит улучшать! Версию стабильную даждь нам днесь и избави нас от дебаггера! :smile:  
 
Цитата
Андрей написал:
Тут собственно говоря проблема была даже не в том, что запятая пропущена, а в том, что клиент не способен корректно пересылать данные на сервер.
обратите внимание на строку ниже: она напрямую запрашивает данные с сервера
Код
   local  PRCStr  =  tostring(tonumber( getParamEx ( "SPBFUT" ,  "RIH1" ,  "LAST" ).param_value)  +   50   *  tonumber( getParamEx ( "SPBFUT" ,  "RIH1" ,  "SEC_PRICE_STEP" ).param_value))
  
 А потом просто ретранслирует их обратно через переменную  
Код
  [ "PRICE" ]       =  PRCStr  
  В этом и состоял вопрос: почему клиент не умеет корректно работать с данными сервера. А это уже вопрос к разработчикам. Хотя  swerg  тоже прав: почему они до сих пор все переводится в строковый вариант))))))
Времена ДОС прям-таки)))))
Смею предположить что PRCStr у вас содержит число вида "123.50000000002" в силу особенностей IEEE 64-битных чисел с плавающей запятой. Опытным путём установлено, что даже просто наличие большего количества нулей чем точность цены тоже отвергает транзакцию. Я выше уже написал функцию которая правильно составляет строковое выражение цены.
 
Цитата
swerg написал:
неужели до сих пор нельзя сделать так, чтобы параметр Transaction["PRICE"] можно было задавать числом, а не строкой?
Давно можно было, если кто не знал. Но QUIK всё одно преобразует аргумент в строку по своему усмотрению. А считает он, что надо 6 знаков после запятой, не меньше. И плевать он хотел на точность шага.

Цитата
Артем написал:
Смею предположить
Тут не надо ничё предполагать. Операции сложении и умножения над целыми числами, как в данном конкретном примере, не влекут потерю точности.
А поскольку getParamEx отдаёт всегда сырые данные во float, а sendTransaction принимает строго с точность шага цены, то варианта тут два:
1) Если работаем только с целыми, перед арифметикой преобразуем все операнды в int
либо
2) На вход в sendTransaction подаём отформатированную строку, с учётом количества знаков.
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Старатель написал:
Но 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).
Ну ви таки понели, да? Чтобы вывести число нужным форматом надо использовать форматирование строки.

Цитата
Старатель написал:

Тут не надо ничё предполагать. Операции сложении и умножения над целыми числами, как в данном конкретном примере, не влекут потерю точности.
Шаг цены бывает например 0.1 и тут будут проблемы.
 
Цитата
Старатель написал:
1) Если работаем только с целыми, перед арифметикой преобразуем все операнды в int
Забыл добавить: это относится именно к целочисленным операциям, таким как сложение, вычитание, умножение. И после вычислений - просто tostring.

Цитата
Артем написал:
tostring ( ) это стандартная функция Lua
tostring как раз лишних нулей не дописывает, можете смело пользоваться. Если у вас int, то и tostring вернёт строку без точки.

Цитата
Артем написал:
Цитата
Старатель написал:
Тут не надо ничё предполагать. Операции сложении и умножения над целыми числами, как в данном конкретном примере, не влекут потерю точности.
Шаг цены бывает например 0.1 и тут будут проблемы.
Речь про целые числа.
Для дробных шагов - округление с точностью шага цены и
Цитата
Старатель написал:
2) На вход в sendTransaction подаём отформатированную строку, с учётом количества знаков.
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
BlaZed написал:
Цитата
Андрей написал:
Кто-нибудь знает ЧТО ЭТО ЗА БРЕД?
Знаю, сталкивался с этим.
В переменной 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().
 
Функция обрезки концевых нулей здесь не раз приводилась. Прекрасно работает и для целых, и для дробных значений.
 
Цитата
вадим написал:
Можно и проще, зачем такие сложности. Можно округлить до целого и убрать точку с нулём через math.ceil().
Если вы присмотритесь, то увидите, что смысл приведенной функции не в округлении до целого, а в обрезании концевых нулей.
Страницы: 1
Читают тему
Наверх