Функции обратного вызова, встроенные в QLua

Автор записи: Дмитрий (Admin)
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 9, среднее: 5,00 из 5)
Загрузка...

Qlua-основы
Во время работы терминала QUIK в нем происходят различные события, такие, как приход новой обезличенной сделки, выставление заявки, сработал стоп-ордер и т.п. Для того, чтобы своевременно и определенным образом реагировать на эти события, в скрипте QLua можно использовать функции обратного вызова, которые будут выполнять блок кода, расположенного внутри них, в тот момент, когда это событие произойдет.

Для каждого определенного события есть своя предопределенная разработчиками QLua функция!

Функции OnInit(), main() и OnStop() рассматриваются в статье "База скрипта в QLua(Lua)".

Для использования функций в терминале QUIK должны быть открыты соответствующие им таблицы!

OnAccountBalance()
Функция вызывается терминалом QUIK при получении изменений текущей позиции по счету (ТОЛЬКО ДЛЯ БРОКЕРА).
OnAccountPosition()
Функция вызывается терминалом QUIK при изменении денежной позиции по счету (ТОЛЬКО ДЛЯ БРОКЕРА).
OnAllTrade()
Функция вызывается терминалом QUIK при получении обезличенной сделки (Таблица всех сделок).
OnCleanUp()
Функция вызывается терминалом QUIK при смене сессии и при выгрузке файла qlua.dll

OnClose()
Функция вызывается перед закрытием терминала QUIK.
OnConnected()
Функция вызывается терминалом QUIK при установлении связи с сервером QUIK.
OnDepoLimit()
Функция вызывается терминалом QUIK при получении изменений лимита по бумагам.
OnDepoLimitDelete()
Функция вызывается терминалом QUIK при удалении клиентского лимита по бумагам.
OnDisconnected()
Функция вызывается терминалом QUIK при отключении от сервера QUIK.
OnFirm()
Функция вызывается терминалом QUIK при получении описания новой фирмы от сервера.
OnFuturesClientHolding()
Функция вызывается терминалом QUIK при изменении позиции по срочному рынку (Позиции по клиентским счетам (фьючерсы)).
OnFuturesLimitChange()
Функция вызывается терминалом QUIK при получении изменений ограничений по срочному рынку (Ограничения по клиентским счетам).
OnFuturesLimitDelete()
Функция вызывается терминалом QUIK при удалении лимита по срочному рынку.
OnMoneyLimit()
Функция вызывается терминалом QUIK при получении изменений по денежному лимиту клиента (Таблица лимитов по денежным средствам).
OnMoneyLimitDelete()
Функция вызывается терминалом QUIK при удалении денежного лимита.
OnNegDeal()
Функция вызывается терминалом QUIK при получении внебиржевой заявки (Таблица заявок на внебиржевые сделки).
OnNegTrade()
Функция вызывается терминалом QUIK при получении внебиржевой сделки для исполнения (Таблица сделок для исполнения).
OnOrder()
Функция вызывается терминалом QUIK при получении новой заявки или при изменении параметров существующей заявки (Таблица заявок).
OnParam()
Функция вызывается терминалом QUIK при изменении текущих параметров (Текущая таблица параметров).
OnQuote()
Функция вызывается терминалом QUIK при получении изменения стакана котировок.
С примером использования данной функции можно ознакомиться в этой статье.

OnStopOrder()
Функция вызывается терминалом QUIK при получении новой стоп-заявки или при изменении параметров существующей стоп-заявки (Таблица стоп-заявок).
OnTrade()
Функция вызывается терминалом QUIK при получении сделки (Таблица сделок).
OnTransReply()
Функция вызывается терминалом QUIK при получении ответа на транзакцию пользователя (Таблица транзакций).

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

В функциях OnAllTrade(), OnParam() и OnQuote() вывод сообщений намеренно закомментирован, т.к. они вызываются очень часто и независимо от Ваших действий, если Вам будет нужно отследить их вызовы, раскомментируйте строки вывода сообщений в данных функциях.

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

Скрипт отслеживания работы функций обратного вызова
Для более удобного просмотра информации, выводимой при помощи функции message(), используйте таблицу сообщений (меню: "Сообщения"->"Системные сообщения"->"Таблица сообщений..."). А также, снимите флажок "Показывать окно сообщений" в меню: "Настройки"->"Основные..."->"Сообщения".

Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!

Добавить комментарий

Функции обратного вызова, встроенные в QLua: 177 комментариев

  1. Доброго дня.
    Для выставления заявки тейк-профит использую вт такой код:

    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
    
    function BuyTPOrder(price)
       uniq_trans_id = uniq_trans_id + 1
     
       local buyTPOrder = {
         ACCOUNT            = my_TRADE_ACCOUNT,
    	 CLIENT_CODE        = my_CLIENT_CODE,
    	 TRANS_ID           = tostring(uniq_trans_id),
    	 ACTION             = 'NEW_STOP_ORDER',
    	 STOP_ORDER_KIND    = 'TAKE_PROFIT_STOP_ORDER',
    	 CLASSCODE          = 'TQBR',
    	 SECCODE            = 'MAGN',
    	 OPERATION          = 'B',
    	 STOPPRICE          = tostring(price),
    	 QUANTITY           = tostring(amount_of_lots),
    	 EXPIRE_DATE        = 'GTC',
    	 OFFSET             = '0,02',
    	 OFFSET_UNITS       = 'PRICE_UNITS',
    	 SPREAD             = '0,05',
    	 SPREAD_UNITS       = 'PRICE_UNITS',
    	 }
     
       local transactionResult = sendTransaction(buyTPOrder)
        if transactionResult ~= '' then
        	message(transactionResult,3)
    	end
    end

    Несмотря на выставление параметра EXPIRE_DATE = 'GTC' (то есть хочется "до отмены") в систему уходит заявка со сроком действия "TODAY". Почему так происходит?

  2. Здравствуйте!
    Следующий код:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    IsRun = true;
     
    function OnStop()
       message("OnStop - остановка скрипта из диалога управления "..tostring(os.clock()));
       -- Останавливает цикл в функции main
       IsRun = false;
    end;
     
    function main()
       -- Цикл будет выполнятся, пока IsRun == true
       while IsRun do
          sleep(1000);
       end;   
    end;
     
    main()

    вешает терминал наглухо. Проверял на разных ПК, с подключением к серверу или без такового. Где я свернул не туда?

  3. Здравствуйте. Подскажите пожалуйста, если уже обсудили, то ткните пожалуйста в материал, как передать в функцию обратного вызова переменные и как вернуть, что-либо оттуда. Вариант с глобальными переменными знаю, использую, но хочу уйти от него. Спасибо.

      1. kalikazandr, так и делаю, но периодически (пару раз за сессию) получаю искажённое, неверное значение переменной, соответственно реакция моей программы меняется. Квик от робота напрягается не сильно. Для устранения мыслю изменить способ обмена данными с функциями обратного вызова (если возможно) ну и компьютер почистить от софта который грузит систему, может какие - нибудь совпадения событий случаются, не знаю. Наблюдаю некоторую задержку в работе квика в момент получения ошибки. Отсюда и вопрос возник "Есть ли способ, передать конкретные данные в конкретную функцию обратного вызова и как вернуть, что-либо оттуда". Спасибо.

        1. Скорее всего к одним и тем же переменным у вас идет обращение из 2-х потоков: функций обратного вызова, которые работают в основном потоке терминала и main. Если так, то посмотрите статьи:
          TGB: "МОДУЛЬ РЕАЛИЗАЦИИ ИНТЕРФЕЙСА ОБРАБОТКИ СОБЫТИЙ..."
          Тоха: "БИБЛИОТЕКА LUA_SHARE..."

          1. Несинхронизированные обращения из двух потоков исключаю, на такие моменты обращаю внимание при написании кода. Получается, нет способа, "передать конкретные данные в конкретную функцию обратного вызова и вернуть, что-либо оттуда". Спасибо.

            1. В таком случае не понятно, где у вас получаются "искаженные" значения переменных? Этого не может быть априори, если у вас в коде все правильно написано. Можно пример кода?

  4. Добрый день! Скажите в Lua есть:
    1. Колбэк на событие закрытия таймфрейма (свечи) графика в заданном окне QUIK?
    2. Доступ к значениям индикатора (из списка встроенных стандартных индикаторов), прикрепленного к графику в заданном окне QUIK?

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

    1. Добрый вечер!
      1. Нет, но можно реализовать.
      2. Файл справки QLUA.chm (где info.exe), вам нужна функция getCandlesByIndex, с помощью этой функции можно получить значения линии(ий) индикатора.

      Делаете свой индикатор, который будет выполнять ваши требования п.2 не нужен вовсе.

  5. Здравствуйте! Никак не могу понять, как правильно пользоваться флагами. Пытаюсь вытащить статус стоп-заявки из таблицы стоп-заявок, номер заявки и иные её параметры для идентификации он воспринимает, все показывает, но сам статус никак не могу понять, как вытащить. Код выглядит вот таким образом:
    if Stopnumb==getItem("stop_orders",l).order_num and getItem("stop_orders",l).flags == 0x1 then
    message("Status active",1)
    message("status"..getItem("stop_orders",l).flags,1)
    if getItem("stop_orders",l).flags==0x4 then
    TP=(-LOT1)
    else TP=(LOT1)
    end
    idx=1
    elseif Stopnumb==getItem("stop_orders",l).order_num and (getItem("stop_orders",l).flags == 0x2 or getItem("stop_orders",l).flags == 0x2) then
    TP=0
    message("Status not active",1)
    message("status"..getItem("stop_orders",l).flags,1)

    1. Здравствуйте. Нужно побитовое сравнение

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      
      --статус заявки/стоп-заявки
      local function olr_status(flags)
        if bit.band(flags, 0x8000) ~= 0 then
          return "C" --"stop-calculate" 
        end
        if bit.band(flags, 0x1) ~= 0 then
          return "A" --"active"
        else
          if bit.band(flags, 0x2) ~= 0 then
            return "K" --"killed"
          else
            return "F" --"filled"
          end
        end
      end
       
      for i=0, getNumberOf("stop_orders")-1 do
        local item = getItem("stop_orders",i)
        message(
          "№: "..tostring(item.order_num)..
          "status: "..olr_status(item.flags)
        )
      end

      Не стоит использовать getItem для получения каждого параметра таблицы.

      1. Спасибо! В этом все сложилось. Я правильно понимаю, что вытащить статус на покупку или на продажу можно вот таким скриптом?:
        local function olr_type(flags)
        if bit.band(flags, 0x8000) ~= 0 then
        return "C" --"stop-calculate"
        end
        if bit.band(flags, 0x4) ~= 0 then
        return "B" --sell
        else
        return "S" --buy
        end
        end

        1. Все! Вроде бы нашла корректную формулировку:
          local function olr_type(flags)
          if bit.band(flags, 0x8000) ~= 0 then
          return "C" --"stop-calculate"
          end
          if bit.band(flags,4) >0 then
          return "S" --sell
          else
          return "B" --buy
          end
          end

          А вообще с этими флагами ну очнеь тяжко все дается.

          1. Привет! Поищите тут, на сайте, функции для работы с битовыми флагами.
            Ваша olr_type, надеюсь решает ваши задачи, но разные по смыслу (направление и одно из состояний стоп-заявки).
            Лучше сделать 4 функции определения:
            1. состояния заявки/стоп-заявки (olr_status);
            2. направление заявки/стоп-заявки;
            3. направление сделки;
            4. направление обезличенной сделки.
            И забудьте про битовые флаги.

  6. Здравствуйте!
    Подскажите, пожалуйста, в какой момент вызывается функция OnTableEvent(), сразу при наступлении события, или если скрипт выполнял другую функцию, то по ее завершению? И после обработки события откуда продолжает выполнение, с места вызова?

    1. Здравствуйте.
      событие попадает в хранилище терминала, если в скрипте есть подписка на это событие, то будет вызвана функция OnTableEvent() в потоке терминала, main об этом ничего не знает и продолжает выполнять свой код в штатном режиме