Germany | Finland | Saint Petersburg | Drive

Поиск в таблицах quik

Опубликовано в QLua

Qlua имеет встроенную функцию getOrderByNumber(STRING class_code, NUMBER order_id). Однако кроме ордеров, но номеру часто приходится искать и стоп-зявки и сделки. Функция SearchItem позволяет исполнять быстрый поиск по любым quik-таблицам, но мне удобнее сделать на ее основе отдельные функции поиска, аналогичные getOrderByNumber()

 

Пара примеров.

-- Получение таблицы стоп-ордера по его номеру
-- Возвращает таблицу стоп-зявки или nil
function getStopOrderByNumber(stop_order_number,from,to)
   local index_table = SearchItems("stop_orders",
                                           from or 0,
                                           to or getNumberOf("stop_orders")-1,
                                           function(t)
                                               return t.order_num == stop_order_number
                                           end)
   if index_table then
      return getItem("stop_orders",index_table[1])
   end
end

 

-- Получение таблицы стоп-ордера по номеру порожденной им заявки
-- Возвращает таблицу стоп-заявки или nil
function getStopOrderByOrderNumber(order_number,from,to)
   local index_table = SearchItems("stop_orders",
                                              from or 0,
                                              to or getNumberOf("stop_orders")-1,
                                              function(t)
                                                  return t.linkedorder == order_number
                                              end)
   if index_table then
      return getItem("stop_orders",index_table[1])
   end
end

Комментарии   

# Eugene Bright 27.09.2019 08:47
Здравствуйте!
Функции поиска getItem() и SearchItems() могут работать только с определенным перечнем таблиц, о чем последний раз указано в Руководстве QLUA 8.0 и что проверено мной при написании скрипта. Следует ли из этого, что нужно пользоваться библиотечными функциями LUA для обработки нужных и не оговоренных в Руководстве таблиц? То же - и о созданных нестандартных таблицах QUIK?
Ответить | Ответить с цитатой | Цитировать
# admin 27.09.2019 09:05
Добрый день.

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

Поэтому для поиска, скажем по пользовательско го таблице, созданной из луа, нужно писать собственные функции.
Ответить | Ответить с цитатой | Цитировать
# Eugene Bright 27.09.2019 09:30
Вторая часть вопроса: "Следует ли из этого, что нужно пользоваться библиот ечными функциями LUA (не QLUA) для обработки нужных и не оговоренных в Руководстве таблиц? То же - и о созданных пользователем нестандартных таблицах QUIK?

Прочел Ваш ответ 2 раза. Понял, что пишем сами, ручками.
Ответить | Ответить с цитатой | Цитировать
# admin 27.09.2019 12:03
Верно. Сами.

Медленно, не торопясь, с перерывами на пиво. Главное - не устать )
Ответить | Ответить с цитатой | Цитировать
# Eugene Bright 27.09.2019 12:29
:lol: с таким количеством багов и "хитростей" спиться можно
Ответить | Ответить с цитатой | Цитировать
# Eugene Bright 05.10.2019 23:41
Опять здрасьте! 8)
Вопрос: догадываюсь, что, в принципе, можно организовать поиск в таблице "orders" по полю flags?
Поскольку операции с битовыми переменными для меня пока еще не очень привычны, прошу по-дружески подсказать, как корректно прописать функцию-фильтр

function(t) return t.flags == ... end

в функции поиска SearchItems(). Вот как раз это многоточие и есть суть вопроса.

(хочу выбрать из таблицы заявок те, которые "зависли", т.е. не являются "ИСПОЛНЕННЫМИ" и не "СНЯТЫ")

Спасибо заранее за помощь!
Ответить | Ответить с цитатой | Цитировать
# admin 06.10.2019 12:10
Да, конечно можно.

Смотрим документацию по назначению полей

бит 0 (0x1) Заявка активна, иначе – не активна
бит 1 (0x2) Заявка снята. Если флаг не установлен и значение бита «0» равно «0», то заявка исполнена
бит 2 (0x4) Заявка на продажу, иначе – на покупку. Данный флаг для сделок и сделок для исполнения определяет направление сделки (BUY/SELL)
бит 3 (0x8) Заявка лимитированная, иначе – рыночная
бит 4 (0x10) Разрешить / запретить сделки по разным ценам
бит 5 (0x20) Исполнить заявку немедленно или снять (FILL OR KILL)
бит 6 (0x40) Заявка маркет-мейкера. Для адресных заявок – заявка отправлена контрагенту
бит 7 (0x80) Для адресных заявок – заявка получена от контрагента
бит 8 (0x100) Снять остаток
бит 9 (0x200) Айсберг-заявка

То есть у активной заявки бит с номером 0 должен быть равен 1

смотрим функцию bit.test


Функция проверяет состояние указанного бита в значении. Возвращает true, если бит равен «1», и false, если бит равен «0».

BOOLEAN bit.test(NUMBER х, NUMBER n)

где:

х – значение;
n – номер бита. Нумерация битов начинается с «0».

Пишем функцию сравнения для SearchItems:

compare = function(flg)
return bit.test(flg,0)
end

Вызов:
SearchItems("orders", 0, getNumberOf("or ders")-1, compare, "flags")

Как-то так....
Ответить | Ответить с цитатой | Цитировать
# Eugene Bright 06.10.2019 12:37
Вот спасибо-то! Ваш вариант смотрится элегантней, чем мой.

За вечер-утро я родил вот такой вариант:

function CheckBit(flags, _bit) -- Определение числа в битовое значение
-- Проверяет, что переданные аргументы являются числами
if type(flags) ~= "number" then error("Ошибка!! ! Checkbit: 1-й аргумент не число!") end
if type(_bit) ~= "number" then error("Ошибка!! ! Checkbit: 2-й аргумент не число!") end

if _bit == 0 then _bit = 0x1
elseif _bit == 1 then _bit = 0x2
elseif _bit == 2 then _bit = 0x4
elseif _bit == 3 then _bit = 0x8
elseif _bit == 4 then _bit = 0x10
elseif _bit == 5 then _bit = 0x20
elseif _bit == 6 then _bit = 0x40
elseif _bit == 7 then _bit = 0x80
elseif _bit == 8 then _bit = 0x100
elseif _bit == 9 then _bit = 0x200
elseif _bit == 10 then _bit = 0x400
elseif _bit == 11 then _bit = 0x800
elseif _bit == 12 then _bit = 0x1000
elseif _bit == 13 then _bit = 0x2000
elseif _bit == 14 then _bit = 0x4000
elseif _bit == 15 then _bit = 0x8000
elseif _bit == 16 then _bit = 0x10000
elseif _bit == 17 then _bit = 0x20000
elseif _bit == 18 then _bit = 0x40000
elseif _bit == 19 then _bit = 0x80000
elseif _bit == 20 then _bit = 0x100000
end

if bit.band(flags, _bit ) == _bit then return true
else return false
end
end

function getOrderByFlags ()
local index_table = SearchItems("or ders",
from or 0,
to or getNumberOf("or ders")-1,
function(t)
return not (not CheckBit(orders .flags, 0) and not CheckBit(orders .flags, 1)) or (CheckBit(orders .flags, 1))
end)
if index_table then
return getItem("orders ", index_table)
end
end

Длинно как-то...
Не корысти ради, а истины для прошу оценить. Важно мне для самооценки.

Спасибо!
Ответить | Ответить с цитатой | Цитировать
# admin 06.10.2019 13:55
Цитирую Eugene Bright:

Длинно как-то...
Не корысти ради, а истины для прошу оценить. Важно мне для самооценки.

Спасибо!


Ну здорово, наверное.. Много всего, богато..
Ответить | Ответить с цитатой | Цитировать
# Eugene Bright 06.10.2019 14:01
:lol: Да бог с ним, с богатством. Была бы польза!

я так понимаю, что для универсализации функции
compare = function(flg) нужно её дополнить номером бита и сделать так:

compare = function(flg, n_bit)
return bit.test(flg,n_bit)
end

А вызов:
SearchItems("orders", 0, getNumberOf("or ders")-1, compare, "flags")
организовать в построчном цикле.

Правильно?
Ведь Ваш пример касается только бита "0"?
Ответить | Ответить с цитатой | Цитировать
# admin 06.10.2019 16:09
Нет.

Впрямую так нельзя.
Ответить | Ответить с цитатой | Цитировать
# Eugene Bright 06.10.2019 16:27
Ну, да, согласно Руководства функция-фильтр не может работать впрямую...
Просто мне кажется неудобным под каждое значение бита для каждого parameters в SearchItems писать свою compare(). Завтра потестирую Ваш вариант и мой.
Ответить | Ответить с цитатой | Цитировать
# Eugene Bright 07.10.2019 10:37
Протестировал. "It wo-o-o-orks!!!" (Dr. Brown, "Back to the Future") :lol:

compare = function(flg, n_bit)
return bit.test(flg, n_bit)
end

function getOrderByFlags ()
local res_table = {}
local index_table = SearchItems("or ders",
from or 0,
to or getNumberOf("or ders")-1,
function(t)
return not ((not compare(t.flags , 0) and not compare(t.flags , 1)) or (compare(t.flags , 1)))
end)
if index_table then

for i = 1, #index_table do

res_table = getItem("orders ", index_table)

end

return res_table
end
end

Спасибо за помощь!

(мой вариант тоже работает, но медленнее на 4мс)
Ответить | Ответить с цитатой | Цитировать
# Eugene Bright 06.10.2019 13:03
(поправка к предыдущему моему ответу
bot4sale.ru/.../...)

"Хвостик" к функции поиска (чтобы вывести не таблицу индексов, а готовую таблицу "зависших" ордеров):

function getOrderByFlags ()
local res_table = {}
local index_table = SearchItems("or ders",
from or 0,
to or getNumberOf("or ders")-1,
function(t)
return not (not CheckBit(t.flag s, 0) and not CheckBit(t.flag s, 1)) or (CheckBit(t.flag s, 1))
end)
if index_table then

for i = 1, #index_table do

res_table = getItem("orders ", index_table )

end

return res_table
end
end

(почему-то не отображается индекс "i" в индексируемых значениях выводимой таблицы)
Ответить | Ответить с цитатой | Цитировать

Добавить комментарий


Защитный код
Обновить

Архив QLua