1 (2014-07-04 17:24:07 отредактировано Archie)

Тема: Работающие скрипты на Lua

Предлагаю здесь размещать целиком законченные и рабочие скрипты на Lua.

Основная идея такая:
часто в Интернете на каких-либо ресурсах попадаются скрипты на Lua для Quik, но при попытке их загрузки сходу в Quik с малыми изменениями (например просто изменить номер счета и торговый инструмент) возникают ошибки вроде таких: для работы требуются определенные библиотеки/функции, а библиотеки/функции самописные и обратно не совместимые. В итоге в скриптах эти функции не работают или работают не так как от них ожидалось.
Здесь предлагается размещать проверенные в работе скрипты (желательно, чтобы большинство используемых функций находились внутри скрипта, в идеале все функции внутри) или ссылки на таковые, если их работа была проверена, желательно с указанием даты проверки, версии Quik и торгового инструмента.

2 (2014-07-06 09:28:15 отредактировано Archie)

Re: Работающие скрипты на Lua

Идея взята отсюда - http://quik2dde.ru/viewtopic.php?id=39, автору за него огромное спасибо, но у меня также не пошел ввод/вывод с xml (ошибка ""Error loading module 'LuaXML_lib' from file  '.\LuaXML_lib.dll: не найден указанный модуль"), т. к. он в сторонней библиотеке и подключить ее никак не удавалось, хотя файл библиотеки сам присутствовал.
Поэтому захотелось побыстрее получить какой-нибудь более-менее рабочий вариант без ошибок.
Требует для работы vcl.dll - подробнее quik2dde.ru/viewtopic.php?id=26
Внимание !!! Эта версия отправляет реальные заявки на биржу 1 лотом фьючерса Сбербанка по ценам bid и offer. Для работы требуется только вписать свой номер счета на FORTS в этой строке - Account="SPBFUTXXXXX". Скрипт лучше останавливать кнопкой "Остановить" из Quik, а не закрывая его окно - так в его работе ошибок не возникало при многократном перезапуске.
Важно! Вероятнее всего, что это скрипт не работает на акциях, т. к. в данном скрипте производится обновление цены до целых чисел, как на фьючерсах. Для округления цена акций до заданной точности необходимо использовать вместо math.floor в строках, подобных этой - bid1 = math.floor (bid) свою функцию округления.

--[[
Описание: простой привод "продать-купить" 1 фьючерс Сбербанка
Версия: 0.0.1
-
Тестирование:
Версия Quik: 6.13.1.11
Дата проверки работы: 04.07.2014
-
Внешние модули/библиотеки:
vcl.dll
-
!!! Внимание !!! Отправляет реальные заявки на биржу
]]

-- Пути для установленного языка Lua
package.cpath=".\\?.dll;.\\?51.dll;C:\\Program Files (x86)\\Lua\\5.1\\?.dll;C:\\Program Files (x86)\\Lua\\5.1\\?51.dll;C:\\Program Files (x86)\\Lua\\5.1\\clibs\\?.dll;C:\\Program Files (x86)\\Lua\\5.1\\clibs\\?51.dll;C:\\Program Files (x86)\\Lua\\5.1\\loadall.dll;C:\\Program Files (x86)\\Lua\\5.1\\clibs\\loadall.dll;C:\\Program Files\\Lua\\5.1\\?.dll;C:\\Program Files\\Lua\\5.1\\?51.dll;C:\\Program Files\\Lua\\5.1\\clibs\\?.dll;C:\\Program Files\\Lua\\5.1\\clibs\\?51.dll;C:\\Program Files\\Lua\\5.1\\loadall.dll;C:\\Program Files\\Lua\\5.1\\clibs\\loadall.dll"..package.cpath
package.path=package.path..";.\\?.lua;C:\\Program Files (x86)\\Lua\\5.1\\lua\\?.lua;C:\\Program Files (x86)\\Lua\\5.1\\lua\\?\\init.lua;C:\\Program Files (x86)\\Lua\\5.1\\?.lua;C:\\Program Files (x86)\\Lua\\5.1\\?\\init.lua;C:\\Program Files (x86)\\Lua\\5.1\\lua\\?.luac;C:\\Program Files\\Lua\\5.1\\lua\\?.lua;C:\\Program Files\\Lua\\5.1\\lua\\?\\init.lua;C:\\Program Files\\Lua\\5.1\\?.lua;C:\\Program Files\\Lua\\5.1\\?\\init.lua;C:\\Program Files\\Lua\\5.1\\lua\\?.luac;"

require "vcl"

-- Раздел настроек (начало)
ClassCode="SPBFUT"    -- класс инструмента - Фьючерсы
SecCode="SRU4"        -- Код инструмента - фьючерс Сбербанка 09.14
Account="SPBFUTXXXXX" -- Счет клиента на FORTS !!! Вписать свой !!!
ClientCode=""
FirmId=""
Trans_ID = 0          -- внутренний счетчик номера заявок
Lots = 1              -- Количество лотов
-- Раздел настроек (конец)

-- Интерфейс (начало)
mainForm = VCL.Form("mainForm")

mainForm.Caption = "Privod ver-0-0-1"
mainForm._= { position="podesktopcenter", height=120, width=150,OnClose = "OnFormClose"}

BuyButton = VCL.Button(mainForm,"Buy")
BuyButton._ = {width=40, height=40, caption="BUY", Top=80, Left=30, onclick = "onBuyClick"}

SellButton = VCL.Button(mainForm,"Sell")
SellButton._ = {width=40, height=40, caption="SELL", Top=80, Left=90, onclick = "onSellClick"}

BidLabel = VCL.Label(mainForm,"Bid")
BidLabel._ = {Top = 40, Left = 15}

OfferLabel = VCL.Label(mainForm,"Offer")
OfferLabel._ = {Top = 10, Left = 16}
-- Интерфейс (конец)

-- Раздел внутренних (не callback) функций (начало)
-- Функция отправки заявок
function SendLimitOrder (ClassCode,SecCode,Operation,OrderPrice,Lots)

Trans_ID = Trans_ID + 1

  local trans = {
          ["ACTION"] = "NEW_ORDER",
          ["CLASSCODE"] = ClassCode,
          ["SECCODE"] = SecCode,
          ["ACCOUNT"] = Account,
          ["OPERATION"] = Operation,
          ["PRICE"] = tostring(OrderPrice),
          ["QUANTITY"] = tostring(Lots),
          ["TRANS_ID"] = tostring(Trans_ID)
                }
  local res = sendTransaction(trans)
  CurrentOrderPrice = OrderPrice
end

--Обработчик кнопки BUY
function onBuyClick(sender)
    if ((qt.bid_count+0 == 0) or (qt.offer_count+0 == 0)) then
      return
    end        
      local bid = qt.bid[qt.bid_count+0].price      
      local bid1 = math.floor (bid)
      SendLimitOrder (ClassCode,SecCode,"B",bid1,Lots)
end

--Обработчик кнопки SELL
function onSellClick(sender)
    if ((qt.bid_count+0 == 0) or (qt.offer_count+0 == 0)) then
      return
    end        
      local offer = qt.offer[1].price      
      local offer1 = math.floor (offer)
      SendLimitOrder (ClassCode,SecCode,"S",offer1,Lots)
end

-- Обработчик закрытия формы
function OnFormClose(Sender, CloseAction)
    is_run = false
    mainForm:Release()
end

function UpdateBidOffer()
-- Функция обновления значений Bid и Offer из стакана
    if is_run == false then
        return
    end    
    qt = getQuoteLevel2(ClassCode,SecCode)
    if qt == nil then               
        return            
    end    
    if ((qt.bid_count+0 == 0) or (qt.offer_count+0 == 0)) then               
        return
    end     
    local bid = qt.bid[qt.bid_count+0].price
    local offer = qt.offer[1].price  
    BidLabel.Caption = "Buy: "..bid.. " (" .. math.floor(qt.bid[qt.bid_count+0].quantity) .. ") " 
    OfferLabel.Caption = "Sell: "..offer.. " (" .. math.floor(qt.offer[1].quantity) .. ") " 
    
end
-- Раздел внутренних (не callback) функций Quik-Lua (конец)

function OnInit()
    mainForm:Show()    
    is_run = true      
       
end

function OnStop()
    is_run = false
    mainForm:Release()
end

function main()   
    while is_run do
        UpdateBidOffer()       
        sleep(50)        
    end    
end

3

Re: Работающие скрипты на Lua

Версия без отправки заявок, при нажатии на кнопки возникает сообщение Quik об эмуляции отправки заявки с указанием торговой операции и цены.

--[[
Описание: простой привод "продать-купить" 1 фьючерс Сбербанка
Версия: 0.0.1em
-
Тестирование:
Версия Quik: 6.13.1.11
Дата проверки работы: 04.07.2014
-
Внешние модули/библиотеки:
vcl.dll
-
!!! Реальные заявки на биржу не отправляются (эмуляция)
]]

-- Пути для установленного языка Lua
package.cpath=".\\?.dll;.\\?51.dll;C:\\Program Files (x86)\\Lua\\5.1\\?.dll;C:\\Program Files (x86)\\Lua\\5.1\\?51.dll;C:\\Program Files (x86)\\Lua\\5.1\\clibs\\?.dll;C:\\Program Files (x86)\\Lua\\5.1\\clibs\\?51.dll;C:\\Program Files (x86)\\Lua\\5.1\\loadall.dll;C:\\Program Files (x86)\\Lua\\5.1\\clibs\\loadall.dll;C:\\Program Files\\Lua\\5.1\\?.dll;C:\\Program Files\\Lua\\5.1\\?51.dll;C:\\Program Files\\Lua\\5.1\\clibs\\?.dll;C:\\Program Files\\Lua\\5.1\\clibs\\?51.dll;C:\\Program Files\\Lua\\5.1\\loadall.dll;C:\\Program Files\\Lua\\5.1\\clibs\\loadall.dll"..package.cpath
package.path=package.path..";.\\?.lua;C:\\Program Files (x86)\\Lua\\5.1\\lua\\?.lua;C:\\Program Files (x86)\\Lua\\5.1\\lua\\?\\init.lua;C:\\Program Files (x86)\\Lua\\5.1\\?.lua;C:\\Program Files (x86)\\Lua\\5.1\\?\\init.lua;C:\\Program Files (x86)\\Lua\\5.1\\lua\\?.luac;C:\\Program Files\\Lua\\5.1\\lua\\?.lua;C:\\Program Files\\Lua\\5.1\\lua\\?\\init.lua;C:\\Program Files\\Lua\\5.1\\?.lua;C:\\Program Files\\Lua\\5.1\\?\\init.lua;C:\\Program Files\\Lua\\5.1\\lua\\?.luac;"

require "vcl"

-- Раздел настроек (начало)
ClassCode="SPBFUT"    -- класс инструмента - Фьючерсы
SecCode="SRU4"        -- Код инструмента - фьючерс Сбербанка 09.14
Account="SPBFUTXXXXX" -- Счет клиента на FORTS !!! Вписать свой !!!
ClientCode=""
FirmId=""
Trans_ID = 0          -- внутренний счетчик номера заявок
Lots = 1              -- Количество лотов
-- Раздел настроек (конец)

-- Интерфейс (начало)
mainForm = VCL.Form("mainForm")

mainForm.Caption = "Privod ver-0-0-1em"
mainForm._= { position="podesktopcenter", height=120, width=150,OnClose = "OnFormClose"}

BuyButton = VCL.Button(mainForm,"Buy")
BuyButton._ = {width=40, height=40, caption="BUY", Top=80, Left=30, onclick = "onBuyClick"}

SellButton = VCL.Button(mainForm,"Sell")
SellButton._ = {width=40, height=40, caption="SELL", Top=80, Left=90, onclick = "onSellClick"}

BidLabel = VCL.Label(mainForm,"Bid")
BidLabel._ = {Top = 40, Left = 15}

OfferLabel = VCL.Label(mainForm,"Offer")
OfferLabel._ = {Top = 10, Left = 16}
-- Интерфейс (конец)

-- Раздел внутренних (не callback) функций (начало)
-- Функция отправки заявок
function SendLimitOrder (ClassCode,SecCode,Operation,OrderPrice,Lots)

Trans_ID = Trans_ID + 1

  local trans = {
          ["ACTION"] = "NEW_ORDER",
          ["CLASSCODE"] = ClassCode,
          ["SECCODE"] = SecCode,
          ["ACCOUNT"] = Account,
          ["OPERATION"] = Operation,
          ["PRICE"] = tostring(OrderPrice),
          ["QUANTITY"] = tostring(Lots),
          ["TRANS_ID"] = tostring(Trans_ID)
                }
  local res = sendTransaction(trans)
  CurrentOrderPrice = OrderPrice
end

--Обработчик кнопки BUY
function onBuyClick(sender)
    if ((qt.bid_count+0 == 0) or (qt.offer_count+0 == 0)) then
      return
    end        
      local bid = qt.bid[qt.bid_count+0].price      
      local bid1 = math.floor (bid)
      local mess = "Эмуляция покупки по цене: " .. bid1
      message(mess,1)
end

--Обработчик кнопки SELL
function onSellClick(sender)
    if ((qt.bid_count+0 == 0) or (qt.offer_count+0 == 0)) then
      return
    end        
      local offer = qt.offer[1].price      
      local offer1 = math.floor (offer)
      local mess = "Эмуляция продажи по цене: " .. offer1
      message(mess,1)      
end

-- Обработчик закрытия формы
function OnFormClose(Sender, CloseAction)
    is_run = false
    mainForm:Release()
end

function UpdateBidOffer()
-- Функция обновления значений Bid и Offer из стакана
    if is_run == false then
        return
    end    
    qt = getQuoteLevel2(ClassCode,SecCode)
    if qt == nil then               
        return            
    end    
    if ((qt.bid_count+0 == 0) or (qt.offer_count+0 == 0)) then               
        return
    end     
    local bid = qt.bid[qt.bid_count+0].price
    local offer = qt.offer[1].price  
    BidLabel.Caption = "Buy: "..bid.. " (" .. math.floor(qt.bid[qt.bid_count+0].quantity) .. ") " 
    OfferLabel.Caption = "Sell: "..offer.. " (" .. math.floor(qt.offer[1].quantity) .. ") " 
    
end
-- Раздел внутренних (не callback) функций Quik-Lua (конец)

function OnInit()
    mainForm:Show()    
    is_run = true      
       
end

function OnStop()
    is_run = false
    mainForm:Release()
end

function main()
    while is_run do
        UpdateBidOffer()       
        sleep(50)        
    end    
end

4

Re: Работающие скрипты на Lua

Немного модифицированный пример из из официального руководства по Qlua - раздел "Сервисные функции" - getInfoParam.
Введен дополнительный несуществующий параметр информационного окна "TEST" и проверка возвращаемых значений на nil или пустое значение.
Важно: каталог для вывода результатов работы скрипта в файл должен существовать, иначе скрипт отработает с ошибкой.
По результатам работы скрипта видно, что некоторые из значений, возвращаемых GetInfoParam пустые, значения nil - отсутствуют.

--[[
Описание: пример из официального руководства по Qlua - раздел "Сервисные функции" - getInfoParam
Версия: 0.0.1
-
Тестирование:
Версия Quik: 6.13.1.11
Дата проверки работы: 07.07.2014
-
Внешние модули/библиотеки:
нет
]]

-- !!! Важно !!! До начала работы скрипта каталог для протокола должен существовать
-- Полный путь к файлу протокола

ProtFilePath = "C:\\Temp\\Lua\\prot\\getinfo.txt"

function main(  )
    params = {"VERSION", "TRADEDATE", "SERVERTIME",
                "LASTRECORDTIME", "NUMRECORDS", "LASTRECORD","LATERECORD",
                "CONNECTION", "IPADDRESS", "IPPORT", "IPCOMMENT",
                "SERVER", "SESSIONID", "USER", "USERID", "ORG", "MEMORY",
                "LOCALTIME", "CONNECTIONTIME", "MESSAGESSENT", "ALLSENT",
                "BYTESSENT", "BYTESPERSECSENT", "MESSAGESRECV", "BYTESRECV",
                "ALLRECV", "BYTESPERSECRECV", "AVGSENT", "AVGRECV",
                "LASTPINGTIME", "LASTPINGDURATION", "AVGPINGDURATION",
                "MAXPINGTIME", "MAXPINGDURATION", "TEST"}
    file = io.open(ProtFilePath, "w+t")
    for key,v in ipairs(params) do
        file:write(v .. " = " .. GetInfoParam(v) .. "\n")
    end
-- Проверка параметров на значение nil или пустое    
        file:write("-------" .. "\n")
        file:write("nil or empty" .. "\n")
        file:write("-------" .. "\n")
    for key,v in ipairs(params) do
        local tmp = GetInfoParam(v)
        if tmp == nil then
        file:write(v .. " = " .. "nil" .. "\n") -- Если значение nil
        end
        if tmp == "" then
        file:write(v .. " = " .. "empty string" .. "\n") -- Если значение пустая строка текста
        end
    end
    file:close()
end