nikolz, нафига их двигать, если можно сразу и пачкой:
Цитата
Ziveleos написал: У каждого флага свой вес. Чтобы узнать состояние флагов, нужно в качестве второго операнда побитового И взять число, равное сумме весов интересующих флагов. Результат = сумме весов установленных флагов.Пример:Если order.flags & 5 == 4, заявка на продажу, не активна. ==1 - заявка на покупку, активна.
Владимир, это на случай проблем с интернетом, электричеством, или на сервере брокера, как это было со сбером, чтобы заявка не осталась с неприкрытой задницей. Ну и для ручной торговли.
VPM написал: order.flags - где нулевой где не нулевой не разберешь.
Руководство пользователя QLua > Описание битовых флагов. У каждого флага свой вес. Чтобы узнать состояние флагов, нужно в качестве второго операнда побитового И взять число, равное сумме весов интересующих флагов. Результат = сумме весов установленных флагов. Пример: Если order.flags & 5 == 4, заявка на продажу, не активна. ==1 - заявка на покупку, активна.
Старая шутка: "Нашел в телефоне кнопку Вкл.бл, значит, где-то должна быть Выкл.нах."
VPM написал: Можно утверждать что такая запись надежна?
В приведенном Вами примере контролируется нулевой бит, а описание почему-то взято от первого. А это все-таки разные вещи: ордер активен и ордер снят. По моему, определять лучше сразу оба бита. Если bit.band(order.flags,3) или order.flags & 3 равно 3, то заявка снята, равно 2 - исполнена, 1 - активна.
VPM написал: if (order.flags % 2) == 0 then -- Заявка снята. Если флаг не установлен и значение бита «0» равно «0», то заявка исполнена
чет/нечет - это проверка нулевого бита. Из руководства:
Цитата
бит 0 (0x1) Заявка активна, иначе – не активна бит 1 (0x2) Заявка снята. Если флаг не установлен и значение бита «0» равно «0», то заявка исполнена
Есть еще вариант bit.test(order.flags,0), но чет/нечет самый быстрый.
Код
function main()
order = getItem("orders", 1)
start = os.clock()
for i = 1, 1e6 do
x = order.flags % 2
--x = bit.band(order.flags,1)
--x = bit.test(order.flags,0)
end
message(tostring(os.clock() - start))
end
if lastLbl then
repeat
sleep(10)
t_Lbl = GetLabelParams(iStr, lastLbl) -- Костыль. Ждем пока появится последняя метка.
until t_Lbl
end
lastLbl = 0
<...>
lbl_ID = AddLabel(iStr, arr)
lastLbl = lastLbl + 1
end
Но лучше, если бы не приходилось изобретать "костыли". Разработчики! Поправьте на досуге.
function OnInit()
is_run = true
path = (getScriptPath() .. "\\")
Arrow_B = (path .. "Arrow_B.bmp") -- Стрелки
Arrow_S = (path .. "Arrow_S.bmp")
iStr = "Rv-1" -- Идентификатор графика.
end
function OnStop()
DelAllLabels(iStr)
is_run = false
return 3000
end
function main()
while is_run do
local cdls = -1
repeat
local cdls0 = cdls
sleep(10)
cdls = getNumCandles(iStr)
until cdls > 0 and cdls == cdls0 -- Ждем, пока загрузятся все свечи.
local tc, nc, leg = getCandlesByIndex (iStr, 0, math.floor(cdls/2), 3)
if leg ~= old_leg and leg ~= "GZU3 [Price]" and leg ~= "" then -- Если на графике сменился инструмент. Один оставляем пустым.
old_leg = leg
LinePrnt("\n \n", leg)
--sleep(500) -- Костыль. Чем больше меток, которые нужно убить, тем больше должна быть задержка.
---[[
if lbl_ID then
for i=1, 700 do
t_Lbl = GetLabelParams(iStr, i) -- После смены инструмента идентификаторы меток тоже изменяются.
if t_Lbl then
last = i
end
end
end
--]]
LinePrnt(cdls, lbl_ID, last)
local image;
local aligt;
DelAllLabels(iStr) -- Если отключить, то quik просто зависает, без "General Protection Fault".
local start = os.clock()
for i=1, 100 do -- Кол-во меток.
local date = string.format("2023%02d%02d", math.random(3, 6), math.random(1, 30)) -- Диапазон месяцев и дней.
local time = string.format("%02d%02d00", math.random(10, 22), math.random(1, 59)) -- Диапазон часов и минут.
local price = tc[1].close + math.random(-100, 100)*tc[1].close/1000 -- Диапазон цен.
--LinePrnt(date, time, price)
local hint = tostring(date.."\n"..time.."\n"..price)
local txt = tostring("Lbl "..i)
if math.floor(i/2) == i/2 then
image = Arrow_B
aligt = "BOTTOM"
else
image = Arrow_S
aligt = "TOP"
end
arr = {
TEXT = "", -- txt
FONT_FACE_NAME = "Arial",
FONT_HEIGHT = 9,
R = 250,
G = 250,
B = 250,
IMAGE_PATH = image, -- Без картинок всё ОК, quik не падает.
TRANSPARENCY = 0,
TRANSPARENT_BACKGROUND = 1,
ALIGNMENT = aligt,
DATE = tonumber(date), -- Работает даже если STRING, зачем DOUBLE - не понятно...
TIME = tonumber(time),
YVALUE = price,
HINT = hint
}
lbl_ID = AddLabel(iStr, arr)
end
LinePrnt(os.clock() - start, lbl_ID)
end
sleep(30)
end
end
-------------------------------------------------------
function LinePrnt(...)
local lin = ""
for i, v in ipairs {...} do
lin = (lin ..(tostring(v)).." ")
end
PrintDbgStr(lin)
end
По-видимому, если во время восстановления меток после смены инструмента (график подключен к каналу), вызвать DelAllLabels, QUIK не выдерживает такой "шизофрении", и падает с криком "Internal exception happened".
Помогает только задержка, позволяющая QUIK восстановить все метки. Как поймать момент окончания прорисовки, мне придумать так и не удалось, может быть разработчики что-нибудь подскажут? Версия терминала - 10, но и на 7-ой всё то же самое.
Alexey Ivannikov написал: Хамство и оскорбления - это по Вашему правильно? Мы Вас верно поняли?
Неверно. И что значит "Мы"? Во множественном числе себя величали только самодержцы. У высказывания есть форма и содержание. Имелось в виду именно содержание.
Цитата
Alexey Ivannikov написал: Да, пользуются. И вполне довольны. Если Вы тоже считаете что пожелания, в которых заинтересованы 1-2-3 пользователя, должны выполняться " по щелчку" - то Вы ничего не понимаете в организации работы IT-Компании.
Ну, если "вполне довольны", то улучшений ждать не приходится. Зачем менять то, что и так работает замечательно?
Чего для мне что-то понимать в организации работы IT-Компании? Достаточно сравнить ваш продукт с тем же приснопамятным TradingView, и с вами всё становится ясно. Взять хотя бы возможность назначать оповещение на пересечение ценой любой линии, например, линии тренда.
Александр написал: Прошел еще месяц, с предыдущего сообщения! Вы че там вообще делаете за наши бабки? В чем сложность убрать бесконечность Фибоначчи??? И так из-за вашего тупого стакана приходится в двух терминалах работать. Вы что на столько тупые что не можете сделать стакан как в МТ фибы как у всех не бесконечные и свободное перемещение графика в окне?*???? Это че прям сложность такая за столько лет или мозгов не хватает тупо посмотреть как у других? Вы сами через свое убожество торгуете или только пишите это уродство?
А вопрос-то правильный. Разработчики OUIK сами пользуются своим продуктом, или "чисто теоретически"?
Andrey Golik, снова сделаете как в 7-ке, загружать картинки один раз, при старте скрипта, и хранить их в randseed.bin в более "удобоваримом" виде? Может быть лучше сохранять картинки в каком-нибудь буфере в оперативке, чтобы AddLabel брала их оттуда? Ну, или считывать картинки как userdata и использовать вместо адреса картинки.
swerg, мои слова, процитированные Вами, были ответом Владимиру. Для себя я все выяснил, о чем и высказывался уже в этой ветке. Видимо, Вы поступили как в том анекдоте: "чукча - не читатель, чукча - писатель!"
Алексей написал: Имеется ввиду, что quik уже за Вас вызвал getScriptPath() и результат Вам подсовывает в качестве параметра при вызове OnInit(script_path).А уж будете Вы использовать этот "подарок" внутри OnInit или нет, дело Ваше
Nikolay написал: Body скрипта выполняется в потоке терминала. Так что служебные переменные вполне себе инициализируются там.
А я что сказал?
Цитата
if до зарезу необходимо сделать что-то до начала работы коллбэков, and в этом "что-то" используются функции объявляемые позже, then без OnInit не обойтись. end В остальном он на фиг не нужен.
Цитата
Nikolay написал: Речь же про колбеки звучит странно, т.к. я слабо себе представляю использование колбеков в алгоритме, если они не обработаны все.
Если в самой функции коллбэка используется нечто не объявленное ранее, и он сработает, возникнет ошибка. Поэтому это "нечто" нужно объявить до запуска main.
Владимир, переменные окружения показывают разницу между body и OnInit. Получается, если до зарезу необходимо сделать что-то до начала работы коллбэков, и в этом "что-то" используются функции объявляемые позже, то без OnInit не обойтись. В остальном он на фиг не нужен.
Видимо, единственное преимущество OnInit в том, что в отличии от body, из неё можно вызывать функции не объявленные ранее. Ну, и " В качестве параметра принимает значение полного пути к запускаемому скрипту."
Скрытый текст
Код
file = io.open(getScriptPath() .. "\\Environment.txt", "w+")
local len = 0
for k, v in pairs(_ENV) do
file:write(string.format("%s\t %s \n",k,(tostring (v))))
len = len + 1
end
file:write("\n Окружение BODY: ", len, "\n\n" )
function OnInit()
local len = 0
for k, v in pairs(_ENV) do
file:write(string.format("%s\t %s \n",k,(tostring (v))))
len = len + 1
end
file:write("\n Окружение OnInit: ", len, "\n\n" )
end
function main()
file:seek("set")
local log = file:read("a")
local b_log = string.match(log, "(.-)\n\n")
local i_log = string.match(log, "Окруж.-\n\n(.-)\n\n")
file:write(" Нет в BODY: ")
for s in string.gmatch(i_log, "(.-)\t.-\n") do
if not string.match(b_log, s) then
file:write("\n", s)
end
end
file:write("\n\n Разница: ")
for s in string.gmatch(i_log, "(.-)\n") do
if not string.match(b_log, s) then
file:write("\n", s)
end
end
file:flush()
file:close()
end
--file:write("Чудо-юдо рыба-кит \n")
function tableLog(t)
for k, v in pairs(t) do
file:write(string.format("%s %s \n",k,(tostring (v))))
end
end
Владимир, Второй поток все-таки нужен, иначе QUIK замрёт, пока работает скрипт. А вот, что касается:
Цитата
nikolz написал: В том, что это этот колбек вызывается раньше всех других колбеков и раньше функции main.Без него у Вас колбеки будут вызываться раньше, чем будет вызвана функция main.
коллбэки начинают работать только вместе с main.
Код
qtes = {}
function OnQuote(class, sec )
ql2 = getQuoteLevel2(class, sec)
table.insert(qtes, ql2)
end
sleep(10000)
function main()
--sleep(10000)
message(tostring(#qtes))
end
Необходимые переменные и библиотеки перед запуском основного потока main() возможно инициализировать и в BODY. Если скрипт не HFT, или вообще без коллбэков, получается OnInit не сильно нужен.
Время сервера передается без начального нуля, поэтому предложенный код до 10 часов утра не работает. Вот немного доработанный вариант:
Код
-- Время сервера в числовой формат.
local sT = getInfoParam("SERVERTIME") -- Время сервера в формате Ч:ММ:СС или ЧЧ:ММ:СС
function DToN (s,i,j)
return tonumber(string.sub(s, i, j)) -- Перевод цифр в числа.
end
srvTime = DToN(sT,-2,-1) + DToN(sT,-5,-4)*60 + DToN(sT,-8,-7)*3600 -- Количество секунд с начала суток.
Constantin написал: Давно уже можно было бы указать в документации QLua GetParamEx сноску, где смотреть названия параметров! А то люди не находят и здесь спрашивают постоянно.
Добрый день,
Документация будет дополнена в одной из очередных версий ПО. Приносим извинения за причиненные неудобства.