Имеем следующий код (только отрывок который интересует, функции отправки и снятия заявок - 100% рабочие, проверено):
Дело в том, что заявка выставляется и попадает в систему, но следующая за выставлением заявки функция отмены всех заявок не отрабатывает, я так понимаю, потому что заявка ещё не попала в таблицу квика по скорости. Если функцию отмены перенести в колбэк OnOrder - она снимется.
При тесте,что до запуска скрипта уже есть активные заявки, снимаются все, кроме только что отправленной.
Вопрос - есть возможность как-то быстро снять заявку только-что выставленную? или придется ждать завершения всего кода в OnParam, только после этого отработает OnOrder и я смогу её снять?
Код
function OnParam (class, sec)
.......
if Delta > 0.9 and CurentActiveOrder.image == "Wait" then
--Отправляем заявку
local id,ms = sendLimit(class,sec,"S",string.format(AUCTPRICE),1,account,client_code,"Коммент")
--Помещаем в ячейку необходимую фразу
tbl:SetValue(line_count_table[sec],'ЕстьЗаявка', string.format("Active"))
--Тут же отменяем все заявки
local trid,ms = killAllOrders(nil)
end
Так же следует отметить, выставление заявки происходит при выполнении условия, вообще ячейку таблицы с "Wait" на "Active" я хотел меня в OnOrder, где флаг заявки бы указывал на то, что она активна, но пока приходит ответ от OnOrder OnParam успевает выставить порядка 4х заявок, тоже беда :(
Что делает функция killAllOrders? Если перебирает данные в таблице заявок, то да, пока заявка там не появится функция естественно ее не увидит. То что заявка появляется не в момент отправки транзакции, это нормально, ведь даже у света есть скорость. Как вариант, можно ловить ответ на транзакцию в OnTransReply и отправлять транзакцию на снятие там.
Вся моя проблема в том, что OnParam может прийти несколько раз по одному и тому же инструменту, когда OnOrder только раз. Проблему нескольких приходов решил с помощью добавления новой колонки таблицы и записи туда переменных, как в коде, но может возникнуть вот такая проблема, как можете посоветовать её решить? :(
--Функция выполнилась, транзакция отправлена, переменная "а" меняется на "Активна", но заявка ещё не пришла
1. Функция OnParam
Если а == "ждать" тогда
ОтправитьТранзакцию
а = "Активна"
ИначеЕсли а == "Активна" Тогда
НайтиТранзакцию
Отменить
ОтправитьНовуюТранзакцию
Конец
--Переменная "а" уже "Активна", но функция "НайтиТранзакцию" её не найдет
2. Функция OnParam Если а == "ждать" тогда
ОтправитьТранзакцию
а = "Активна"
ИначеЕсли а == "Активна" Тогда
НайтиТранзакцию
Отменить
ОтправитьНовуюТранзакцию
Конец
В таком ключе OnTransReply быстрее отработает?
Сергей,подскажите, у отправленной транзакции есть мой уникальный ID, можно ли отследить данную транзакцию и успеть её отменить до того как она улетела на биржу? Какие варианты может принимать аргумент ACTION="NEW_ORDER" в транзакции?
Надо строить робота на основе событийной модели, тогда таких проблем не будет. Т е робот - это конечный автомат, который полностью описывается набором его состояний. Поэтому надо фиксировать эти состояния и программировать условия перехода из одного состояния в другое.
Николай Камынин написал: Надо строить робота на основе событийной модели, тогда таких проблем не будет. Т е робот - это конечный автомат, который полностью описывается набором его состояний. Поэтому надо фиксировать эти состояния и программировать условия перехода из одного состояния в другое.
Я с Вами полностью согласен, но в lua нет событийности, всё зависит от стека функций об.вызова, как они придут и потока всего два и основной стек находится в одном потоке.
Sergey Gorokhov, может мне использовать цикл while внутри onParam? Сделать какую-нибудь переменную в значение false и, если транзакция прошла, ждать пока не появится заявка в таблице с флагом активна?
Или она не прилетит в таблицу пока OnParam не закончится?
Александр Правилов написал: Сергей,подскажите, у отправленной транзакции есть мой уникальный ID, можно ли отследить данную транзакцию и успеть её отменить до того как она улетела на биржу?
Как Вы себе это представляете? отправить транзакцию на отмену быстрее чем транзакцию на выставление? Скорость транзакции никак контролировать нельзя.
Цитата
Александр Правилов написал: Какие варианты может принимать аргумент ACTION="NEW_ORDER" в транзакции?
Посмотрите документацию на терминал QUIK, "Раздел 6. Совместная работа с другими приложениями" - "6.11 Импорт транзакций"
Цитата
Александр Правилов написал: может мне использовать цикл while внутри onParam?
Sergey Gorokhov, дело в том, что не обязательно транзакция должна отмениться сразу, оно может должна отмениться в следующий раз
К примеру
Условие: если b > c тогда отправить транзакцию, если c > b тогда отменить (b,c -какие то параметры бумаги)
Стек вызовов: OnParam OnParam OnTransReply
Код
-- OnParam - Отправилась транзакция
b = 5, c =3
Если b > c Тогда
ОтправитьТранзакцию (Цена = B)
ИначеЕсли c > b Тогда
ОтменитьАктивнуюТранзакцию
ОтправитьТранзакцию( Цена = С)
--2. OnParam - Меняется b и c, а транзакция ещё не дошла
b = 3, c =5
Если b > c Тогда
ОтправитьТранзакцию (Цена = B)
ИначеЕсли c > b Тогда
ОтменитьАктивнуюТранзакцию -- Отменять нечего и выставится ещё одна заявка (задвоится)
ОтправитьТранзакцию( Цена = С)
--3. OnTransReply -- По сути уже не нужна
Николай Камынин написал: Надо строить робота на основе событийной модели, тогда таких проблем не будет. Т е робот - это конечный автомат, который полностью описывается набором его состояний. Поэтому надо фиксировать эти состояния и программировать условия перехода из одного состояния в другое.
Я с Вами полностью согласен, но в lua нет событийности, всё зависит от стека функций об.вызова, как они придут и потока всего два и основной стек находится в одном потоке.
Именно библиотека QLUA и дает Вам механизм событий в виде колбеков, что принципиально отличает ее от QPILE. Состояние же робота необходимо хранить в таблице состояний - это уже особенности алгоритма. Луа позволяет все это сделать.
Николай Камынин, не согласен с вами, колбэками управлять нельзя, они приходят как приходят, посмотрите мой пример выше, как разрулить эту ситуацию?
Sergey Gorokhov, Сергей, подскажите другой момент, что то не получается получить таблицу заявок, в чем может быть ошибка?
в row=getItem("orders",i) пишет - improperly formatted XML data
Код
for i=1,getNumberOf("orders") do
local row=getItem("orders",i)
if row ~= nil and row[sec_code]==sec then
local trid,ms = killOrder(row[order_num],sec,class)
if trid ~= nil then
tbl:SetValue(line_count_table[sec],'ÅñòüÇàÿâêà', string.format("Cancel"))
tbl:SetValue(line_count_table[sec],'ÖåíàÇàÿâêè', string.format("0"))
end
end
end
Александр Правилов написал: Николай Камынин , не согласен с вами, колбэками управлять нельзя, они приходят как приходят, посмотрите мой пример выше, как разрулить эту ситуацию?
А где Я Вам говорил, что колбеками надо управлять(ужас какой-то). Колбеки - это функции, которые вызываются системой ( в данном случае тарминалом КВИК) при наступлении определенного события. Т е они сообщают вам о событиях в КВИКЕ и ВСЕ. --------------------- Когда робот отсылает заявку - то он переходит из состояния - "послать" в состояние - "ждать ответа". А у Вас нет этих состояний т е Вашему роботу все по... Вот он у вас и шлет кучу заявок и ничего не ждет. Ну как-то так получается...
Александр Правилов написал: в row=getItem("orders",i) пишет - improperly formatted XML data
В интернете говорят что проблема может быть из за кодировки Файл скрипта должен быть строго в ANSI, а по Вашему примеру кода видно что у Вас это не так.
Александр Правилов написал: Николай Камынин , не согласен с вами, колбэками управлять нельзя, они приходят как приходят, посмотрите мой пример выше, как разрулить эту ситуацию?
Sergey Gorokhov , Сергей, подскажите другой момент, что то не получается получить таблицу заявок, в чем может быть ошибка?
в row=getItem("orders",i) пишет - improperly formatted XML data
Код
for i = 1 , getNumberOf ( "orders" ) do
local row = getItem ( "orders" ,i)
if row ~ = nil and row[sec_code] = = sec then
local trid,ms = killOrder(row[order_num],sec,class)
if trid ~ = nil then
tbl: SetValue (line_count_table[sec],'ÅñòüÇàÿâêà', string.format ( "Cancel" ))
tbl: SetValue (line_count_table[sec],'ÖåíàÇàÿâêè', string.format ( "0" ))
end
end
end
Николай Камынин, если с кодировкой что-то не то, почему остальной код работает? Николая, подскажите кучочек кода, как перевести в состояние ожидания ответа по заявке?
is_run = true
function main()
for i=1,getNumberOf("orders") do
local row=getItem("orders",i)
local row=getItem("trades",i)
end
end
function OnStop(s)
is_run = false
message ("fr", 2)
end
Sergey Gorokhov,выяснил такой момент, за пятницу было 16 заявок, getItem("orders",i) отрабатывает когда заявка была исполнена, если снята, то показывает ошибку xml
Александр Правилов, Вы читали ссылку которая приведена выше? Там ведь тоже была речь про decoda Может быть стоит взглянуть на описанные там рекомендации.
Sergey Gorokhov, какой среду разработки вы могли бы порекомендовать?
Да, я переходил по ссылке, но её уже не существует, вылетает просто на форум.
Не соглашусь в этом плане относительно decod'a, ибо я в режиме онлайн могу запросить вместо заявок - сделки и всё будет ок. и если я в режиме онлайн игнорируя эту ошибку пропишу через точку row.order_num к примеру, число выдастся, поэтому в принципе работать можно
Александр Правилов написал: Sergey Gorokhov, какой среду разработки вы могли бы порекомендовать?
Ту, в которой Вам будет удобно.
Цитата
Александр Правилов написал: Да, я переходил по ссылке, но её уже не существует, вылетает просто на форум.
Ссылка работает, специально проверили на разных компьютерах. У Вас что то не так с браузером?
Цитата
Александр Правилов написал: Не соглашусь в этом плане относительно decod'a, ибо я в режиме онлайн могу запросить вместо заявок - сделки и всё будет ок. и если я в режиме онлайн игнорируя эту ошибку пропишу через точку row.order_num к примеру, число выдастся, поэтому в принципе работать можно
Александр Правилов написал: Николай Камынин , если с кодировкой что-то не то, почему остальной код работает? Николая, подскажите кучочек кода, как перевести в состояние ожидания ответа по заявке?
Общий подход работы робота на основе событийной модели следующий. ------------------------ В начале описываете таблицу возможных состояний робота. Например у меня есть таблица состояния заявок, таблица состояния стоп-заявок ну и т д. Эти таблицы в отличии от таблиц квика содержат лишь активные заявки. ------------------------------------------- Когда посылаете заявку то пишите в конец таблицы запись о том что послали заявку в систему Когда собираетесь послать заявку то проверяете состояние последней записи в таблице состояния заявок Если там указано что заявка отправлена брокеру ( т е еще нет подтверждения что она на бирже) то пропускаете отправку новой. ----------------------------- Ну и т д
Sergey Gorokhov,можно ли в колбэке OnParam указать код, который поставит OnParam в ожидание прихода другого события, например OnTransReply? Можно ли хоть как-то добиться асинхронности колбэков или какой-нибудь "псевтоасинхронности". на гл.странице сайта квика есть пример, где отправляется транзакция и отслеживается, но там сделано хитро, транзакция отправляется в main, там то понятно, разные потоки, main работает и параллельно приходят колбэки. А как быть если отправить в OnParam?
немного нашел информацию про event, якобы ожидает прихода события, может есть что-то подобное?
Николай Камынин,Да дело не в таблице состояний, это не то. Этот способ режет скорость. После отправки транзакции в OnParam есть ещё код и пока этот код не выполнится, не придет ответ от OnTransReply и OnOrder, а надо получить ответы еще при выполнении кода в OnParam.
Если Вы остановите колбек, то у Вас зависнет терминал. Именно потому что колбеки идут в одном потоке терминала QUIK и никак это изменить нельзя. Решение - выставить ожидание в main, а в колбеках использовать флаги, которые будут влиять на поведение цикла в main
Александр Правилов написал: Николай Камынин ,Да дело не в таблице состояний, это не то. Этот способ режет скорость. После отправки транзакции в OnParam есть ещё код и пока этот код не выполнится, не придет ответ от OnTransReply и OnOrder, а надо получить ответы еще при выполнении кода в OnParam.
Пока исполняется OnParam никакие новые данные с сервера не могут быть обработаны. Поэтому НЕВОЗМОЖНО находясь в onParam получить ответ OnTransReply и OnOrder, Полагаю Вы это поняли. ----------------------------
Николай Камынин, в этом то самая и большая проблема, в невозможности получить ответ, пока не закончится OnParam или не подождать в OnParam, к примеру через event.timer или event.pull, могу ошибаться. Ну да ладно, что-нибудь придумаю, благо для текущего алгоритма, скорость не является приоритетной.
Александр Правилов написал: в этом то самая и большая проблема, в невозможности получить ответ, пока не закончится OnParam или не подождать в OnParam, к примеру через event.timer или event.pull, могу ошибаться.
Да не в этом проблема. А в неверном построении алгоритма. Николай уже неоднократно обращал на это внимание, но посыл не доходит.
Еще раз: не нужно в callback-функциях что-то делать и чего-то ждать. это тормозит терминал. Максимум нужно выставить флаги или признаки, и выйти. А уже основной цикл внутри main() эти флаги должен обнаружить и принять какие-то решения.
Александр Правилов написал: Николай Камынин , в этом то самая и большая проблема, в невозможности получить ответ, пока не закончится OnParam или не подождать в OnParam, к примеру через event.timer или event.pull, могу ошибаться. Ну да ладно, что-нибудь придумаю, благо для текущего алгоритма, скорость не является приоритетной.
Вы очевидно не понимаете, что это в принципе невозможно в КВИК, так как принятый ответ обрабатывается в том же потоке, где работает функция OnParam. т е ядро процессора (поток) занят этой функцией и обработка новых данных будет после ее завершения. а других потоков для обработки новых данных в КВИКЕ не выделяется т е это так сделан КВИК. Поэтому, если очень хочется, то надо отказываться от КВИК и подключаться прямо к бирже.
есть два варианта ускорить прием ответа. 1) отказаться от onParam 2) во всех колбеках поставить запуск новых потоков и выход из колбека В этом случае будет максимально быстро выходить из OnParam и др колбеков.
Николай Камынин, как можно организовать второй вариант? Есть какая-нибудь рекомендуемая литература? От OnParam не откажусь, не нашел альтернативы в получении специфических параметров.
Imersio Arrigo, где в main нужно организовывать очередной цикл для поддержания работы скрипта? Ну как то тоже не интересно.
Николай Камынин, да я уже понял, что квик так сделан, и уже принял неизбежность формирования таблицы необходимых мне состояний, просто всё это увеличит кол-во проверяемых условий и общую нагрузку на объем кода.
Предложу свои решения. 1. Возможно Вам подойдет задание особых параметров заявки - Fill or kill или Kill balance, которые в случае неисполнения уничтожаются автоматически. 2. У меня каждая заявка / позиция выставляется с формированием уникальной для него таблицы с несколькими полями, куда записываются уникальный идентификатор транзакции, номер заявки на сервери биржи и другие параметры, например placed = true - если получен "положительный" (status = 3) отклик в OnTransReply. Там же фильтруются и вторичные отклики: инфа о полученных откликах сохраняется, если вновь приходит сообщение с тем же номером заявки, что уже приходил ранее, оно игнорируется как повторное. Конструкция сложная, но неизбежная в нашей ситуации
Иван Ру, спасибо, я уже понял, что доп.таблицы мне не избежать, буду продумывать как это всё лучше организовать. Kill balance это снятие заявки, если выполнена частично?
Sergey Gorokhov, с помощью функции getNumberOf нельзя получить количество строк в созданной скриптом таблице? Сначала показалось, что работает, но видимо показалось :(
Таблица создается, выводится, заполняется (относительно работы с таблицей внешняя библиотека норм работает)
В сount всегда -1
Код
require"QL"
is_run = true
tblord=QTable:new()
tblord:SetCaption('Таблица')
tblord:AddColumn('Security_',QTABLE_STRING_TYPE,15)
tblord:AddColumn('NameStock_',QTABLE_STRING_TYPE,50)
tblord:Show()
function main()
while is_run do
line=tblord:AddLine()
rand2 = random(1,1000)
tblord:SetValue(line,'Security_', rand2 )
tblord:SetValue(line, 'NameStock_', rand2)
count = getNumberOf("tblord")
sleep(500)
end
end
Александр Правилов написал: Иван Ру , спасибо, я уже понял, что доп.таблицы мне не избежать, буду продумывать как это всё лучше организовать. Kill balance это снятие заявки, если выполнена частично?