-- Вывод таблицы крупных "склеенных" обезличенных сделок по набору инструментов.
-- Для каждого инструмента, идентифицируемого кодом класса и кодом инструмента,
-- задаётся положительная граница размера крупной обезличенной сделки в лотах/контрактах.
local bounds = {
--[[["TQBR:SBER"] = 500,
["TQBR:GAZP"] = 200,
["SPBFUT:SiM0"] = 100,]]
["SPBFUT:SiH2"] = 3,
}
local isInterrupted = false -- флаг прерывания для завершения работы скрипта
local tableId -- информационная таблица
local SELL_FLAG = 1
local BUY_FLAG = 2
local prevTrade -- информация о предыдущей обезличенной сделке
local currTrade -- информация о текущей обезличенной сделке
local mergedTrade = {} -- информация о "склееной" сделке
local largeTradesCount = 0 -- количество крупных "склеенных" сделок
local largeTrades = {} -- массив крупных "склеенных" сделок
local printCount = 1 -- номер крупной "склеенной" сделки, которую нужно вывести в таблицу
function OnStop()
if tableId then
DestroyTable(tableId)
tableId = nil
end
isInterrupted = true
end
function OnAllTrade(allTrade)
prevTrade = currTrade
currTrade = allTrade
local key = allTrade.class_code .. ":" .. allTrade.sec_code
local bound = bounds[key]
if type(bound) ~= "number" then
return
end
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) >= bound then
if math.abs(mergedTrade.prevVolume) < bound 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
local function rgb(color)
local r, g, b = string.match(color, "#(%x%x)(%x%x)(%x%x)")
return RGB(tonumber(r, 16), tonumber(g, 16), tonumber(b, 16))
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.secCode)
SetCell(tableId, rowId, 3, tostring(largeTrade.price1), largeTrade.price1)
SetCell(tableId, rowId, 4, tostring(largeTrade.price2), largeTrade.price2)
SetCell(tableId, rowId, 5, tostring(largeTrade.volume), largeTrade.volume)
SetCell(tableId, rowId, 6, tostring(largeTrade.count), largeTrade.count)
SetCell(tableId, rowId, 7, tostring(largeTrade.price2 - largeTrade.price1), largeTrade.price2 - largeTrade.price1)
--SetCell(tableId, rowId, 3, largeTrade.classCode)
--SetCell(tableId, rowId, 4, tostring(largeTrade.tradeNum), largeTrade.tradeNum)
--[[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(largeTrade.volume), largeTrade.volume)
SetCell(tableId, rowId, 8, tostring(largeTrade.count), largeTrade.count)
SetCell(tableId, rowId, 9, tostring(largeTrade.price2 - largeTrade.price1), largeTrade.price2 - largeTrade.price1)]]
if largeTrade.volume > 0 then
SetColor(tableId, rowId, QTABLE_NO_INDEX, rgb("#0b091c"), rgb("#006f00"), rgb("#0b091c"), rgb("#006f00")) --#9b0000 FFE8E8 006f00
elseif largeTrade.volume < 0 then
SetColor(tableId, rowId, QTABLE_NO_INDEX, rgb("#0b091c"), rgb("#9b0000"), rgb("#0b091c"), rgb("#9b0000"))
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, 2, "Тикер", true, QTABLE_CACHED_STRING_TYPE, 10)
--AddColumn(tableId, 4, "Номер сделки", true, QTABLE_INT_TYPE, 20)
AddColumn(tableId, 3, "Нач.Цена", true, QTABLE_DOUBLE_TYPE, 12)
AddColumn(tableId, 4, "Кон.Цена", true, QTABLE_DOUBLE_TYPE, 12)
AddColumn(tableId, 5, "Кол-во", true, QTABLE_INT_TYPE, 6)
AddColumn(tableId, 6, "Частей", true, QTABLE_INT_TYPE, 6)
AddColumn(tableId, 7, "Проскальзывание", true, QTABLE_DOUBLE_TYPE, 20)
CreateWindow(tableId)
SetWindowCaption(tableId, "Time and Sales")
--[[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 |