Эта статья начинает серию статей с примерами блоков кода, которые применяются при написании скриптов на QLua(Lua), каждый блок выполняет свою определенную задачу.
С каждой новой статьей блок кода будет усложняться своей функциональностью.
Эти блоки удобно брать и вставлять в свои скрипты, где нужно решить задачу, реализованную в блоке.
Блок кода QLua
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | -- ПОЛУЧЕНИЕ РЕЗУЛЬТАТОВ ВЫПОЛНЕНИЯ ОТПРАВЛЕННОЙ ТРАНЗАКЦИИ -- для примера отправляется транзакция на выставление лимитированной заявки на покупку по определенной цене ACCOUNT = "SPBFUT00k59" -- Код счета CLASS_CODE = "SPBFUT" -- Код класса SEC_CODE = "RIH6" -- Код инструмента OpenPrice = 73000 -- Цена выставления заявки run = true -- Флаг работы цикла while в функции main trans_id = os.time() -- Текущие дата и время в секундах хорошо подходят для уникальных номеров транзакций LastStatus = nil -- Последний статус транзакции, который был выведен в сообщении -- Основная функция скрипта, пока работает эта функция, работает скрипт function main() -- Отправляет транзакцию на открытие позиции TransOpenPos() -- Пока работает данный цикл, работает скрипт while run do sleep(1) end end -- Срабатывает при остановке скрипта function OnStop() run = false end -- Отправляет транзакцию на открытие позиции function TransOpenPos() -- Выставляет заявку на открытие позиции -- Получает ID для следующей транзакции trans_id = trans_id + 1 -- Заполняет структуру для отправки транзакции local Transaction={ ['TRANS_ID'] = tostring(trans_id), -- Номер транзакции ['ACCOUNT'] = ACCOUNT, -- Код счета ['CLASSCODE'] = CLASS_CODE, -- Код класса ['SECCODE'] = SEC_CODE, -- Код инструмента ['ACTION'] = 'NEW_ORDER', -- Тип транзакции ('NEW_ORDER' - новая заявка) ['OPERATION'] = 'B', -- Операция ('B' - buy, или 'S' - sell) ['TYPE'] = 'L', -- Тип ('L' - лимитированная, 'M' - рыночная) ['QUANTITY'] = '1', -- Количество ['PRICE'] = tostring(OpenPrice) -- Цена } -- Отправляет транзакцию local Res = sendTransaction(Transaction) if Res ~= '' then message('TransOpenPos(): Ошибка отправки транзакции: '..Res) else message('TransOpenPos(): Транзакция отправлена') end end -- Функция вызывается терминалом, когда с сервера приходит новая информация о транзакциях function OnTransReply(trans_reply) -- Если пришла информация по нашей транзакции if trans_reply.trans_id == trans_id then -- Если данный статус уже был обработан, выходит из функции, иначе запоминает статус, чтобы не обрабатывать его повторно if trans_reply.status == LastStatus then return else LastStatus = trans_reply.status end -- Выводит в сообщении статусы выполнения транзакции if trans_reply.status == 0 then message('OnTransReply(): Транзакция отправлена серверу') elseif trans_reply.status == 1 then message('OnTransReply(): Транзакция получена на сервер QUIK от клиента') elseif trans_reply.status == 2 then message('OnTransReply(): Ошибка при передаче транзакции в торговую систему. Так как отсутствует подключение шлюза Московской Биржи, повторно транзакция не отправляется') elseif trans_reply.status == 3 then message('OnTransReply(): ТРАНЗАКЦИЯ ВЫПОЛНЕНА !!!') elseif trans_reply.status == 4 then message('OnTransReply(): Транзакция не выполнена торговой системой. Более подробное описание ошибки отображается в поле «Сообщение» (trans_reply.result_msg)') elseif trans_reply.status == 5 then message('OnTransReply(): Транзакция не прошла проверку сервера QUIK по каким-либо критериям. Например, проверку на наличие прав у пользователя на отправку транзакции данного типа') elseif trans_reply.status == 6 then message('OnTransReply(): Транзакция не прошла проверку лимитов сервера QUIK') elseif trans_reply.status == 10 then message('OnTransReply(): Транзакция не поддерживается торговой системой') elseif trans_reply.status == 11 then message('OnTransReply(): Транзакция не прошла проверку правильности электронной цифровой подписи') elseif trans_reply.status == 12 then message('OnTransReply(): Не удалось дождаться ответа на транзакцию, т.к. истек таймаут ожидания. Может возникнуть при подаче транзакций из QPILE') elseif trans_reply.status == 13 then message('OnTransReply(): Транзакция отвергнута, так как ее выполнение могло привести к кросс-сделке (т.е. сделке с тем же самым клиентским счетом)') end end end |
Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!
Добрый день! Посмотрел комментарии, был вопрос о переносе заявки, но для переноса лимитной заявки такой код не срабатывает. Может кто-то использовал в своей практике подобные вещи? Пробовал некоторые параметры, но все равно не срабатывает. Как я понимаю, при выставлении лимитной заявки с критериями переноса и до какой даты, должно заполниться поле "Код биржи" в таблице заявок.
Параметр "time_sek" в формате: ггггммдд, 20210218
Здравствуйте, Василий, самый простой способ разобраться с полями - это использовать таблицу "Карман транзакций", открыть ее можно: "Создать окно" - "Все типы окон" - Прочее - "Карман транзакций"
Добавьте в нее нужную Вам транзакцию, затем кликните по ней правой кнопкой мыши и выберите пункт "Сохранить транзакции в tri-файл"
Откройте получившийся файл и посмотрите какие там поля и какие значения, функция sendTransaction() позволяет отправлять таблицы транзакций как с англоязычными названиями полей, так и с русскими, хоть вперемешку. Можно при помощи этой функции отправить все содержимое этого tri-файла одной строкой
Дмитрий, спасибо огромное!!!
Всегда пожалуйста 🙂
Дополню комментарий, может кому пригодится.
Через скрипт qlua можно отправить лимитную заявку с англоязычными названиями полей, но только без переноса через клиринг.
Если необходимо переносить лимитную заявку до какой либо даты, то в коде нужно использовать русскоязычное название полей, а также их значений, исключение составляют лишь некоторые поля и значения.
Добрый день! Не подскажите почему не работает условие снять остаток?
sell = {
["EXECUTION_CONDITION"] = "KILL_BALANCE",
["CLASSCODE"] = tostring(p_classcode),
["SECCODE"] = tostring(p_seccode),
["ACCOUNT"] = tostring(p_account),
["CLIENT_CODE"] = tostring(p_account),
["ACTION"]="NEW_ORDER",
["TYPE"]="L",
["OPERATION"]="S",
["QUANTITY"]= tostring(lots),
["PRICE"]=tostring(priceSell),
["TRANS_ID"]="2"
}
result = sendTransaction(sell)
Пробовал и через робот запускать и вручную в терминале. Заявка выставляется и тут же снимается. А по идее должен сниматься только не исполненный остаток.
Подскажите, как узнать/установить поле заявки "Переносить заявку".
Такой вариант пройдет:
?
Да, точно не помню, но, вроде бы, должно сработать
["EXPIRY_DATE"] = "GTC"
«GTC» – до отмены либо Дата в формате «ггггммдд», где «гггг» – год, «мм» – месяц, «дд» – день.
Это верно для стоп-заявки. Для лимитки так не получится.
Здравствуйте. Почему-то не отправляется транзакция, никак не могу найти, в чём причина. Вот код:
Измените запись в лог ошибки транзакции, там будет написано что не так:
или просто message('Ошибка: '..res)
Доброе время суток. А как можно вывести на терминал что-то типа окошка например с 2-мя кнопками "ДА" "НЕТ", ну и дальше действовать, в зависимости от нажатия
Здравствуйте, для этого можно создавать QLua-таблицу с 2-мя кнопками, пример работы с таблицами можете посмотреть здесь: https://quikluacsharp.ru/quik-qlua/primer-skripta-qlua-lua-vypolnyayushhego-torgovye-operatsii-v-terminale-quik/
Спасибо, работа кипит круглосуточно :))
Пожалуйста 🙂
Добрый день!
Пытаюсь колбеки транзакций записывать в файл - но пропадают некоторые из них. Я отправляю сразу 10 тестовых заявок, из них записываются 8-9
Вот код
Если запись в файл поставить в OnTransReply, то все колбеки записываются
Добрый день! Это происходит из-за смещения индексов массива при удалении в цикле. Самый простой вариант, ничего не удалять из массива, а запоминать индекс последней обработанной транзакции при завершении цикла for и при следующей итерации цикла while начинать чтение массива со следующего по счету индекса, тогда Вы не пропустите ничего.
Понятно) Спасибо большое!!
Пожалуйста! Есть еще такой вариант:
Вроде бы тоже должен работать
Заработало!!)) Спасибо!!
Всегда пожалуйста!
Что-то вы перемудрили, вот так проще:
Перебирайте таблицу с конца и не парьтесь на счет всяких там индексов
for i=1, #queu, -1 do
line=tostring(queue[i].trans_id)..";"..tostring(queue[i].status)..";"..tostring(tonumber(queue[i].order_num))..";"..tostring(queue[i].brokerref)..";"..tostring(queue[i].result_msg)..";".."\n";
table.sremove(queue,i);
f:write(line);
f:flush();
end;
t = {
["TRANS_ID"]=10,
["CLASSCODE"]=SPBFUT,
["SECCODE"]=BRH18,
["ACTION"]="NEW_ORDER",
["ACCOUNT"]=SPBFUTJRcwz,
["TYPE"]="L",
["OPERATION"]=B,
["QUANTITY"]=1,
["PRICE"]=66.8,
}
res=sendTransaction(t)
message(res,1)
Quik выдает ошибку - неверный идентификатор транзакции, перепробовал все начиная от времени системы в "транс ИД" до произвольных чисел.
["QUANTITY"] - вот так нет нужды писать, ну если начётно известно имя поля
Все значения таблицы t должны быть строками, а у вас цифры и какие-то переменные: BRH18, SPBFUTJRcwz - чему они равны?
Вот так будет правильно:
t_id = 10
price = 66.8
scode = "BRH18"
t = {
TRANS_ID=tostring(t_id ),
CLASSCODE="SPBFUT",
SECCODE=scode,
ACTION="NEW_ORDER",
ACCOUNT="SPBFUTJRcwz",
TYPE="L",
OPERATION="B",
QUANTITY="1",
PRICE=tostring(price),
}
res=sendTransaction(t)
message(res,1)
кавычки забыл)понял)) спасибо, что-то заглупил сильно))
Бывает)
Почему то ругается на кол-во знаков после запятой, машина думает что я указываю 67.420000
Когда как указываю 67.42
Разобрался)