Блог им. _sk_
-- -- Вывод таблицы крупных "склеенных" обезличенных сделок по набору инструментов. -- -- Для каждого инструмента, идентифицируемого кодом класса и кодом инструмента, -- задаются следующие значения: -- largeBound = положительная граница размера крупной склеенной сделки в лотах/контрактах; -- hugeBound = положительная граница размера очень крупной склеенной сделки в лотах/контрактах; -- slipPercent = размер проскальзывания в процентах, которое считается большим; -- manyBound = граница количества сделок в "слишком многосоставной" склеенной сделке. -- settings = { ["TQBR:SBER"] = { largeBound = 500, hugeBound = 2000, slipPercent = 0.03, manyBound = 25, }, ["SPBFUT:SiH2"] = { largeBound = 50, hugeBound = 200, slipPercent = 0.03, manyBound = 25, }, } dofile(getScriptPath() .. "/LargeMergedTrades.lua")
-- -- Вывод таблицы крупных "склеенных" обезличенных сделок по набору инструментов. -- -- Для каждого инструмента, идентифицируемого кодом класса и кодом инструмента, -- задаются следующие значения: -- largeBound = положительная граница размера крупной склеенной сделки в лотах/контрактах; -- hugeBound = положительная граница размера очень крупной склеенной сделки в лотах/контрактах; -- slipPercent = размер проскальзывания в процентах, которое считается большим; -- manyBound = граница количества сделок в "слишком многосоставной" склеенной сделке. -- -- Пример файла настроек, из которого вызывается основной скрипт: -- settings = { -- ["TQBR:SBER"] = { -- largeBound = 500, -- hugeBound = 2000, -- slipPercent = 0.03, -- manyBound = 25, -- }, -- ["SPBFUT:SiH2"] = { -- largeBound = 50, -- hugeBound = 200, -- slipPercent = 0.03, -- manyBound = 25, -- }, -- } -- dofile(getScriptPath() .. "/LargeMergedTrades.lua") -- -- -- Цветовые настройки: FG -- цвет символов, BG -- цвет фона -- -- Цветовые настройки для больших покупок local LARGE_BUY_FG_COLOR = RGB(216, 255, 216) local LARGE_BUY_BG_COLOR = RGB(0, 0, 0) -- Цветовые настройки для очень больших покупок local HUGE_BUY_FG_COLOR = RGB(160, 255, 160) local HUGE_BUY_BG_COLOR = RGB(0, 0, 0) -- Цветовые настройки для больших проскальзываний при покупках local SLIP_BUY_FG_COLOR = RGB(128, 255, 128) local SLIP_BUY_BG_COLOR = RGB(0, 0, 0) -- Цветовые настройки для большого количества сделок в склеенной сделке при покупке local MANY_BUY_FG_COLOR = RGB(64, 255, 64) local MANY_BUY_BG_COLOR = RGB(0, 0, 0) -- Цветовые настройки для больших продаж local LARGE_SELL_FG_COLOR = RGB(255, 216, 216) local LARGE_SELL_BG_COLOR = RGB(0, 0, 0) -- Цветовые настройки для очень больших продаж local HUGE_SELL_FG_COLOR = RGB(255, 160, 160) local HUGE_SELL_BG_COLOR = RGB(0, 0, 0) -- Цветовые настройки для больших проскальзываний при продажах local SLIP_SELL_FG_COLOR = RGB(255, 128, 128) local SLIP_SELL_BG_COLOR = RGB(0, 0, 0) -- Цветовые настройки для большого количества сделок в склеенной сделке при продаже local MANY_SELL_FG_COLOR = RGB(255, 64, 64) local MANY_SELL_BG_COLOR = RGB(0, 0, 0) local SELL_FLAG = 1 local BUY_FLAG = 2 local isInterrupted = false -- флаг прерывания для завершения работы скрипта local tableId -- информационная таблица local prevTrade -- информация о предыдущей обезличенной сделке local currTrade -- информация о текущей обезличенной сделке local mergedTrade = {} -- информация о "склееной" сделке local largeTradesCount = 0 -- количество крупных "склеенных" сделок local largeTrades = {} -- массив крупных "склеенных" сделок local printCount = 1 -- номер крупной "склеенной" сделки, которую нужно вывести в таблицу function OnStop() if tableId then local tId = tableId tableId = nil DestroyTable(tId) end isInterrupted = true end function OnAllTrade(allTrade) prevTrade = currTrade currTrade = allTrade local key = allTrade.class_code .. ":" .. allTrade.sec_code local t = settings[key] if type(t) ~= "table" then return end local largeBound = t.largeBound local buySell = 0 if bit.band(currTrade.flags, BUY_FLAG) == BUY_FLAG then buySell = 1 elseif bit.band(currTrade.flags, SELL_FLAG) == SELL_FLAG then buySell = -1 end -- Эвристика buySell if prevTrade then if currTrade.class_code == prevTrade.class_code and currTrade.sec_code == prevTrade.sec_code and currTrade.trade_num == prevTrade.trade_num + 1 and (buySell > 0 and prevTrade.buySell > 0 and currTrade.price >= prevTrade.price or buySell < 0 and prevTrade.buySell < 0 and currTrade.price <= prevTrade.price) and currTrade.datetime.ms == prevTrade.datetime.ms and os.time(currTrade.datetime) == os.time(prevTrade.datetime) then buySell = buySell * 2 end end currTrade.buySell = buySell if buySell == 1 or buySell == -1 then mergedTrade.datetime = currTrade.datetime mergedTrade.tradeNum = currTrade.trade_num mergedTrade.price1 = currTrade.price mergedTrade.price2 = currTrade.price mergedTrade.prevVolume = 0 mergedTrade.currVolume = currTrade.qty * buySell mergedTrade.count = 1 else mergedTrade.price2 = currTrade.price mergedTrade.prevVolume = mergedTrade.currVolume mergedTrade.currVolume = mergedTrade.currVolume + currTrade.qty * buySell / 2 mergedTrade.count = mergedTrade.count + 1 end if math.abs(mergedTrade.currVolume) >= largeBound then if math.abs(mergedTrade.prevVolume) < largeBound then -- Новая крупная "склеенная" обезличенная сделка largeTrades[largeTradesCount + 1] = { time = os.date("%Y-%m-%d %X", os.time(mergedTrade.datetime)) .. string.format(".%03d", mergedTrade.datetime.ms), classCode = currTrade.class_code, secCode = currTrade.sec_code, tradeNum = mergedTrade.tradeNum, price1 = mergedTrade.price1, price2 = mergedTrade.price2, volume = mergedTrade.currVolume, count = mergedTrade.count, } largeTradesCount = largeTradesCount + 1 else -- Обновление информации о последней крупной "склеенной" обезличенной сделке local largeTrade = largeTrades[largeTradesCount] largeTrade.price2 = mergedTrade.price2 largeTrade.volume = mergedTrade.currVolume largeTrade.count = mergedTrade.count end end end --- Строковое представление для данного числа. -- @param x число -- @return строка, представляющая число с некоторой точностью local function roundStringValue(x) if x == 0 then return "0" end local s = x > 0 and 1 or -1 x = x * s local p = math.log(x, 10) p = math.floor(p - 3) if p >= 0 then return tostring(math.floor(0.5 + x) * s) else return string.format("%." .. (-p) .. "f", x * s) end end local tointeger = math.tointeger or (function(x) return x end) --- Сделать вещественное число целым, если это возможно. -- @param x вещественное число -- @return целое число или исходное вещественное число, если преобразование невозможно local function tryInt(x) return tointeger(x) or x end local function displayInfoTable() if tableId and IsWindowClosed(tableId) then isInterrupted = true else local count = largeTradesCount for rowId = printCount, count do while GetTableSize(tableId) < rowId do InsertRow(tableId, -1) end local largeTrade = largeTrades[rowId] SetCell(tableId, rowId, 1, largeTrade.time) SetCell(tableId, rowId, 2, largeTrade.classCode) SetCell(tableId, rowId, 3, largeTrade.secCode) SetCell(tableId, rowId, 4, tostring(largeTrade.tradeNum), largeTrade.tradeNum) SetCell(tableId, rowId, 5, tostring(largeTrade.price1), largeTrade.price1) SetCell(tableId, rowId, 6, tostring(largeTrade.price2), largeTrade.price2) SetCell(tableId, rowId, 7, tostring(tryInt(largeTrade.volume)), tryInt(largeTrade.volume)) SetCell(tableId, rowId, 8, tostring(largeTrade.count), largeTrade.count) SetCell(tableId, rowId, 9, roundStringValue(largeTrade.price2 - largeTrade.price1), largeTrade.price2 - largeTrade.price1) local t = settings[largeTrade.classCode .. ":" .. largeTrade.secCode] local isHuge = math.abs(largeTrade.volume) >= t.hugeBound local isMany = largeTrade.count >= t.manyBound local isSlippery = math.abs(largeTrade.price2 / largeTrade.price1 - 1) >= t.slipPercent / 100.0 if largeTrade.volume > 0 then if isHuge then SetColor(tableId, rowId, QTABLE_NO_INDEX, HUGE_BUY_FG_COLOR, HUGE_BUY_BG_COLOR, HUGE_BUY_FG_COLOR, HUGE_BUY_BG_COLOR) else SetColor(tableId, rowId, QTABLE_NO_INDEX, LARGE_BUY_FG_COLOR, LARGE_BUY_BG_COLOR, LARGE_BUY_FG_COLOR, LARGE_BUY_BG_COLOR) end if isMany then SetColor(tableId, rowId, QTABLE_NO_INDEX, MANY_BUY_FG_COLOR, MANY_BUY_BG_COLOR, MANY_BUY_FG_COLOR, MANY_BUY_BG_COLOR) end if isSlippery then SetColor(tableId, rowId, QTABLE_NO_INDEX, SLIP_BUY_FG_COLOR, SLIP_BUY_BG_COLOR, SLIP_BUY_FG_COLOR, SLIP_BUY_BG_COLOR) end elseif largeTrade.volume < 0 then if isHuge then SetColor(tableId, rowId, QTABLE_NO_INDEX, HUGE_SELL_FG_COLOR, HUGE_SELL_BG_COLOR, HUGE_SELL_FG_COLOR, HUGE_SELL_BG_COLOR) else SetColor(tableId, rowId, QTABLE_NO_INDEX, LARGE_SELL_FG_COLOR, LARGE_SELL_BG_COLOR, LARGE_SELL_FG_COLOR, LARGE_SELL_BG_COLOR) end if isMany then SetColor(tableId, rowId, QTABLE_NO_INDEX, MANY_SELL_FG_COLOR, MANY_SELL_BG_COLOR, MANY_SELL_FG_COLOR, MANY_SELL_BG_COLOR) end if isSlippery then SetColor(tableId, rowId, QTABLE_NO_INDEX, SLIP_SELL_FG_COLOR, SLIP_SELL_BG_COLOR, SLIP_SELL_FG_COLOR, SLIP_SELL_BG_COLOR) end end end if printCount < count then printCount = count end end end function main() tableId = AllocTable() AddColumn(tableId, 1, "Дата/Время", true, QTABLE_STRING_TYPE, 25) AddColumn(tableId, 2, "Класс", true, QTABLE_CACHED_STRING_TYPE, 10) AddColumn(tableId, 3, "Инструмент", true, QTABLE_CACHED_STRING_TYPE, 10) AddColumn(tableId, 4, "Номер сделки", true, QTABLE_INT_TYPE, 20) AddColumn(tableId, 5, "Нач.Цена", true, QTABLE_DOUBLE_TYPE, 12) AddColumn(tableId, 6, "Кон.Цена", true, QTABLE_DOUBLE_TYPE, 12) AddColumn(tableId, 7, "Кол-во", true, QTABLE_INT_TYPE, 6) AddColumn(tableId, 8, "Частей", true, QTABLE_INT_TYPE, 6) AddColumn(tableId, 9, "Проскальзывание", true, QTABLE_DOUBLE_TYPE, 20) CreateWindow(tableId) SetWindowCaption(tableId, "Крупные склеенные обезличенные сделки") while not isInterrupted do displayInfoTable() sleep(200) end end
скрин бы к такому показать как выглядит — когнетивней быстрей понять смысл
спасибо
1) в папке терминала QUIK создаёте подпапку Lua, в неё кладёте приведённые в посте 2 файла в кодировке Windows CP-1251 (иначе QUIK не поймёт);
2) в терминале вызываете меню Lua-скриптов, добавляете туда файл LargeMergerTrades_Demo.lua и запускаете его.
Например сравнить какой объём был проторгован маркет ордерами на каждом ценовом уровне с максимальным лимитником встречного направления на этом же уровне.