1

Тема: Странности при выполнении скрипта qlua в quik

Всех приветствую, ребята подскажите в чем может быть проблема - вообщем только начал изучать Qlua и создание скриптов на нем для квика, создал для начала пробный скрипт
по простой схеме -

IsRun = true;
function main()
while is_run do
       sleep(50)
   end;

end;

function ontrade (trade_data)

file = io.open("res_ontrade.txt", "a")
   
   for key,v in pairs(trade_data) do
   file:write(key .. " = " ..tostring(v).. "\n")
   end
   file:close()

end
function OnStop()
  IsRun = false;
end;

в тело функции ontrade прописал простенький скрипт для записи результата выполненной сделки в текстовый файл но тут происходит странное - в случае совершения сделки, т.е. одной сделки любой сделки, покупка продажа - запись результатов происходит трижды, много раз перепробовал все одно и то же - сделка одна и три одинаковых записи подряд о ней, почему так?

2 (2018-12-26 20:15:16 отредактировано Kolossi)

Re: Странности при выполнении скрипта qlua в quik

Вы обрабатываете вызов OnTrade(trade_data) не проверяя номера заявки?
Пропишите в переменную идентификатор транзакции, который вы будете передавать в заявке.
Потом, при отправке транзакции вы получите ответ в функции OnTransReply(trans_reply) где по идентификатору транзакции узнаете номер заявки.  А уж потом в OnTrade(trade_data) найдете свою  исполненную заявку по ее номеру.

К стати, trade_data в этой функции таблица, а не переменная wink

3

Re: Странности при выполнении скрипта qlua в quik

Kolossi пишет:

Вы обрабатываете вызов OnTrade(trade_data) не проверяя номера заявки?
К стати, trade_data в этой функции таблица, а не переменная wink

Вроде как по моему коду сразу видно что trade_data я обрабатываю как таблицу

4 (2018-12-26 22:50:02 отредактировано Kolossi)

Re: Странности при выполнении скрипта qlua в quik

Nordman пишет:
Kolossi пишет:

Вы обрабатываете вызов OnTrade(trade_data) не проверяя номера заявки?
К стати, trade_data в этой функции таблица, а не переменная wink

Вроде как по моему коду сразу видно что trade_data я обрабатываю как таблицу

Пардон, кроме записи в файл, я никакой обработки не заметил.
Посмотрите поля trade_data["order_num"] и trade_data["trade_num"]
Ну и мы понимаем конечно, что функция вызывается по каждой сделке с таким order_num до исполнения заявки.

5

Re: Странности при выполнении скрипта qlua в quik

Kolossi пишет:

Пардон, кроме записи в файл, я никакой обработки не заметил.
Посмотрите поля trade_data["order_num"] и trade_data["trade_num"]
Ну и мы понимаем конечно, что функция вызывается по каждой сделке с таким order_num до исполнения заявки.

Что тут незаметного key,v in pairs( ) - это ведь обработка элементов таблицы, впрочем неважно
Вообщем ни черта не пойму - добавил в свой скрипт еще функции OnOrder и OnTransReply

function OnOrder (neworder)
ordn=neworder.order_num
end

function OnTransReply (transorder)
if transorder.order_num == ordn then
    tnsid = transorder.trans_id
end
end

function OnTrade(trade_data)
if trade_data.trans_id  == tnsid then
....

OnOrder вызывается ведь при отправке заявки в систему правильно? В ней я узнаю номер заявки order_num
OnTransReply вызывается как ответ систему на получение заявки и происхождении любых событий с ней - правильно?
Получаю пользовательский идентификатор транзакции tnsid = transorder.trans_id

и уже в функции OnTrade сверяю идентификатор транзакции с полученным из OnTransReply
Так получается надо делать? Вообще не работает так у меня, что то неправильно
и вообще нехитрым способом я проверил что происходит, передалал скрипт примерно таким образом

function Oninit ()
n=0
end

function OnOrder (neworder)

        file = io.open("C:\\FinamJunior\\logs\\res_onorder.txt", "a")
      n=n+1
    file:write(tostring (n).."\n")
    file:close()

end

function OnTransReply (transorder)

        file = io.open("C:\\FinamJunior\\logs\\res_ontransreply.txt", "a")
        n=n+1
    file:write(tostring (n).."\n")
    file:close()

end

function OnTrade(trade_data)

        file = io.open("C:\\FinamJunior\\logs\\res_ontrade.txt", "a")
        n=n+1
    file:write(tostring (n).."\n")
    file:close()

end

Далее делаю следующее - формирую завку на покупку одного лота некоторых акций по рыночной цене, чтобы заявка быстро была выполнена, и отправляю ее и вижу следующий результат:
функция OnTrade выполняется первой, причем три раза, в файле res_ontrade.txt  я увидел 1 2 3
Затем выполняется два раза функция OnOrder, два раза - в res_onorder.txt я увидел 4 5
Функция OnTransReply вообще не была выполнена ни разу - в файле res_ontransreply.txt  пусто

6 (2018-12-27 11:06:42 отредактировано Kolossi)

Re: Странности при выполнении скрипта qlua в quik

Попробуйте выставить заявку вот так:

function Trade(a_oper,a_count,a_price,p_TRANS_ID) -- (направление, количество, прайс, идентификатор)
    if a_count>0 and a_price>0 then
        --посылаем заявку
        local ton = {
                ["CLASSCODE"]=p_classcode,
                ["SECCODE"]=p_seccode,
                ["ACTION"]="NEW_ORDER",
                ["ACCOUNT"]=p_account,
                ["CLIENT_CODE"]=p_clientcode,
                ["TYPE"]="L",
                ["OPERATION"]=a_oper,
                ["QUANTITY"]=tostring(a_count),
                ["PRICE"]=tostring(a_price),
                ["EXPIRY_DATE"]="GTC",
                ["TRANS_ID"]=p_TRANS_ID
            }
        local res=sendTransaction(ton)
        if res == "" then
            messages("Send = "..tostring(a_count),1)
        else
            messages("Error = "..res,1)
        end
    end
end

В идентификатор - любое число, например = 5, направление "S" или "B"

потом ответ на транзакцию

function OnTransReply(trans_reply)
    local id=tostring(trans_reply["trans_id"]) -- идентификатор транзакции
    --если это наша транзакция, обработаем ее
    if id==p_TRANS_ID then
        local nord=trans_reply["order_num"] --номер заявки
        if nord==nil or nord==0 or nord=="0" then
                messages(p_seccode.." Order do not receive ",1)
        else
            order_num=nord
        end
    end
end

  Дальше в onTrade(trade) проверяете    

if trade["order_num"]==order_num then -- это Ваша сделка

есть еще один косяк в onTrade, о котором я расскажу потом

7

Re: Странности при выполнении скрипта qlua в quik

Сравнил сейчас резльтаты выгрузки таблиц OnOrder (neworder) и OnTrade(trade_data) в файл
Таблицы neworder отличаются значениями withdraw_datetime, datetime и uid, причем 1ый uid=0 а второй uid = 132894
Таблицы trade_data отличаются значениями canceled_datetime  (Какой тут может быть canceled_datetime? заявка ведь выполнена) и datetime

8 (2018-12-27 11:43:35 отредактировано Kolossi)

Re: Странности при выполнении скрипта qlua в quik

Nordman пишет:

Сравнил сейчас резльтаты выгрузки таблиц OnOrder (neworder) и OnTrade(trade_data) в файл
Таблицы neworder отличаются значениями withdraw_datetime, datetime и uid, причем 1ый uid=0 а второй uid = 132894
Таблицы trade_data отличаются значениями canceled_datetime  (Какой тут может быть canceled_datetime? заявка ведь выполнена) и datetime

OnTrade иногда запускается чужой заявкой, видимо это ваш случай.

Если вы получили из OnOrder(neworder) номер заявки  x=neworder["order_num"] ,
то ваша OnTrade(trade_data) только та, где trade_data["order_num"]==x

9 (2018-12-27 11:48:46 отредактировано Nordman)

Re: Странности при выполнении скрипта qlua в quik

Kolossi пишет:

Попробуйте выставить заявку вот так:

function Trade(a_oper,a_count,a_price,p_TRANS_ID) -- (направление, количество, прайс, идентификатор)

есть еще один косяк в onTrade, о котором я расскажу потом

Спасибо за помощь но что же тогда делать с ручной формировкой заявок - иногда и вручную хочется, и самое главное надо бы знать почему на выполнение одной заявки на покупку одного лота приходит три ответа с разным временем? можно конечно отсечь дубликаты но вдруг иногда эти дубликаты будут иметь какое то значение?

Вообщем пока решил проблему так:

function OnInit ()
ordn=0
tr=0
end

function main()
    while is_run do
       tr=0
       ordn=0
       sleep(1000)
    end;

function OnOrder (neworder)

if ordn==0 then
ordn=neworder.order_num
....
end

function OnTrade(trade_data)
   
if tr~=0 then return end
    if tr ==0 then
    tr=trade_data.trade_num
...
end


И что за косяк? Можно сразу?

10

Re: Странности при выполнении скрипта qlua в quik

Nordman пишет:

И что за косяк? Можно сразу?

Иногда, (редко, но бывает) приходит оnТrade(trade) чужой заявки с вашим order_num.

Я выкрутился, проверяя номер сделки trade["trade_num"], что бы эти номера шли по возрастанию.

11

Re: Странности при выполнении скрипта qlua в quik

Kolossi пишет:
Nordman пишет:

И что за косяк? Можно сразу?

Иногда, (редко, но бывает) приходит оnТrade(trade) чужой заявки с вашим order_num.

Может достаточно сверять параметры выполненной сделки по USERID? Он ведь для каждого пользователя должен быть уникальным я так понимаю
getInfoParam("USERID")
Можно еще и по client_code тоже
И тогда получается достаточно будет отсеивать точно такие же ответы от сервера по этой сделке с моим USERID
и client_code?

Кстати все три ответа по Ontrade и два по OnOrder у меня приходят c моим uid (USERID)
да и все остальные параметры одинаковые кроме datetime canceled_datetime и withdraw_datetime.
Видимо это какой то глюк на сервере, или может неизвестный нам технический нюанс

12 (2018-12-28 14:20:48 отредактировано Kolossi)

Re: Странности при выполнении скрипта qlua в quik

Да вариантов много разных.
Суть того, что применяю я - если номер сделки не больше, чем предыдущий значит это дубль и эта сделка уже обработана.   Почему номер сделки ? Да потому, что на одну заявку, которая больше одного лота, может реально пройти несколько сделок, которые нужно обработать и отсеять дубли и прочий мусор.  Естественно, что большинство параметров в этих сделках будут одинаковы.

13

Re: Странности при выполнении скрипта qlua в quik

Ясно спасибо, ну и то есть если как я говорю - фильтровать приходящие ответы от сервера по USERID это даст гарантию отсева случайных ответов на чужие заявки как выговорите что изредка такое случается? На чужую заявку ответ ведь должен быть с USERID другого трейдера

14

Re: Странности при выполнении скрипта qlua в quik

Kolossi пишет:
Nordman пишет:

И что за косяк? Можно сразу?

Иногда, (редко, но бывает) приходит оnТrade(trade) чужой заявки с вашим order_num.

Я выкрутился, проверяя номер сделки trade["trade_num"], что бы эти номера шли по возрастанию.

Не бывает такого и быть априори не может, а вот что для каждой новой сделке приходит 3 события - факт, по этому при первой обработке запоминаем:
mytrades = {}
if  mytrades[trade_num] then return end -- обработана
  // обработка события сделки //
  mytrades[trade_num] = true
end
Для новых заявок приходит 2 события или одно, принцип тот же, но нужна проверка по балансу - если не поменялся то второй раз не считать

15

Re: Странности при выполнении скрипта qlua в quik

kalikazandr пишет:
Kolossi пишет:
Nordman пишет:

И что за косяк? Можно сразу?

Иногда, (редко, но бывает) приходит оnТrade(trade) чужой заявки с вашим order_num.

Я выкрутился, проверяя номер сделки trade["trade_num"], что бы эти номера шли по возрастанию.

Не бывает такого и быть априори не может, а вот что для каждой новой сделке приходит 3 события - факт, по этому при первой обработке запоминаем:
mytrades = {}
if  mytrades[trade_num] then return end -- обработана
  // обработка события сделки //
  mytrades[trade_num] = true
end
Для новых заявок приходит 2 события или одно, принцип тот же, но нужна проверка по балансу - если не поменялся то второй раз не считать

Те же шары, только в профиль.
У меня примерно так:
mytrades = {}
mytrades[trade_num]=0
...
if  mytrades[trade_num]==trade_data[trade_num] then return end -- обработана
  // обработка события сделки //
  mytrades[trade_num]=trade_data[trade_num]
end

16 (2018-12-29 15:38:14 отредактировано Nordman)

Re: Странности при выполнении скрипта qlua в quik

kalikazandr пишет:

но нужна проверка по балансу - если не поменялся то второй раз не считать

И как раз подскажите пожалуйста:
1. Как проверить баланс, то есть чистый остаток денежных средств не учитывая стоимости ценных бумаг и прочих  активов, почитал мануал по Qlua -
   Функция getMoney (STRING client_code, STRING firmid, STRING tag, STRING currcode)
client_code я узнать могу а как узнать firmid, tag и currcode? Узнать то их можно но просто получив весь список фирм - getItem ("firms"), кстати он у меня выглядит так:
N       firmid               name            code     npars    nsecs
0 = SMS_FIRM               nil              nil          nil        nil
1 = MB1000100000       nil               nil         nil        nil
2 = SPBFUT000000         nil              nil         nil        nil
3 = NC0011100000         nil                nil       nil        nil
4 = SPBFUTQORT             nil                nil       nil        nil
5 = SPBFUT000HSE         nil                 nil       nil       nil
6 = ZERHM                       nil                 nil       nil      nil
7 = CITF                           nil                 nil       nil       nil
8 = CITFS                         nil                nil        nil       nil
9 = SOLDM                       nil                 nil        nil       nil
10 = SOLDM01                 nil                 nil        nil        nil
11 = OPENM                     nil                nil         nil        nil
12 = OPENM26                 nil                nil          nil       nil
13 = OPENGM                   nil                nil          nil       nil

(Пока что на демо-счете тренируюсь)

А как узнать какая фирма моя? ))))))
То же и по tag и currcode, их конечно можно получить при совершении сделки из функции Ontrade() но для этого надо чтото купить или продать а я так понимаю должна быть возможность узнать все свои рабочие параметры и без совершения сделок, сразу при запуске скрипта из oninit(), терминал ведь знает все мои параметры после установки соединения с сервером и показывает их мне

2. Как при совершении сделки в скрипте узнать что это была за сделка - Купля Продажа или еще чтото?
Я нашел только такой параметр как side_qualifier в таблице Сделки возвращаемой функцией Ontrade()
0 – не определено; 1  – Buy; 2  – Sell; 3 – Sell short; 4 – Sell short exempt; 5  – Sell undiclosed
И вот он у меня все время 0 при любой сделке
Тем не менее сам то терминал получает полную информацию о сделках - в окне "Таблица сделок" записи идут с пометкой купля или продажа

17

Re: Странности при выполнении скрипта qlua в quik

Nordman пишет:
kalikazandr пишет:

но нужна проверка по балансу - если не поменялся то второй раз не считать

И как раз подскажите пожалуйста:
1. Как проверить баланс, то есть чистый остаток денежных средств не учитывая стоимости ценных бумаг и прочих  активов

привет, не этот баланс, а баланс в OnOrder(order) order.balance - вот этот, если не поменялся с прошлого раза, то можно игнорировать это событие (естественно по одному order_num).

18

Re: Странности при выполнении скрипта qlua в quik

Nordman пишет:

2. Как при совершении сделки в скрипте узнать что это была за сделка - Купля Продажа или еще чтото?
Я нашел только такой параметр как side_qualifier в таблице Сделки возвращаемой функцией Ontrade()
0 – не определено; 1  – Buy; 2  – Sell; 3 – Sell short; 4 – Sell short exempt; 5  – Sell undiclosed
И вот он у меня все время 0 при любой сделке
Тем не менее сам то терминал получает полную информацию о сделках - в окне "Таблица сделок" записи идут с пометкой купля или продажа

поле flags содержит это информацию, в справке QLUA.chm все описано.

19

Re: Странности при выполнении скрипта qlua в quik

kalikazandr пишет:

поле flags содержит это информацию, в справке QLUA.chm все описано.

Спасибо, и вот подскажите еще пожалуйста - как при запуске скрипта, из секции OnInit ()
можно сразу узнать текущее состояние баланса денежных средств, исходя из справки для этого служат функции
getMoney  и getMoneyEx, им нужно передать параметры (STRING client_code, STRING firmid, STRING tag, STRING currcod
client_code можно получить а как получить firmid, tag и currcod?
Их можно получить либо по результатам из таблиц ontrade или onorder но для этого уже после запуска скрипта надо совершить какие либо действия, либо прописать вручную, но допустим я хочу максимально автоматизировать скрипт - чтобы он без совершения каких либо сделок или заявок сам каждый раз узнавал нужные параметры, без прописывания их вручную, терминал ведь знает все эти параметры сразу после соединения с сервером

20

Re: Странности при выполнении скрипта qlua в quik

Nordman пишет:

без прописывания их вручную, терминал ведь знает все эти параметры сразу после соединения с сервером

Привет. В OnInit не стоит использовать функции для получения данных из таблиц квика, если вы планируете не выключать скрипт, но будете выключать терминал, то при следующем включении терминала OnInit сработает раньше, чем нужные таблицы будут загружены из хранилища. А если не планируете вообще выключать терминал, то OnInit будет вызван 1 раз, при первом запуске.
Так же в main необходимо обработать событие подключения к серверу квик, т.к. в этот момент все таблицы в терминале будут очищены и заново заполнены новыми данными, полученными с сервера. Пока этого не произошло, есть шанс получить некорректные данные. Нужно понимать, что соединение с сервером при включении и после обрыва соединения не одно и тоже событие.
Такие параметры, как код клиента, firmid и др. можно прописать в файл и считывать оттуда, либо непосредственно писать их в коде. Узнать можно и программно, но это лишняя трата времени и никоим образом на автоматизацию не влияет.