порядок-выполнения-в-квике

В прошлой статье мы разобрали как создать свой первый скрипт, запустили его. Давайте вспомним код из него:

function main()
  message("Запущен мой скрипт");
end


Код написан всего в несколько строчек. Оставим на потом разбор самих функций, используемых в скрипте, а сейчас рассмотрим именно порядок исполнения функций в коде. Это нужно именно для понимания того, что код не всегда будет исполняться по порядку, в котором мы его создаем, например со второй строки. Это зависит от используемых функций в коде. В нашем примере мы использовали одну функцию — main. Скрипт, написанный на LUA в терминале КВИК, может включать одновременно ряд функций, обрабатывающих различные события (например, изменение котировок, новая сделка и пр.).

Последовательность исполнения скрипта на языке LUA в КВИКе представим так:

схема-работы-скрипта

Нажимая «Запустить» в разделе «Сервисы -> Lua скрипты«, начинает свою работу скрипт. Сначала обрабатывается основа скрипта без всех функций (на картинке обозначено как — BODY) и вызова обработчика Init(). Дальше после того, как выполнится функция Init(), образовывается отдельный новый поток в терминале КВИК и именно в нем запускается функция main(). Пока функция main исполняется, скрипт можно считать запущенным. При завершении исполнения функция main, выполнение скрипта также останавливается, т.е. и вызов из него обработчиков событий.

И главное, функции обработки событий, выполняются в основном потоке терминала QUIK, в отличие от функции main(), из этого следует, что они должны работать мало, иначе будут видны «подтормаживания» в работе КВИКа.

Представим наш скрипт Укрупненно в виде такой схемы

схема-работы-скрипта-LUA

Схематично показан наш скрипт. Состоит из четырех компонентов. В красном блоке расположена главная функция main. И как писали выше, что функция может находиться не в начале скрипта. Пара желтых блоков — это функции, которые создает сам пользователь. Нижний синий блок — это функция обратного вызова. И немного поговорим о данной функции.

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

справочный-файл-по-луа

Если откроем справочник QLUA.chm из папки с КВИКом, то можем узнать, что за события используются в КВИКЕ и что за функции с ними связаны. Находим в заглавии — Функции обратного вызова.

функция-обратного-вызова

И узнаем, что функция Main — это функция обратного вызова.

Цитата из инструкции:
«Функция, реализующая основной поток выполнения в скрипте. Для ее выполнения терминал QUIK создает отдельный поток. Скрипт считается работающим, пока работает функция main(). При завершении работы функции main() скрипт переходит в состояние «остановлен». Если скрипт находится в состоянии «остановлен», то не происходит вызовов функций обработки событий терминала QUIK, содержащихся в этом скрипте.»

Главный момент — это то, что Main исполняется в своем новом потоке и не мешает процессам основного функционала терминала КВИК.

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

Перейдем к следующему блоку в нашей схеме — OnInit (функция обратного вызова), в схеме показана синим. В справочнике по LUA про эту функцию написано следующее:
«Функция вызывается терминалом QUIK перед вызовом функции main(). В качестве параметра принимает значение полного пути к запускаемому скрипту.»

Основное для нас — функция OnInit исполняется до начала выполнения функции main. Следовательно по порядку — сначала сработает функция OnInit, а после ее выполнения, начнет отрабатывать функция Main. А т.к. вызывается OnInit до вызова main, то выполнение функции OnInit осуществляется в общем потоке QUIK, т.к. main еще не была вызвана, следовательно отдельного поток еще нет.

Рассмотрим функции, создаваемые нами, т.е. пользователями.

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

А теперь разберем все на живом примере.

скрипт-на-луа

На первый взгляд может показаться все сложно и непонятно, но давайте разберемся!

Сначала объявляем таблицу t и в поле 0 устанавливаем время, в течении которого работает терминал QUIK. Для нас будет точка старта выполнения кода. В другие графы запишем разницу между временем в необходимый момент и стартовой точкой, в итоге узнаем сколько времени прошло в любой момент кода. Со следующей строки запишем время старта скрипта, потом сделаем паузу в 100 мс. Дальше в нужных точках кода указываем, где расположено исполнение и время в данный момент, этим мы определим последовательность выполнения кода. В завершении, перед остановкой функции main, покажем информацию, где покажем все указанные точки.

Можете скачать файл и запустить в Квике у себя. Должно получиться данное сообщение.

скрин-сообщения-от-скрипта

Смотрим на метки по времени. 1я метка «Запуск» и время 0, скрипт только запустился и прошло 0 мс. 2я метка «Отметили myFirstFunc» и время 0,101, это означает — Квик получил информацию, что есть функция myFirstFunc спустя 101мс после старта скрипта, но только лишь узнал про функцию, при этом основа функции не исполнилась. А чем был занять скрипт эти 100мс? Собственно ничем 🙂 Просто ожидал. Получил команду sleep(100) в строка номер 2. Обращаем ваше внимание, что функция main тоже отмечена, в это время, но не исполняется пока и новый поток для нее не создан. Так же поступили и другие метки участвующих функций.

работа-скрипта

Смотрим на цвет курсора. Сначала цвет был синим, что показывает процесс исполнения кода в потоке самой платформы QUIK, а после исполнения функции OnInit() поток в QUIK начинает выполнять функционал самого терминала, при этом создан новый поток — окрашен в желтый цвет. После завершения функции main, новый поток исчезает и сам скрипт останавливается.

В статье попытались понять последовательность выполнения процессов в запущенных нами скриптах, написанных на языке LUA в торговом терминале QUIK.
 
 
 


Вы уже сейчас можете начать изучать Видео курс- роботы в TSLab и научиться самому делать любых роботов!
 
Можно записаться на следующий поток ОнЛайн курса «Создание роботов в TSLab без программирования», информацию по которому можно посмотреть тут->
 
Также можете научиться программировать роботов на нашем Видео курсе «Роботы для QUIK на языке Lua»
 
Если же вам не хочется тратить время на обучение, то вы просто можете выбрать уже готовые роботы из тех, что представлены у нас ДЛЯ TSLab, ДЛЯ QUIK, ДЛЯ MT5, ДЛЯ КРИПТОВАЛЮТЫ!
 
Также можете посмотреть совершенно бесплатные наработки для МТ4, Квика, МТ5. Данный раздел также постоянно пополняется.
 
Не откладывайте свой шанс заработать на бирже уже сегодня!