Ошибка получения параметра "order_num" поля таблицы "orders" через lua_CApi.

Страницы: 1
RSS
Ошибка получения параметра "order_num" поля таблицы "orders" через lua_CApi.
 
Здравствуйте, данный вопрос является продолжением начатой мною темы:https://forum.quik.ru/forum10/topic3539/
Которая перешла в несколько иное русло.

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

Когда я протестировал два одинаковых скрипта (один на чистом lua, а другой на lua_CApi ) - то обнаружил интересную закономерность (либо я криворукий... поправте в случае нахождения ошибки)
первый скрипт - на qlua - возвращает верное значение lua_CApi. Второй (скрипт близнец) - на С++ с использованием lua_CApi - возвращает значение order_num: -2147483648

Ниже представляю оба тестовых скрипта:
большая просьба как к админам, так и просто к тем кто пишет ботов на С++ так же как и я поправить или же прокомментировать мои ошибки, или же как можно обойти встречную мною ситуацию:

Qlua:
Код
function main()
   for i = getNumberOf("orders")-1,0,-1 do
      T = getItem("orders",i);
      if T.sec_code == "ROSN" and
         bit.test(T.flags,0) then
         message(tostring(T.order_num));
      end;
   end;
end;


lua_CApi + C++:
Код
#include <Windows.h>
#include <thread>

#define LUA_LIB
#define LUA_BUILD_AS_DLL
extern "C" {
#include "Lua\lauxlib.h"
#include "Lua\lua.h"
}




BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
   return TRUE;
}

static struct luaL_reg ls_lib[] = {
   { NULL, NULL }
};

#include <bitset>
extern "C" LUALIB_API int luaopen_test_addition(lua_State *L)
{
   auto _test = [](int bit_num, int bit_test)
   {
      std::bitset<16> bits(bit_num);

      return bits[bit_test] == 1;
   };
   lua_settop(L, 0);
   lua_getglobal(L, "getNumberOf");
   lua_pushfstring(L, "orders");
   lua_call(L, 1, 1);

   int length = (int)lua_tonumber(L, -1);
   lua_settop(L, 0);
   for (size_t i = 0; i < length; i++)
   {
      lua_getglobal(L, "getItem");
      lua_pushfstring(L, "orders");
      lua_pushnumber(L, i);
      lua_call(L,2,1);

      lua_getfield(L, -1, "sec_code");
      std::string sc = lua_tostring(L, -1);
      lua_remove(L, -1);
      lua_getfield(L, -1, "flags");
      int f = lua_tonumber(L, -1);
      lua_remove(L, -1);

      if (sc.compare("ROSN") == 0 && _test(f, 0))
      {
         lua_getfield(L, -1, "order_num");
         int N = lua_tonumber(L, -1);
         lua_remove(L, -1);

         msg_ToQuik(L, std::to_string(N), 1);
      }
      lua_settop(L, 0);
   }

   return 0;
}
 
Причем, если брать фьючерсы вместо акций,то скрипт работает верно.
 
Чуть не забыл часть кода:
Код
void msg_ToQuik(lua_State *L, std::string msg, int num)
{
   lua_settop(L, 0);
   lua_getglobal(L, "message");
   lua_pushfstring(L, msg.c_str());
   lua_pushnumber(L, num);
   lua_call(L, 2, 0);
}
 
У вас переполнение типа int. Номера заявок и сделок - это 64-битные целые числа.
 
Цитата
SG написал:
У вас переполнение типа int. Номера заявок и сделок - это 64-битные целые числа.
SG прав...

ошибка в строчке:
Код
int N = lua_tonumber(L, -1);
добавлю только, что судя по определению:
Код
typedef double lua_Number;
lua_Number lua_tonumber (lua_State *L, int index);
произошло преобразование значения типа double превышающего максимально возможное значение типа int, в результате чего было получено значение INT_MIN из <climits> (limits.h)
Код
#define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
 
Вы правы господа, не думал что order_num превысит int.
 
Цитата
Suntor написал:
Цитата
SG   написал:
У вас переполнение типа int. Номера заявок и сделок - это 64-битные целые числа.
SG прав...

ошибка в строчке:
Код
  int N  =  lua_tonumber(L,  -  1 );  
добавлю только, что судя по определению:
Код
  typedef double lua_Number;
lua_Number lua_tonumber (lua_State  * L, int index);
  
произошло преобразование значения типа double превышающего максимально возможное значение типа int, в результате чего было получено значение INT_MIN из <climits> (limits.h)
Код
   # define INT_MIN     ( -  2147483647   -   1 ) / *  minimum (signed) int value  * /  
Тем не менее, должен заметить, что проблема до конца не решается. Судя по официальной информации, диапазон поддерживаемых целых чисел ограничен 100 000 000 000 000.  https://www.lua.org/pil/2.3.html
QuantPro Platform https://quantpro.ru
 
Цитата
Andrey Perchits написал:
Тем не менее, должен заметить, что проблема до конца не решается. Судя по официальной информации, диапазон поддерживаемых целых чисел ограничен 100 000 000 000 000.   https://www.lua.org/pil/2.3.html
Тогда уже, если развить тему, то число, указанное в документации Lua, не совсем точное. Не знаю почему так.

На самом деле границы диапазона взаимно-однозначного перевода целых чисел между типами double и __int64 составляют:
Код
[±9007199254740992] ([±2^53])
Это чуть более чем в 90 раз больше, чем по документации Lua:
Код
  100,000,000,000,000 (max: lua docs)
9,007,199,254,740,992 (max: double-precision IEEE 754)
То-есть, в строковом представлении число длиной в 15 десятичных цифр точно. (16 цифр неполностью)

Судя по описанию торговой платформы ASTS (Фондовый и Валютный рынки МосБиржи), которое я нашёл,
идентификационный номер заявки в Торговой Системе — поле ORDERNO, имеет тип INTEGER и размер 12.
То-есть задаётся строкой длиной в 12 символов, или соответственно числом длиной 12 цифр.
Что на приблизительно 2-е цифры больше чем максимально-возможное значение 32-хбитного типа int,
но гораздо меньше, чем максимально-возможное точное целочисленное значение типа double:
Код
        4,294,967,296 (2^32) — тип int
9,007,199,254,740,992 (2^53) — тип double
      000,000,000,000        — поле ORDERNO, тип INTEGER, 12 цифр
Так что, получается, что типа lua_Number (от же double) достаточно для точной передачи номера заявки в торговой системе Фондового и Валютного рынков МосБиржи.
Страницы: 1
Читают тему
Наверх