Как-то зашла речь
smart-lab.ru/blog/961365.php
хорош Quik или плох.
Replikant_mih, последнюю мою систему Квик просто физически не потянул, хотя вся его задача была, это трансляция данных и получение заявок. До заявок дело не дошло.))
3Qu Сегодня в 00:28
3Qu, использовать события типа On-Anything для чего-то, кроме table.sinsert() — очень плохая идея. Никаких ДЛЛ в событиях! Эти события — в главном потоке Квика.
Для обработки данных из таблицы следует использовать table.sremove() в функции main(). Например в цикле через wait (1) или wait(100) — тыщу или 10 раз в секунду. И очищать накопления в таблице одним махом.
Rostislav Kudryashov Сегодня в 01:02
Rostislav Kudryashov, про main я в курсе. С другой стороны, что отдать в main, что сразу в ДЛЛ — время практически одинаковое (еще неизвестно, куда быстрее)). Дальше по любому асинхронно.
Кстати, и через main не тянет. Даже с пропусками части значений.
Квик, кстати, не виснет, с виду все нормально, время сервера начинает отставать от реала. Как вам данные 5-ти минутной давности?))
3Qu Сегодня в 01:25
Это слова. Факты таковы. Регистрируем обезличенные сделки — это самый интенсивный поток данных с биржи. Самые торгуемые фьючерсы MXZ3, RIZ3, SiZ3. Вместо неуказанного протокола передачи данных используем самый дубовый, напролом, вывод в текстовый файл на HDD.
К каждой записи добавляем расхождение времени ПК и времени сервера. Оно практически постоянно.
Quik тянет как зверь. Всё вовремя. За несколько часов расхождение между локальным временем ПК, временем сервера и временем из обезличенных сделок осталось в пределах 2 секунд.
Десктоп не очень новый: Intel® Core(TM) i7-3770 CPU @ 3.40 GHz, ядер 4, логических процессоров 8. Память 16 Гб. SSD AMD RSSL256G, HDD WDC WD5003ABYX-01WERA1.
При этом был запущен виртуальный ПК для интернет-браузера.
За 3 с лишним часа испытания набралось 70077 записей. Вот первые и последние из этих записей.
Dlt;ServerTm;LocalTm;TradeDateTime;Sec;Cls;Per;TradeNo;Flags;Price;Qty
2;13:00:29;13:00:27;2023.11.20-13:00:29;SiZ3;SPBFUT;1;1892948986797760030;1026;88990.0000;2
...
2;13:00:29;13:00:27;2023.11.20-13:00:29;RIZ3;SPBFUT;1;1925037134142534737;1025;113400.0000;1
...
2;13:00:29;13:00:27;2023.11.20-13:00:30;MXZ3;SPBFUT;1;1984991304181889167;1026;320500.0000;1
… ...
2;16:28:44;16:28:42;2023.11.20-16:28:45;SiZ3;SPBFUT;1;1892948986797842050;1026;89153.0000;1
А вот код на QLua 5.3.5
-- Вывод в файл обезличенные сделки и SERVERTIME-LOCALTIME
SecTbl = {"MXZ3", "RIZ3", "SiZ3"}
LogPath = "D:\\TMP\\OnAllTradeLog.csv"
DataQueue = {}
StopFlag = false
AllTradeTitle = "TradeDateTime;Sec;Cls;Per;TradeNo;Flags;Price;Qty"
function AllTradeToString (t)
-- Не включаем поля accruedint, yield, settlecode, reporate, repovalue,
-- repo2value, repoterm, open_interest, exchange_code, exec_market, benchmark.
local dt = DateTimeToString (t.datetime)
return string.format ("%s;%s;%s;%d;%d;%d;%.4f;%d", dt
,t.sec_code, t.class_code, t.period, t.trade_num, t.flags, t.price, t.qty)
end -- AllTradeToString()
function DateTimeToString (dt)
return string.format ("%04d.%02d.%02d-%02d:%02d:%02d"
,dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec)
end -- DateTimeToString()
function OnAllTrade (alltrade) -- В Quik'е д.б.
-- Настройки-Программа-Получение данных-Обезличенные и
-- открыть, свернуть окно "Обезличенные сделки".
for _,v in ipairs (SecTbl) do
if v == alltrade.sec_code then
table.sinsert (DataQueue, {alltrade
,getInfoParam ("SERVERTIME"), getInfoParam ("LOCALTIME")})
return
end
end
end -- OnAllTrade()
function OnStop (signal)
StopFlag = true
return 1000
end -- OnStop()
function SendData (data)
local at = AllTradeToString (data[1])
local st = data[2]
local lt = data[3]
local dlt = TimeToSeconds (st) - TimeToSeconds (lt)
LogFile:write (string.format ("%4d;%s;%s;%s\n", dlt, st, lt, at))
end -- SendData()
function TimeToSeconds (t) -- Текст формата HH:MM;SS
return (tonumber (t:sub(1,2)) * 60 + t:sub(4,5)) * 60 + t:sub(7,8)
end -- TimeToSeconds()
function main()
message ("main started\n".. "SERVER ".. getInfoParam ("SERVERTIME")
.."\nLOCAL ".. getInfoParam ("LOCALTIME"))
if 1 ~= isConnected() then error ("Not Connected") end
for i = 1, #SecTbl do
if not Subscribe_Level_II_Quotes ("SPBFUT", SecTbl[i]) then
message ("Subscribe_Level_II_Quotes failed with ".. SecTbl[i])
return
end
end
LogFile = io.open (LogPath, "w")
LogFile:write ("Dlt;ServerTm;LocalTm;".. AllTradeTitle .."\n")
while not StopFlag do
sleep (10)
while #DataQueue > 0 do
SendData (table.sremove (DataQueue, 1))
end
end -- while not StopFlag
LogFile:close()
message ("main StopFlag ".. tostring (StopFlag))
end -- main()
...
Ну а со среднем временем в позиции больше 30 минут и(или) со средней прибыльной сделкой больше 0,8% в квике нет никаких проблем.
«Flash Boys. Высокочастотная революция на Уолл-Стрит» Майкл Льюис.
В Quik'е событие OnQuote() и команда getQuoteLevel2() не дают такой информации.
И почему события в стакане должны иметь задержку в несколько раз большую, чем в таблице обезличенных сделок?
В моих системах минутки закачиваются и этот «сбой» со сменой цен закрытия минуток я заметил, качая минутки с графика в моменты окончания минуток и потому сделал программу формирования минуток из таблиц всех сделок с отслеживанием времени совершения сделок. Потому что для моих алгоритмов не имеет значение задержка на секунды, а вид минутки имеет значение.
После подачи заявки из QLua командой sendTransaction() до подтверждения от брокера в событии OnTransReply() проходит 50-100 миллисекунд.
После этого до получения от брокера регистрации заявки на бирже по событию OnOrder() проходит ещё 50-100 миллисекунд.
Т.е. подтверждение заявки после её подачи Quik'ом приходит от брокера (с биржи) через 0.2 секунды максимум.
А вот мой скрипт — это вполне эталон качества. Знай наших!