Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Владимир, argumentum ad verecundiam. Вы эксперт в C, Prolog, Fortran, ассебмлер Z80? В Lua вы не эксперт. Тоже, пожалуйста, прочитайте инструкцию - в этом языке она очень короткая. Почерпнёте много нового.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Тут как говорится, нечего на зеркало пенять если рожа крива. Не знаете языка, а глаголите как будто сопоставимо экспертному мнению, а не пердежу в лужу. Будете иметь весомое мнение, когда хотя-бы выучите формальное определение языка, про реальную имплементацию в коде уж не будем заикаться.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
TGB,про бинарные строки вам уже рассказали. Собственно эта информация прямым текстом написана в третьем параграфе первой главы, т.е. в самом начале инструкции - которую вы очевидно не читали. Так что пожалуйста прочитайте, целиком и полностью. Перед тем как делать библиотеки для других людей, сначала убедитесь что ваши познания и умения находятся на уровне повыше плинтуса.
Программа заранее знает, какой именно параметр был изменен сервером, но не отправляет эти данные в колбек, из-за чего возникают недоразумения. Пожалуйста сделайте так чтобы в OnParam третьим аргументом передавалась Lua-таблица аналогичная выводу GetParamEx() т.е. формата { param_name, param_type, param_image, param_value }
Код
function OnParam ( class, sec, param )
--param = GetParamEx ( class, sec, "bid" )
--вместо GetParamEx ( ) сразу берём param_data
if class == "TQBR" and sec == "SBER" and param.name == "bid" and param.value >= 300 then
message ( "TQBR SBER покупается за 300" )
end
end
Просьба также добавить аналогичные входные данные в другие колбеки, в которых таковые отсутствуют. В целом должно действовать правило, что колбек должен содержать все данные, которые к нему относятся - без вызова посторонних функций - иначе будет каша.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Немного доработанный код. Вроде справляется со всем, включая NaN. Все виды кодировок текста совместимые с ASCII должны работать без проблем. После загрузки всех модулей надо вызвать addalias() чтобы подцепить все функции, что не добавилось - добавить вручную. Для дампа есть вариант сразу в файл на случай если у вас данные на несколько гигабайт. Велосипед под лицензией MIT, берите-катайтесь.
TGB, выгружает _G в строку за 10 мсек, в файл за 2 мсек.
Код
local aliases = { }
local function escape ( s )
s = tostring ( s ):gsub ( "\n", "\\n" )
return s
end
local function dumpstr ( t, alias, seen )
alias, seen = alias or aliases, seen or { }
if seen[ t ] then return "" else seen[ t ] = true end
local s, mt = string.format ( "newtable %s\n", alias[ t ] or escape ( t ) ), getmetatable ( t )
if mt then s = string.format ( "%smetatable %s\n", s, alias[ mt ] or escape ( mt ) ) end
for k, v in pairs ( t ) do
s = string.format ( "%sk %s %s\nv %s %s\n", s, type ( k ), alias[ k ] or escape ( k ), type ( v ), alias[ v ] or escape ( v ) )
end
if mt then s = string.format ( "%s%s", s, dumpstr ( mt, alias, seen ) ) end
for k, v in pairs ( t ) do
if type ( k ) == 'table' then s = string.format ( "%s%s", s, dumpstr ( k, alias, seen ) ) end
if type ( v ) == 'table' then s = string.format ( "%s%s", s, dumpstr ( v, alias, seen ) ) end
end
return s
end
local function dumpfile ( file, t, alias, seen )
alias, seen = alias or aliases, seen or { }
if seen[ t ] then return else seen[ t ] = true end
local mt = getmetatable ( t )
file:write ( string.format ( "newtable %s\n", alias[ t ] or escape ( t ) ) )
if mt then file:write ( string.format ( "metatable %s\n", alias[ mt ] or escape ( mt ) ) ) end
for k, v in pairs ( t ) do
file:write ( string.format ( "k %s %s\nv %s %s\n", type ( k ), alias[ k ] or escape ( k ), type ( v ), alias[ v ] or escape ( v ) ) )
end
if mt then dumpfile ( file, mt, alias, seen ) end
for k, v in pairs ( t ) do
if type ( k ) == 'table' then dumpfile ( file, k, alias, seen ) end
if type ( v ) == 'table' then dumpfile ( file, v, alias, seen) end
end
end
local function unescape ( s )
s = s:gsub ( "\\n", "\n" )
return s
end
local function loadstr ( s, alias )
alias = alias or aliases
do local t = { } for k, v in pairs ( alias ) do t[ v ] = k end alias = t end
local tlist, tcurr, kcurr, troot = { }, nil, nil, nil
for l in s:gmatch ( "([^\n]+)\n" ) do
local nt = l:match ( "newtable (.+)" )
local mt = l:match ( "metatable (.+)" )
local kt, k = l:match ( "k ([^ ]+) (.+)" )
local vt, v = l:match ( "v ([^ ]+) (.+)" )
if nt then tlist[ nt ] = tlist[ nt ] or alias[ nt ] or { }; tcurr = tlist[ nt ]; troot = troot or tcurr
elseif mt then tlist[ mt ] = tlist[ mt ] or alias[ nt ] or { }; setmetatable ( tcurr, tlist[ mt ] )
elseif k then
if kt == 'table' then tlist[ k ] = tlist[ k ] or alias[ k ] or { }; kcurr = tlist[ k ]
elseif kt == 'number' then kcurr = alias[ k ] or tonumber ( k ) or 0/0
elseif kt == 'string' then kcurr = alias[ k ] or unescape ( k )
else kcurr = alias[ k ]
end
elseif v and tcurr and kcurr ~= nil then
if vt == 'table' then tlist[ v ] = tlist[ v ] or alias[ v ] or { }; tcurr[ kcurr ] = tlist[ v ]
elseif vt == 'number' then tcurr[ kcurr ] = alias[ v ] or tonumber ( v ) or 0/0
elseif vt == 'string' then tcurr[ kcurr ] = alias[ v ] or unescape ( v )
else tcurr[ kcurr ] = alias[ v ]
end
end
end
return troot
end
local function addalias ( item, path, deep, seen )
if item == nil and path == nil and deep == nil and seen == nil then item, path, deep = _G, "_G", true end
seen = seen or { }
if item == nil or path == nil or seen[ item ] ~= nil then
return
elseif type ( item ) == 'table' and deep then
seen[ item ] = true
for k, v in pairs ( item ) do
if type ( v ) == 'table' then
addalias ( v, string.format ( "%s.%s", path, escape( k ) ), deep, seen )
elseif type ( v ) ~= 'string' and type ( v ) ~= 'number' then
aliases[ v ] = string.format ( "%s.%s", path, escape ( k ) )
end
end
else
aliases[ item ] = path
end
end
addalias ( math.huge, "math.huge" )
addalias ( -math.huge, "-math.huge" )
return { dumpstr = dumpstr, dumpfile = dumpfile, loadstr = loadstr, addalias = addalias }
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
s_mike@rambler.ru написал: во втором случае результат явно неверен. "a" и "a\0b" - совершенно разные строки.
Так как символ \0 в Lua это признак завершения строки, то для Lua "a" и "a\0b" - эквивалентные строки.
Lua использует бинарные строки с указанной длиной. Указанные строки - разные, и Lua будет их считать разными; при выгрузке в файл значения разные (и совпадающие со входящими). То что они отобразились одинаково это вероятно из-за того, что в используемом терминале используется С стандарт строк с нуль-терминатором.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
local function escape ( s )
s = tostring ( s ):gsub ( "\n", "\\n" )
return s
end
local function dumpstr ( t, alias, seen )
seen = seen or { }
if seen[ t ] then return "" else seen[ t ] = true end
local s, mt = string.format ( "newtable %s\n", alias[ t ] or escape ( t ) ), getmetatable ( t )
if mt then s = string.format ( "%smetatable %s\n", s, alias[ mt ] or escape ( mt ) ) end
for k, v in pairs ( t ) do
s = string.format ( "%sk %s %s\nv %s %s\n", s, type ( k ), alias[ k ] or escape ( k ), type ( v ), alias[ v ] or escape ( v ) )
end
if mt then s = string.format ( "%s%s", s, dumpstr ( mt, alias, seen ) ) end
for k, v in pairs ( t ) do
if type ( k ) == 'table' then s = string.format ( "%s%s", s, dumpstr ( k, alias, seen ) ) end
if type ( v ) == 'table' then s = string.format ( "%s%s", s, dumpstr ( v, alias, seen ) ) end
end
return s
end
local function dumpfile ( file, t, alias, seen )
seen = seen or { }
if seen[ t ] then return else seen[ t ] = true end
file:write ( string.format ( "newtable %s\n", alias[ t ] or escape ( t ) ) )
local mt = getmetatable ( t )
if mt then file:write ( string.format ( "metatable %s\n", alias[ mt ] or escape ( mt ) ) ) end
for k, v in pairs ( t ) do
file:write ( string.format ( "k %s %s\nv %s %s\n", type ( k ), alias[ k ] or escape ( k ), type ( v ), alias[ v ] or escape ( v ) ) )
end
if mt then dumpfile ( file, mt, alias, seen ) end
for k, v in pairs ( t ) do
if type ( k ) == 'table' then dumpfile ( file, k, alias, seen ) end
if type ( v ) == 'table' then dumpfile ( file, v, alias, seen) end
end
end
Код
local function unescape ( s )
s = s:gsub ( "\\n", "\n" )
return s
end
local function loadstr ( s, alias )
do local t = { } for k, v in pairs ( alias ) do t[ v ] = k end alias = t end
local tlist, tcurr, kcurr, troot = { }, nil, nil, nil
for l in s:gmatch ( "([^\n]+)\n" ) do
local nt = l:match ( "newtable (.+)" )
local mt = l:match ( "metatable (.+)" )
local kt, k = l:match ( "k ([^ ]+) (.+)" )
local vt, v = l:match ( "v ([^ ]+) (.+)" )
if nt then tlist[ nt ] = tlist[ nt ] or alias[ nt ] or { }; tcurr = tlist[ nt ]; troot = troot or tcurr
elseif mt then tlist[ mt ] = tlist[ mt ] or alias[ nt ] or { }; setmetatable ( tcurr, tlist[ mt ] )
elseif k then
if kt == 'table' then tlist[ k ] = tlist[ k ] or alias[ k ] or { }; kcurr = tlist[ k ]
elseif kt == 'number' then kcurr = alias[ k ] or tonumber ( k )
elseif kt == 'string' then kcurr = alias[ k ] or unescape ( k )
else kcurr = alias[ k ]
end
elseif v and tcurr and kcurr ~= nil then
if vt == 'table' then tlist[ v ] = tlist[ v ] or alias[ v ] or { }; tcurr[ kcurr ] = tlist[ v ]
elseif vt == 'number' then tcurr[ kcurr ] = alias[ v ] or tonumber ( v )
elseif vt == 'string' then tcurr[ kcurr ] = alias[ v ] or unescape ( v )
else tcurr[ kcurr ] = alias[ v ]
end
end
end
return troot
end
Выгрузка таких вещей как функции (особенно встроенные) и юзердата не предусмотрено, так что надо передавать список строковых псевдонимов в формате { ["math.max"] = math.max, ["getUniqueID"] = getUniqueID, ... }.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Тут суть скорее в том что есть практическая возможность использовать алгоритм который не даёт осечек (просто ID+=1)* а вы используете стохастические и ограниченно-отказоустойчивые, в результате чего со временем происходят ошибки.
*даже выполняя миллион транзакций в секунду, что вчетверо выше пиковой пропускной способности NASDAQ, оверфлов произойдет не ранее чем через ~38,9 миллиардов лет
Шо значит могли бы. Если бы существовал нормальный браузер (а не агент гугла/яндекса/майкрософта с побочной функцией отрисовки хтмл), было бы здорово.
Я имел ввиду не тонкий клиент, а чтобы на локальном терминале вместо классического Winforms/GTK/QT и т.п. ГУЯ выводилась веб-страница. Вообще я изначально хотел предложить движок QUIK к Chromium прикрутить, но это слишком жирный объем работы для такого несерьёзного изменения.
То что веб-браузер это теперь целая операционная система только ради того, чтобы можно было запускать приложения из интернета без установки и компиляции (даже формошлёпство на HTML уже отпало), ну так исторически сложилось. Можно кривляться а можно эксплуатировать.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Незнайка написал: Есть идеи, как сделать уникальный trans_id в разных роботах без необходимости задавать свой диапазон (robot_id) внутри каждого робота (или их копий)?
Если робот работает в личной инстанции QUIK то можно взять Process ID из операционной системы, нормализировать по длине, и к нему спереди приклеивать порядковый номер транзакий и т.п. Альтернативно, можно брать адрес его функции main - для разных роботов (из разных файлов) он будет разный.
Цитата
BlaZed написал: В результате чтобы нарушилась уникализация надо одним роботом более 100 раз в секунду транзакцию сделать, что практически невозможно.
Делать ставку на то что маловероятное событие НИКОГДА не произойдёт - плохая тактика. Владимир уже на своем опыте об этом знает.
Косность и дубовость интереса (или разработчиков?) - просто поражает воображение!
Всё в лучших традициях олдскульного кодинга - графический интерфейс делается по остаточному принципу.
Вообще, могли бы прикрутить HTTP сервер к QUIK и сделать безголовый режим, и просто веб-морду состряпать которая открывается в браузере, что во-первых не составляет никакого труда, а во-вторых позволяет юзерам легко всё регулировать через скрипты и стайлщиты.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
В догонку: сид рандома надо задавать вручную из какой-то непостоянной величины, которая будет меняться от запуска к запуску. Псевдослучайный рандом, разумеется, всегда выдаёт одинаковую последовательность чисел - если она еще и начинается каждый раз с одного и того же числа, то никакой случайности не будет.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
У стандартного рандома Lua всего 15 бит собственно рандомности, не считая несовершенство алгоритма генератора - повторы гарантированны с довольно короткой периодичностью.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Артем написал: какой такой сценарий в контексте брокерского торгового терминала предпологает "некоммерческое" использование?
Некоммерческое использование это значит, что любое частное лицо (пользователь) может использовать обсуждаемые средства (в том виде как они есть, без гарантии последующей их поддержки с моей стороны) для создания своего робота.
Создаешь с помощью вашего фреймворка робота который будет торговать и зарабатывать деньги - тут налицо коммерческое использование. Логически, любая утилита для торгового терминала по-умолчанию будет использоваться коммерчески так как у торгового терминала есть только коммерческий функционал.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Целую страницу постов а-ля "нинужно, кг/ам" нафлудили. Вам нинужно, а кому-то может интересно будет. Та же is-odd.js как ни абсурдно имеет астрономическую популярность (справедливости ради, широта языка не распологает к инлайн-исполнению таких вещей).
Вопрос к автору: какой такой сценарий в контексте брокерского торгового терминала предпологает "некоммерческое" использование?
Насколько я понимаю, время свечки пересчитывается по локальным часам. Может ли быть такое, что сделка, попадающая точно на границу свечек, может попасть в предыдущую свечку а не в следующую при обработке в колбеке? При этом такой эффект не будет наблюдаться при загрузке архива свечек с сервера. Попробуйте вывести также содержимое соседних свечек.
В обоих случаях установлен бит 10 "отклонено торговой системой". Судя по тому что для "следок" бит 10 и бит 1 не определёны, я пологаю вы имеете ввиду "заявки"? Бит 0 заявок указывает на активность заявки, что не важно при отклонении т.к. она не может быть активна, а бит 1 указывает на то что заявка снята. Старая система показывает "отклонено, активно" а новая система показывает "отклонено, снято".
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Владимир, написание велосипедов - так себе достижение. При желании конечно что-то вроде TempleOS можно навелосипедить, но это надо иметь терминальную стадию шизофрении, а в противном случае попросту не представляется возможным на современной аппаратуре. Не говоря о том что это по сути пустая трата времени. Я раньше увлекался деланием видеоигр, и там целое движение "движкописателей" существует, которые до написания собственно игр не доходят. В кружке художников тоже существуют идейные элитисты которые цифровые инструменты не признают, хотя по итогу визуальное качество оказывается гораздо выше при тех же трудозатратах.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Владимир написал: TGB, Совершенно верно: "все можно сделать и на ассемблере". А кое-что можно сделать ТОЛЬКО на ассемблере. А потому именно на нём и можно предельно быстро и качественно разрабатывать любые приложения. В общем случае, быстрее, чем на любом другом языке. ::
Я как-то одному знакомому веб-программисту, в ответ на высказывание что "использовать ассемблер ничуть не тяжелее пхп", предложил написать на ассемблере программу прыгающего логотипа DVD на любой платформе, например Денди (процессор 6502). В ответ на что он конечно не засунул язык в задницу как подобает джентльмену, а начал кривляться что это ниже его достоинства и вообще он слишком занят. Его друг мне в ответ предложил написать определённого Telegram-бота за два дня (судя по его выпалке это должно было быть коротким сроком), с чем я справился за три часа т.к. у Telegram специально для этого был веб-интерфейс. Программировать графику на Денди конечно тоже было очень просто - там специальный графический процессор есть, достаточно просто скопировать часть ROM в VRAM и записать байтики в несколько регистров - но этот брошенный вызов остался неотвеченным. Предлагаю и вам "предельно быстро и качественно" написать такую программу.
Владимир,ну не надо ёрничать. Программы оптимизируются под имеющуюся аппаратуру. Если вычислительной мощности нехватает то разработчики вынуждены срезать углы чтобы затолкать главную часть функционала в имеющиеся рамки. А если мощности предостаточно то не требуется заниматься микрооптимизацией а можно сосредоточиться на собственно написании программы в её наиполнейшем варианте.
Дядя Билли тоже таким вопросом задавался, ведь 640 килобайт это такой огромный объем памяти, что туда может не влезть? Тут всё действует по принципу "был бы ресурс, а применение найдётся".
Владимир, с тех пор стоимость мегабайта памяти снизилась с $3 000 до $0.003 так что на спичках экономить перестало быть целесообразно. Ну и много свечек в 4 килобайта не затолкаешь как ни старайся.
Владимир, Мне - ничем, я пользуюсь только программным интерфейсом. Вам оно может помочь либо точно установить источник ошибкок который вы можете обогнуть в своем коде, либо создать точный багрепорт для разработчиков QUIK чтобы они могли его быстрее исправить. Под лежачий камень вода не течет.
Тут рекомендация докупить побольше оперативной памяти а не выжимать побольше возможностей из ограниченной системы. 32 гигабайта должно быть вполне адекватно: мой несжатый текстовых архив на 70 000 000 свечек занимает 5 гигабайт.
Если я правильно понимаю, то нет ограничений по количеству одинаковых/различных комментариев. Таким образом, можно подсчитать количество открытых роботом позиций на основе либо простого строкового сравнения, либо соответствующего регулярного выражения. Настройки робота можно описывать в файле конфигурации который он загружает при начале работы. Выполнить его можно как обычный Lua-файл который объявляет некоторые переменные; робот будет его загружать и эти переменные будут доступны внутри его кода.
В английском языке есть такая идиома, "assuming makes an ass out of you and me". Индукционные заключения валидны только при полноте данных, а в этой ситуации отсутствует большое их количество. Мои предложения направлены на заполнение этого вакуума. Напоминаю, что баги легче фиксить если существует хороший репорт, так что "заниматься онанизмом" это в ваших интересах.
Владимир, попробуйте создать таблицу заполненную нулями со случайно раскрашенными полями и высокой частотой обновления. Если проблема в QUIK то ошибка должна воспроизводиться и на синтетической таблице.
Владимир, ну так там цвета и из других источников берутся, а не только указываются литерально.
Попробуйте составить отдельный самодостаточный код который воспроизводит ошибку. Попытайтесь уменьшить количество кода чтобы можно было понять, в каких именно ситуациях ошибка возникает. Тогда во-первых ошибку можно будет избежать, а во-вторых отдать в трекер для исправления.
Детский-не детский, а дебаг проводить таки надо, а не просто пологаться на "да я 40 лет программирую, ошибок не допускаю принципиально" - как минимум чтобы претензии не голословно предъявлять. Да и вообще, как бы знать положено что репорты багов даются с минимально воспроизводимым кодом а не "у меня тут что-то не работает, свой показывать не буду, давайте чините".
Артем написал: Между чтениями данных из базы данных образуется задержка, которая может быть достаточно большой чтобы выполнилась одна или более транзакций.
Транзакция в прошлом? В окне сообщений есть и время свечи и время самого сообщения.
В асинхронных фреймворках еще и не такое бывает.
Вроде как свечи обновляются срезами, разные срезы = расхождение в данных.
В программировании как в квантовой физике - всегда всё может быть. Попробуйте использовать измененный код. Он не должен выводить никаких сообщений при корректной работе. Попробуйте также подписаться на большое количество данных и высокую частоту обновления, чтобы максимально повысить вероятность появления ошибки.
Код
k=0xFFFFFF; -- по умолчанию строки чёрно-белые
l=0; -- k - цвет фона, l - цвет текста
SetColor(T,a[i][10],-1,k,l,-1,-1);
k=W[a[i][1][3]+1]; -- цвет фона столбца кода тикера
l=L[a[i][1][1]+1]; -- цвет текста для разных валют
if a[i][1][8]==0 then k=0xFFFF;end;
if a[i][2]==0 then k=0x990000;l=0xFFFFFF;end;
if k == l then message ( "Идентичный цвет фона и текста" ) end
SetColor(T,a[i][10],1,k,l,-1,-1);
SetCell(T,a[i][10],1,a[i][0]);-- заполняем данными строку таблицы
Nikolay написал: include файлы и lua54.lib взято с оф. сайта lua.
Не точно, но возможно, вы взяли статическую библиотеку lua54.lib (~300 кб.). Надо использовать библиотеку импорта dll lua54.lib (~30 кб.) с тем, чтобы использовались функции QUIK из его lua54.dll. Либо надо самому создать библиотеку импорта lua54.lib, используя lua54.dll из QUIK.
Возможно. Но, как написал, просто сам собрал.
Собрал Lua 5.4.1, не работает. Файл lua54.lib производится динамический (30кб). Использовал вот такой скрипт:
Код
cl /MD /O2 /c /DLUA_BUILD_AS_DLL *.c
ren lua.obj lua.o
ren luac.obj luac.o
link /DLL /IMPLIB:lua54.lib /OUT:lua54.dll *.obj
link /OUT:lua.exe lua.o lua54.lib
lib /OUT:lua54-static.lib *.obj
link /OUT:luac.exe luac.o lua54-static.lib
Владимир написал: там у меня тоже ничего нет, кроме SetCell, да SetColor
Работа с именно этмии функциями и может быть проблематичной. Чтобы убедиться, на чьей стороне ошибка, прямо перед вызовом этих функций проверьте, идентичный цвет фона и текста передаётся в них или различный. Можете также перенести весь код заполнения таблицы в ту часть, где он не может выполняться синхронно с другим кодом.
Исполнение кода занимает некоторое время, команда sleep принудительно останавливает процесс. Между чтениями данных из базы данных образуется задержка, которая может быть достаточно большой чтобы выполнилась одна или более транзакций.
Ваш код очень тяжело читается, возможно содержит неочевидные ошибки. Что именно он должен делать, если словами?
Колбеки не являются прерываниями т.к. не прерывают исполнение фонового кода. Предпологаю что OnTrade у вас, через цепочку вызовов и возможно глобальных переменных, отправляет в отрисовщик таблицы данные с идентичным цветом фона и текста. Можете проверить таковую гипотезу, оставив тело OnTrade полностью пустым.
Алексей написал: Так прежде, чем это всё настроить надо голову сломать, чтоб понять как. Квик, в отличие от других, интуитивно НЕ понятен. Путай - путай он.
Простой интерфейс = мало информации. Мало информации = низкая точность предсказания рынка. Низкая точность предсказания = высокая вероятность проиграть.
Практически каждый брокер имеет собственное приложение для торговли с простым и понятным интерфейсом. Если QUIK видится как слишком сложный инструмент, пользуйтесь приложениями брокера.
QUIK предоставляет полный объем инструментария, пользователь сам выбирает какими пользоваться а какие скрыть. По умолчанию даётся неплохой набор окон и настроек для обычного торговца на бирже. Ненужные окна можно позакрывать, недостающие - добавить.
Правильный подход в асинхронных программах это каждый раз запрашивать таблицу и пользоваться только табличными данными - колбеки это только для информирования что что-то поменялось. По поводу пачек колбеков: пишите их в стек а не исполняйте все сразу. В стеке можно их отсортировать по времени и удалить "дублирующие" инстанции. Как и в любом другом API, последовательность вызова колбеков не определена и в лучшем случае имеется "типичная последовательность" опираться на которую не следует.
local duplicates = { }for k, v in pairs ( t1 ) do duplicates[ v ] = ( duplicates[ v ] or 0 ) + 1endfor k, v in pairs ( duplicates ) do
if v > 1 then t2[ #t2 + 1 ] = k endend
Просуммировать количество каждого значения, потом выбрать значения у которых сумма >1.
hts написал: Скажите плиз Как настроить квак под торговлю иностранцами, ETF, акциями и облигациями
Что вы имеете ввиду? Простой терминал, который подойдёт для большинства типов торговли, состоит из графика, стакана, списка заявок и позиций, портфеля, баланса, и списка инструментов. Поменяв список инструментов в редакторе таблицы можно выбрать облигации, ETF, акции в т.ч. иностранных компаний. При желании можно добавить несколько графиков, стаканов и прочих окон.
Я нашел в чём проблема. При добавлении скриптов QUIK меняет рабочую директорию на директорию скрипта. В результате чего, с одной стороны элемент package.path который загружает модули из текущей директории перестаёт функционировать (но дублируется элементом с абсолютным путём), а с другой стороны создаёт иллюзию что у каждого скрипта есть своя личная рабочая директория из которой будут подгружаться модули, а не только из корня QUIK.