Блог им. _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 и запускаете его.
Например сравнить какой объём был проторгован маркет ордерами на каждом ценовом уровне с максимальным лимитником встречного направления на этом же уровне.