Сегодня:
Узнаем общее количество заявок
Функции getNumberOf и getItem
Как пройтись циклом по всем заявкам
Вывод активных заявок
Снять скриптом заявку
Снимаем все активные заявки скриптом
Снимаем только заявки, выставленные конкретным скриптом
В прошлый раз мы научились выставлять скриптом заявки в терминале, теперь можем поработать с ними.
Выставим скриптом 5 заявок на покупку и продажу от лучших цен BIDи OFFERстакана заявок с шагом в 0,01.
Напишем функцию, которая будет выдавать нам необходимые цены (лучшую цену спроса и предложения) со стакана:

И возвращать -1, если предложения или покупки в стакане не найдены (стакан закрыт, либо нет торгов).
Тогда основной алгоритм в main будет выглядеть:

Функцию выставления заявки newtransaction() мы прописывали ранее, она не изменится.
Запустим скрипт, увидим в нем свои заявки:

Теперь поработаем с ними.
Узнаем общее количество заявок
Количество строк в таблице заявок (т.е. сумму как активных заявок, так и снятых и исполненных) можно получить через функцию getNumberOf:
number = getNumberOf("orders")
message("Количество заявок: "..number)
Данная функция позволяет получать количество строк из различных таблиц терминала. Используется чаще всего вместе с функцией getItem с помощью которой мы можем получать уже сами значения таблиц и смотреть в т.ч. лимиты по деньгам, лимиты по бумагам, информацию по сделкам и пр. Подробное описание можно найти в файле QLUA.chm (находится в папке с терминалом) при поисковом запросе getNumberOf:

Сейчас нас будут интересовать заявки.
Каждая строка таблицы заявок представляет собой массив данных с набором параметров. Нумерация строк идет с 0. Параметры таблицы каждой строки можно посмотреть в мануале QLUA раздел getNumberOf, далее Заявки (orders):

Следующий скрипт пройдется по таблице заявок и выведет по каждой номер, цену, объем и комментарий.

Внимательно изучая таблицу параметров можно заметить, что нигде не прописаны направление (покупка/продажа), а также статус по заявке (активная, снята, исполнено). Это разработчики решили спрятать во флаги (flags), с которыми нам нужно будет работать побитово. Чтобы не было скучно, видимо.
bit.band(tonumber(myorder["flags"]), 1) > 0 -- активная заявка bit.band(tonumber(myorder["flags"]), 4) > 0 -- заявка на продажу
Вывод всех активных заявок:

Результат будет аналогичен предыдущему выводу, за минусом тех заявок, которые успели исполниться, либо которые мы сняли вручную.
Выведем активные заявки на покупку:

Номер заявки в торговой системе (order_num) нам нужен, чтобы работать далее с ней. Например, снять заявку.
Снять скриптом заявку
Чтобы снять активную заявку нужно знать её номер (order_num не путать с idтранзакции!). Если мы его знаем и хотим запустить транзакцию на удаление нам достаточно передать в sendTransactionследующую таблицу:

Но если в терминале мы можем посмотреть номер конкретной заявки, то в случае автоматизации нам нужно указать скрипту по какой логике и какую именно заявку мы хотим снять. Напишем в качестве примера скрипт, снимающий последнюю активную заявку.
Если мы уверены, что нужная нам заявка находится последней в таблице, то мы можем, получив по getNumberOfколичество строк таблицы заявок просто взять последнюю строку (с нумерацией getNumberOf() – 1) и по её номеру выставить транзакцию на снятие заявки.
Однако мы рассмотрим вариант, когда мы не знаем активна последняя заявка или нет и будет циклом перебирать в обратном порядке список заявок построчно, пока не дойдем до первой активной заявки. Её и снимем (она может попасться сразу, а может быть и в середине таблицы или даже в самом начале, если мы вручную или скриптом ранее снимали остальные заявки, либо какие-то заявки исполнились).
Сделаем функцию, которая будет снимать заявку по её номеру в терминале (order_num):
Проходим циклом по всем строкам таблицы заявок в обратном порядке и как только находим первую активную заявку снимаем её:

Файл: https://github.com/morefinances/qlua/blob/main/delete_one_order.lua
Снимаем все заявки скриптом
Чтобы снять разом все активные заявки нам достаточно в предыдущем примере убрать (или закомментить --) break в цикле, который обрывал работу после снятия первой найденной активной заявки. В этом случае цикл пройдется по всем строкам таблицы заявок и через новые транзакции снимет каждую активную заявку.

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

Видим по комментариям, что снимались сперва те заявки, которые выставились последними. Всё автоматизировано.
Снимаем только заявки, выставленные конкретным скриптом.
Чтобы скрипт снял не все заявки, а только собственные, ранее выставленные, нам нужно обращаться к комментарию заявки (CLIENT_CODE) и сверять по нему (при условии, что другие скрипты делают собственные комментарии, отличные от варианта текущего алгоритма).
Здесь в string.sub(myorder["brokerref"], 8, 15) – первые 7 символов это торговый код и двойной слэш, поэтому делая срез с 8 по 15 получаем именно тот общий комментарий (code_order), который делал скрипт при выставлении заявки, но без слэша и номера id заявки.
Для проверки работы скрипта выставим вручную в терминале заявку, например, на продажу объемом в 10 лот.


После этого опять запустим скрипт выставления заявок по стакану.

В таблице заявок видим, что 10 лот, выставленные вручную имеют короткий комментарий (только код клиента и двойной слэш), а скриптом с указанием скрипта, который выставлял и номером id заявки (прописывали это в алгоритме выставления заявки).

Теперь снимем скриптом заявки, выставленные алгоритмом.
Видим, что заявка, выставленная вручную осталась активной, остальные снялись:

Одна заявка успела исполнится. После работы на учебном счете не забывайте закрывать позиции, чтобы суммы демосчета хватило для всех экспериментов.
В следующей статье завершим работу с заявками.
Самостоятельная работа:
1) Напишите скрипт, закрывающий все активные заявки по таймеру, например в 18:30.
2) Измените предыдущий скрипт так, чтобы заявки по таймеру не закрывались, а перевыставлялись на исполнение по рынку.
3) Напишите скрипт, который делает покупку по рынку 1 лотом GAZP в 11:01 и продает в 11:55.
4*). Напишите скрипт, который выставляет тейк и стоп после исполнения заявки, при этом если по таймеру (например 2 часа) ни один уровень не достигнут, то позиция принудительно закрывается по рынку.
Теги: qlua для начинающих, кружок авиамоделизма.
Ранее:
Qlua: введение
Доля клиентов, использующих алгоритмическую торговлю
«Кружок авиамоделизма»
Разные торговые терминалы, почему Quik
Основной функционал qlua
smart-lab.ru/blog/917696.php
Настраиваем торговый терминал и редактор кода
Установка торгового терминала
Подготовка терминала
Вкладки в терминале
Сохранение и загрузка настроек
Таблица системных сообщений
Отключение окна сообщений
Редактор Notepad++
Настройка русского языка в редакторе
Выбор синтаксиса языка и кодировки
Цветовые настройки
Дублирующий просмотр
Запуск первого скрипта
smart-lab.ru/blog/918869.php
Основы qlua, часть 1:
message, конкатенация
фильтрация по сообщениям в терминале
PrintDbgStr, комментарии
типы данных, type
операции с числами
операции со строками
операции с таблицами
условные операторы
smart-lab.ru/blog/920031.php
Основы qlua, часть 2:
Циклы for … do … end, while do … end, repeat … until.
sleep, break, goto.
как пройти весь массив циклом, как пройти таблицу по ключам
локальные и глобальные переменные, функции
получение даты и времени
получение данных через getInfoParam
smart-lab.ru/blog/921366.php
Qlua: структура скрипта.
Структура типового скрипта qlua с примерами.
Обработка скриптом «обрыва связи» с сервером и возобновления работы.
Работа с файлами: запись, перезапись и чтение файла.
getScriptPath, getWorkingFolder
smart-lab.ru/blog/922044.php
Qlua: получение данных из таблицы текущих торгов, создание таблиц в торговом терминале.
Получение биржевых данных через функцию getParamEx
Выгрузка списка параметров функции getParamEx через DDE из торгового терминала
Создание пользовательских таблиц в торговом терминале
smart-lab.ru/blog/923365.php
Qlua: работа с таблицами (продолжение). Пишем своего советника (начало).
Интегрируем таблицы в структуру скрипта qlua.
Удаляем таблицы через DestroyTable.
Останавливаем скрипт через IsWindowClosed.
Обработка события закрытия таблицы через коллбэк.
Работа с цветом SetColor, Highlight, SetSelectedRow.
Пишем простого советника.
smart-lab.ru/blog/924710.php
Qlua: дополняем скрипт советника таймингом:
Устанавливаем время старта работы скрипта,
Ставим тайминг на получение сигналов на вход,
Устанавливаем таймер на приостановку скрипта.
smart-lab.ru/blog/925421.php
Qlua советник: дополняем сигналами на закрытие позиции, таблицей для вывода данных и расчетом финансового результата по позициям.
Дополняем сигналами на закрытие позиции.
Создаем дополнительную таблицу для вывода данных.
Делаем расчет финансового результата.
smart-lab.ru/blog/926972.php
Qlua: завершаем апгрейд советника:
Пропуск «поздних» сигналов на старте.
Обработка советником обрыва связи.
Сохранение сигналов и логов в файл.
smart-lab.ru/blog/927748.php
Qlua: пишем скринер акций Московской биржи
smart-lab.ru/blog/928152.php
Qlua: получение данных биржевых свечей с сервера брокера, обработка данных, пишем скрипт выгрузки котировок
Функция CreateDataSource
Получение количества свечек данных
Пауза для подгрузки данных
Получение по инструменту OPEN, HIGH, LOW, CLOSE, VOLUME
Обработка времени и даты
Закрытие источника данных
Примеры: получение данных последних 10 свечей, выгрузка новой минутной свечки после её закрытия, текущее значение простой средней SMA10 по минуткам
Простой скрипт выгрузки котировок
smart-lab.ru/blog/929905.php
Qlua: получение данных с графиков терминала.
Идентификатор инструмента
Получаем количество свечей через getNumCandles
Получаем свечные данных через getCandlesByIndex
Читаем данные с индикатора SMA
Данные с верхней и нижней линии Price Channel
Графики с таблицы текущих торгов.
Сравнение получение данных через CreateDataSource и через getCandlesByIndex
smart-lab.ru/blog/931408.php
Qlua: работа с метками, пишем торгового советника на индикаторах.
Вывод текста на график
Вывод графических сигналов
Удаление меток с графика
Торговый советник на индикаторах
Удаление данных вечерней/утренней сессии с графика.
smart-lab.ru/blog/933582.php
Qlua: работа с лентой всех сделок.
Что такое таблица обезличенных сделок.
Настройка таблицы в терминале.
Что делать, если таблица открылась, но она пустая.
Вывод данных с таблицы по DDE.
Работа с таблицей обезличенных сделок через скрипт qlua с примерами.
Пишем советника, показывающего на графике крупных игроков.
smart-lab.ru/blog/935919.php
Qlua: работа с лентой всех сделок (часть 2).
Различия данных ленты всех сделок и биржевого стакана.
Большие покупки и продажи в ленте сделок и динамика цены.
Альтернативные варианты поиск крупных игроков по ленте сделок.
smart-lab.ru/blog/938053.php
Qlua: дополняем скринер акций статистикой, лидерами роста и падения.
Добавляем статистику по акциям роста и падения.
Составляем TOP лидеров роста и падения.
Быстрый поиск акций по тикеру в терминале.
smart-lab.ru/blog/938450.php
Qlua: работа с биржевым стаканом.
Работа с биржевым стаканом через getQuoteLevel2
Особенность нумерации в стакане заявок терминала квик
Работа через функцию обратного вызова OnQuote
Примеры работы со стаканом из скрипта
Сравнение реализации одного алгоритма через разные функции
smart-lab.ru/blog/940742.php
Qlua: работа с заявками (часть 1).
Зачем нужен демо терминал
Где открыть учебный счет
Выставление заявки в торговом терминале через скрипт
Делаем функцию выставления заявки по требуемым условиям
Карман заявок и tri-файлы
Параметры для заявок с примерами по разным рынкам
smart-lab.ru/blog/942481.php
Например: в календарных спредах легко найти отрицательную цену.
Номер транзакции тоже ненадежен в этом плане.
Еще добавлю, что для получения лучшего спроса и предложения по инструменту не надо подписываться на очень «тяжелый» поток данных Level_II_Quotes. Эти данные есть в таблице текущих торгов, получаемые очень быстро и просто. И если уж рассматривается метод getQuoteLevel2, то важно уточнять, что без подписки он будет работать если стакан уже открыт самим пользователем. Что вероятно и будет сделано, но, например, вероятна ситуация, когда нет открытых окон в терминале. Все заказывается скриптами.
Также стоит уточнить, что для снятия всех активных заявок есть отдельный метод, и не надо циклом бегать по ордерам. Что тоже необязательно делать постоянно, т.к. при первом сканировании достаточно запомнить индекс записи в таблице ордеров. Он будет неизменным в течении торговой сессии.
Но как учебный пример в учебной ситуации — годится. Хотя, конечно, лучше сразу предусматривать в коде нештатные ситуации. Избегать sleep, т.к. это плохой подход в клиент серверном взаимодействии. В конечном итоге, пишется же инструмент для работы с деньгами, т.е. он должен быть надежным даже когда время ожидания ответа от сервера брокера достигает десятков минут.
Вопрос немного не по теме, а есть ли у Вас опыт работа с различными типами заявок типа Стоп-лимит (Stop limit), Тейк профит… рекомендации по ним?
В частности интересует механизм реализации Тейк профит: у моего брокера нет алгоритмических заявок, а я бы хотел каждый день автоматом выставлять заявку на продажу по цене к примеру 101. Выхода два: 1) ставить скриптом, 2) использовать Take profit. Вопрос такой — если была заявка на покупку по рыночной цене которая с 99 пробьет цену до 105, то в какой очередности обработаются — прямая заявка по 101, прямая заявка по 102, заявка Take profit по 101…