From c2f92a69319ab0982e7b1e63ea182f94faca8b8b Mon Sep 17 00:00:00 2001 From: cia76 Date: Sun, 25 Sep 2022 17:33:59 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=81=D0=BA=D1=80=D0=B8?= =?UTF-8?q?=D0=BF=D1=82=D0=BE=D0=B2=20LUA=20=D1=81=20QUIKSharp.=20=D0=92?= =?UTF-8?q?=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20ReadMe=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=BE=D0=B1=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0=D1=85=20cor?= =?UTF-8?q?e.dll=20/=20LUA=20=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QUIK/lua/qsfunctions.lua | 148 ++++++++++++++++++++++++++++++++++++++- QUIK/lua/qsutils.lua | 14 +++- README.md | 4 ++ 3 files changed, 162 insertions(+), 4 deletions(-) diff --git a/QUIK/lua/qsfunctions.lua b/QUIK/lua/qsfunctions.lua index 6feea7f..f808554 100644 --- a/QUIK/lua/qsfunctions.lua +++ b/QUIK/lua/qsfunctions.lua @@ -156,6 +156,102 @@ function qsfunctions.addLabel(msg) return msg end +-- Выводит на график метку +-- Функция возвращает числовой идентификатор метки. В случае неуспешного завершения функция возвращает «nil». +function qsfunctions.addLabel2(msg) + local spl = split2(msg.data, "|"); + local chartTag, yValue, strDate, strTime, text, imagePath, alignment, hint, r, g, b, transparency, tranBackgrnd, fontName, fontHeight = + spl[1], spl[2], spl[3], spl[4], spl[5], spl[6], spl[7], spl[8], spl[9], spl[10], spl[11], spl[12], spl[13], spl[14], spl[15]; + + -- значения по умолчанию + if text == "" then text = nil else r = 255 end + if imagePath == "" then imagePath = nil end + if alignment == "" then alignment = nil end + if hint == "" then hint = nil end + if r == "-1" then r = nil end + if g == "-1" then g = nil end + if b == "-1" then b = nil end + if transparency == "-1" then transparency = nil end + if tranBackgrnd == "-1" then tranBackgrnd = nil end + if fontName == "" then fontName = nil end + if fontHeight == "-1" then fontHeight = nil end + + local labelParams = { + YVALUE = yValue:gsub(",", "."), + DATE = strDate, + TIME = strTime, + TEXT = text, + IMAGE_PATH = imagePath, + ALIGNMENT = alignment, + HINT = hint, + R = r, + G = g, + B = b, + TRANSPARENCY = transparency, + TRANSPARENT_BACKGROUND = tranBackgrnd, + FONT_FACE_NAME = fontName, + FONT_HEIGHT = fontHeight, + } + + local res = AddLabel(chartTag, labelParams); + + msg.data = res; + return msg; +end + +-- Функция задает параметры для метки с указанным идентификатором. +-- В случае успешного завершения функция возвращает «true», иначе – «false». +function qsfunctions.setLabelParams(msg) + local spl = split2(msg.data, "|"); + local chartTag, labelId, yValue, strDate, strTime, text, imagePath, alignment, hint, r, g, b, transparency, tranBackgrnd, fontName, fontHeight = + spl[1], spl[2], spl[3], spl[4], spl[5], spl[6], spl[7], spl[8], spl[9], spl[10], spl[11], spl[12], spl[13], spl[14], spl[15], spl[16]; + + -- значения по умолчанию + if text == "" then text = nil else r = 255 end + if imagePath == "" then imagePath = nil end + if alignment == "" then alignment = nil end + if hint == "" then hint = nil end + if r == "-1" then r = nil end + if g == "-1" then g = nil end + if b == "-1" then b = nil end + if transparency == "-1" then transparency = nil end + if tranBackgrnd == "-1" then tranBackgrnd = nil end + if fontName == "" then fontName = nil end + if fontHeight == "-1" then fontHeight = nil end + + local labelParams = { + YVALUE = yValue, + DATE = strDate, + TIME = strTime, + TEXT = text, + IMAGE_PATH = imagePath, + ALIGNMENT = alignment, + HINT = hint, + R = r, + G = g, + B = b, + TRANSPARENCY = transparency, + TRANSPARENT_BACKGROUND = tranBackgrnd, + FONT_FACE_NAME = fontName, + FONT_HEIGHT = fontHeight, + } + + local res = SetLabelParams(chartTag, tonumber(labelId), labelParams); + msg.data = tostring(res); + return msg; +end + +-- позволяет получить параметры метки +-- Функция возвращает таблицу с параметрами метки. В случае неуспешного завершения функция возвращает «nil». +function qsfunctions.getLabelParams(msg) + local spl = split2(msg.data, "|"); + local chartTag, labelId = spl[1], spl[2]; + + local res = GetLabelParams(chartTag, tonumber(labelId)); + msg.data = res; + return msg; +end + -- Удаляем выбранную метку function qsfunctions.delLabel(msg) local spl = split(msg.data, "|") @@ -207,7 +303,7 @@ function qsfunctions.getSecurityInfo(msg) return msg end ---- Функция берет на вход список из элементов в формате class_code|sec_code и возвращает список ответов функции getSecurityInfo. +--- Функция берет на вход список из элементов в формате class_code|sec_code и возвращает список ответов функции getSecurityInfo. -- Если какая-то из бумаг не будет найдена, вместо ее значения придет null function qsfunctions.getSecurityInfoBulk(msg) local result = {} @@ -262,7 +358,15 @@ function qsfunctions.getClientCodes(msg) for i=0,getNumberOf("MONEY_LIMITS")-1 do local clientcode = getItem("MONEY_LIMITS",i).client_code if clientcode ~= nil then - table.insert(client_codes, clientcode) + fnd = false + for index, value in ipairs(client_codes) do + if value == clientcode then + fnd = true + end + end + if fnd == false then + table.insert(client_codes, clientcode) + end end end msg.data = client_codes @@ -345,6 +449,33 @@ end -- Trading functions -- ----------------------- +--- Функция предназначена для расчета максимально возможного количества лотов в заявке. +-- При заданном параметре is_market=true, необходимо передать параметр price=0, иначе будет рассчитано максимально возможное количество лотов в заявке по цене price. +function qsfunctions.calc_buy_sell(msg) + local bs = CalcBuySell + local spl = split(msg.data, "|") + local class_code, sec_code, clientCode, account, price, is_buy, is_market = spl[1], spl[2], spl[3], spl[4], spl[5], spl[6], spl[7] + if is_buy == "True" then + is_buy = true + else + is_buy = false + end + if is_market == "True" then + is_market = true + else + is_market = false + end + local qty, comiss = bs(class_code, sec_code, clientCode, account, tonumber(price), is_buy, is_market) + if qty ~= "" then + msg.data = {} + msg.data.qty = qty + msg.data.comission = comiss + else + message("Ошибка функции CalcBuySell", 1) + end + return msg +end + --- отправляет транзакцию на сервер и возвращает пустое сообщение, которое -- будет проигноировано. Вместо него, отправитель будет ждать события -- OnTransReply, из которого по TRANS_ID он получит результат отправленной транзакции @@ -370,7 +501,7 @@ function qsfunctions.paramRequest(msg) return msg end ---- Функция принимает список строк (JSON Array) в формате class_code|sec_code|param_name, вызывает функцию paramRequest для каждой строки. +--- Функция принимает список строк (JSON Array) в формате class_code|sec_code|param_name, вызывает функцию paramRequest для каждой строки. -- Возвращает список ответов в том же порядке function qsfunctions.paramRequestBulk(msg) local result = {} @@ -523,6 +654,17 @@ function qsfunctions.getFuturesHolding(msg) return msg end +-- Функция для получения информации по всем фьючерсным позициям +function qsfunctions.getFuturesClientHoldings(msg) + local holdings = {} + for i=0,getNumberOf("futures_client_holding")-1 do + local holding = getItem("futures_client_holding",i) + table.insert(holdings, holding) + end + msg.data = holdings + return msg +end + -- Функция возвращает таблицу заявок (всю или по заданному инструменту) function qsfunctions.get_orders(msg) if msg.data ~= "" then diff --git a/QUIK/lua/qsutils.lua b/QUIK/lua/qsutils.lua index 54e6a05..3a15810 100644 --- a/QUIK/lua/qsutils.lua +++ b/QUIK/lua/qsutils.lua @@ -127,7 +127,7 @@ function log(msg, level) end end - +-- Doesn't work if string contains empty values, eg. 'foo,,bar'. You get {'foo','bar'} instead of {'foo', '', 'bar'} function split(inputstr, sep) if sep == nil then sep = "%s" @@ -141,6 +141,18 @@ function split(inputstr, sep) return t end +-- https://stackoverflow.com/questions/1426954/split-string-in-lua#comment73602874_7615129 +function split2(inputstr, sep) + sep = sep or '%s' + local t = {} + for field, s in string.gmatch(inputstr, "([^"..sep.."]*)("..sep.."?)") do + table.insert(t, field) + if s == "" then + return t + end + end +end + function from_json(str) local status, msg= pcall(json.decode, str, 1, json.null) -- dkjson if status then diff --git a/README.md b/README.md index 485a0be..2ef6bc1 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ Скрипт должен запуститься без ошибок, в окне сообщений QUIK выдать **QUIK# is waiting for client connection...** +### Возможные ошибки +1. Если возникают ошибки, связанные с **core.dll**, то все варианты этой библиотеки выложены в проекте QUIKSharp [здесь >>>](https://github.com/finsight/QUIKSharp/tree/master/src/QuikSharp/lua/clibs64) Путем перебора подбираете подходящую для вас версию core.dll +2. Если возникают ошибки при исполнении LUA скриптов, то, возможно, были обновления в QUIK или LUA. Последняя версия LUA скриптов находится [здесь >>>](https://github.com/finsight/QUIKSharp/tree/master/src/QuikSharp/lua) Они не учитывают мои специфические правки, но должны работать без ошибок с последней версией QUIK. + ### Начало работы В папке **Examples** находится хорошо документированный код примеров. С них лучше начать разбираться с библиотекой.