Заметка

Qlua для чайников. Часть 3. Работа со стаканом

  11  

Как я и обещал на прошлом уроке, с сегодняшнего дня мы начнем писать робота. Для начала разработаем что-нибудь простенькое, например, робота спредера, который по заданному инструменту смотрит цены в стакане, если спред достаточно большой, то выставляет заявки от лучших цен покупки/продажи с заданным шагом.

Предыдущие статьи:

Qlua для чайников. Часть 1

Qlua для чайников. Часть 2. Циклы

Итак, если цены 1000/1100, а шаг 10, то робот должен выставить заявки по 1010/1090. В случае изменения цен робот должен снимать заявки и выставлять новые. Если какая-то заявка исполнилась или частично исполнилась, то робот должен это учитывать, либо вообще не перевыставлять исполненную заявку, пока не исполниться противоположная, либо выставлять на количество остатка.

Итак, берем наш шаблон. Все лишнее оттуда удаляем:

is_run=true

function main()

      while is_run do

            sleep(2000)

      end

end

function OnStop(stop_flag)

      is_run=false

end

И начинаем делать первый шаг. А именно, писать код, который бы читал крайние цены из стакана. Все эти данные можно брать из текущей таблицы параметров:

 

Но стоп! Если мы уже ввели заявки, то крайние цены – это будут цены наших заявок.  Тогда нам придется изменить цены заявок, рассчитывая новые цены от их же цен! После чего это повториться и так до тех пор, пока заявки не встретятся. Значит таблица текущих параметров не катит. Надо напрямую обращаться к стакану.

В qlua есть предопределенная функция OnQuote, она вызывается каждый раз, когда меняется стакан. У этой функции два параметра «Код класса» и «Код инструмента», по которому изменилось содержимое стакана. Давайте посмотрим, как работает данная предопределенная функция. Вставим в конец программы вот такие строки:

function OnQuote(class_code, sec_code)

      message(class_code.."   "..sec_code,1);

end

И запустим программу, чтобы посмотреть, как она будет работать:

 

Итак, это сообщение мы будем видеть каждый раз, когда по какой-либо бумаге будут меняться данные в стакане, причем только по тем бумагам, по которым стакан открыт. Закройте стакан – сообщения прекратятся.  Да, это неудобно, но если вы решили программировать под Quik, остается только смириться, принять это как данность и идти дальше.

У нас может быть открыто несколько стаканов. Следовательно, событие могут приходить от каждого из них. Их придется как-то фильтровать. Для этого выберем какую-нибудь бумагу, и будем сравнивать параметры функции OnQuote с выбранной нами бумагой. Но лучше всего сделать это путем указания параметров в начале программы, как я делал это в других моих статьях (http://robostroy.ru/community/article.aspx?id=765). Вот например так:

p_classcode="TQBR" --Код класса

p_seccode="LKOH" --Код инструмента

is_run=true

function main()

      while is_run do

            sleep(2000)

      end

end

function OnStop(stop_flag)

      is_run=false

end

function OnQuote(class_code, sec_code)

      if class_code==p_classcode and sec_code==p_seccode then

            message(class_code.."   "..sec_code,1)

      end

end

И вот мы познакомились с новой конструкцией языка – if. Между операторами if и then прописывается условие. Условий может быть несколько, их можно объединять словами and (И) либо or (ИЛИ). Если условие выполняется, то система выполнит команды между then и end. Иначе пропустит их.

Но нас интересует не значения class_code, sec_code, ибо они нужны только для фильтрации, а непосредственно котировки. Их можно получить при помощи функции getQuoteLevel2.

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

p_classcode="TQBR" --Код класса

p_seccode="LKOH" --Код инструмента

is_run=true

count=1

function main()

      while is_run do

            sleep(2000)

      end

end

function OnStop(stop_flag)

      is_run=false

end

function OnQuote(class_code, sec_code)

      if class_code==p_classcode and sec_code==p_seccode then

            l_file=io.open("D:\\1\\1\\"..tostring(count)..".txt", "w")

            tb=getQuoteLevel2(class_code, sec_code)

           

            l_file:write("BID:\n")

            for i=1,tb.bid_count,1 do

                  l_file:write(tostring(tb.bid[i].price)..";  "..

                        tostring(tb.bid[i].quantity).."\n")

            end

           

            l_file:write("OFFER:\n")

            for i=1,tb.offer_count,1 do

                  l_file:write(tostring(tb.offer[i].price)..";  "..

                        tostring(tb.offer[i].quantity).."\n")

            end        

           

            count=count+1

            l_file:close()

      end

end

Путь к файлу вместо "D:\\1\\1\\" поставьте тот, который вам надо.

Программка будет создавать в указанном каталоге файлы примерно вот такого содержания:

 

Таким образом, файлы будут содержать  цену и количество из стакана.

Будьте осторожны, этих файлов может оказаться ОЧЕНЬ МНОГО.

Итак, читать стакан мы научились. Теперь надо научиться анализировать прочитанное. Это будет тема следующего урока.

Комментарии

Николай Камынин — 13 октября 2014 г.

megabax,
у Вас намечается методическая ошибка.
Вы пишете о QLua, но собираетесь учить анализировать стакан.
Вы уверены в собственном уровне знаний данного вопроса?
Плохой учитель хуже никакого.

-1 +

megabax — 13 октября 2014 г.

Николай Камынин, смотре что вы понимаете под словом "анализ". Я пишу об анализе в контексте программирования.

3 +

Lomonosov — 5 октября 2015 г.

megabax, Выдаёт ошибку "26: attempt to index global 'I_file' (a nil value)" в момент запуска скрипта и не создаёт файлы, которые "будут содержать цену и количество из стакана"...

0 +

suvik — 22 февраля 2015 г.

николай как правильно написать робота который входит в сделки только на определённом отступе от скользящей средней

0 +

suvik — 22 февраля 2015 г.

либо в лонг либо в шорт

0 +

Optimus1 — 4 сентября 2015 г.

Здравствуйте,

Подскажите, а можно ли как то к этим данным стакана прикрутить еще и время ?

0 +

Optimus1 — 4 сентября 2015 г.

Файлы не сохраняются !

0 +

Lomonosov — 5 октября 2015 г.

Выдаёт ошибку "26: attempt to index global 'I_file' (a nil value)" в момент запуска скрипта и не создаёт файлы, которые "будут содержать цену и количество из стакана"...

0 +

ardeo — 26 октября 2015 г.

function OnQuote(class_code, sec_code)
if class_code == p_class and sec_code==p_sec then
QL2=getQuoteLevel2(class_code, sec_code)
local i=tonumber(QL2.bid_count)
out_txt="BID: "..QL2.bid[i].price.." "..QL2.bid[i].quantity..
"\nOFFER: "..QL2.offer[1].price.." "..QL2.offer[1].quantity
message(out_txt,1)
end
end

0 +

andromedaX — 15 мая 2016 г.

Спасибо, все работает!

0 +

Написать комментарий

Чтобы написать комментарий, необходимо авторизоваться.

Написать администратору