Вопрос ко всем, кто знает: какую таблицу возвращает getQuoteLevel2 если нет bid или ask?
Пользователь
Сообщений: Регистрация: 27.12.2022
17.04.2026 21:29:51
Напр., бывает так, что запампленная акция выросла до потолка и её все хотят продать, но никто не хочет купить. Какова структура таблицы, если, к примеру, bid_count == 0 (на самом деле там вопреки документации будет строка "0.000000")? 1. Таблица bid отсутствует (нет ноды с именем "bid"). 2. Есть нода с именем "bid" и её тип nil. 3. Тип этой ноды "table" и эта таблица пустая? 4. Или, как сказано в документации, вместо таблицы bid "возвращается пустая строка"?
На днях я посмотрел, какую последнюю таблицу по разным акциям возвращает getQuoteLevel2 в конце вечерней сессии примерно в 23:50: в ней общее количество нод две: bid_count == offer_count == "0.000000". Причём, по одним акциям биржа возвращает последнюю таблицу до 23:50, а после этого по другим акциям биржа ещё может вернуть полноценные таблицы с 4-мя нодами.
QUIK clients support
Сообщений: Регистрация: 11.08.2025
20.04.2026 07:48:43
Добрый день.
Если определить параметры bid и offer, то функция вернет таблицу без этих параметров. Пример:
Вот что написано в последней версии справки QLUA.chm за 23.10.25:
Цитата
При отсутствии и спроса и предложения функция возвращает таблицу без параметров bid и offer.
Параметр
Тип
Описание
bid_count
STRING
Количество котировок покупки. При отсутствии спроса возвращается значение «0»
offer_count
STRING
Количество котировок продажи. При отсутствии предложения возвращается значение «0»
bid
TABLE
Котировки спроса (покупки). При отсутствии спроса возвращается пустая строка
offer
TABLE
Котировки предложений (продажи). При отсутствии предложения возвращается пустая строка
1. Здесь, к примеру, неправильно написано, что при отсутствии спроса возвращается значение "0": возвращается "0.000000". Я ещё в прошлом году писал об этом на форуме. Сказали, что исправят, но так и не сделали.
2. Это описание противоречит само себе. При отсутствии спроса и предложения нет параметров с именами "bid" и "offer", или они есть, но имеют тип STRING и длину строки == 0?
3. Что возвращается, если, к примеру, есть offer, но нет bid? bid будет пустой строкой или не будет параметра с именем "bid" (вместо него будет нода с типом NIL?)
Пользователь
Сообщений: Регистрация: 27.12.2022
20.04.2026 20:24:30
Нормальному человеку трудно представить, как можно написать в док-ции, что bid имеет тип TABLE, но может возвращать пустую строку...
Из армейского фольклора: "В военное время величина синуса может достигать четырёх".
Serge123 написал: Нормальному человеку трудно представить, как можно написать в док-ции, что bid имеет тип TABLE, но может возвращать пустую строку...
Из армейского фольклора: "В военное время величина синуса может достигать четырёх".
Возможно это потому, что это LUA. и строка и таблица это TValue содержащий тип и указатель. Когда таблицы нет, то надо что-то верную . Лучше полагаю вернуть nil, но почему-то рушили возвращать пустую строку.
1. Актуальная документация к QLua находится по ссылке: В нее внесены изменения, о которых вы говорите. 2. Если спрос и предложения будут отсутствовать, то действительно будет возвращена пустая строка. Таков дизайн QLua. 3. Указанный вами случай описан в документации в п. 3.9.1
Пользователь
Сообщений: Регистрация: 27.12.2022
21.04.2026 18:35:17
Цитата
Oleg Kuzembaev написал: 2. Если спрос и предложения будут отсутствовать, то действительно будет возвращена пустая строка. Таков дизайн QLua.
Нет, в этом случае не будет параметров bid и offer согласно вашей же док-ции. Оказывается, ещё в октябре прошлого года, похоже, после того, как я на форуме об этом написал, эту док-цию исправили в файле "Интерпретатор языка Lua.pdf", но почему-то не исправили в файле QLUA.chm, который входит в Квик, поэтому я об этом узнал только сейчас.
Мне кажется, Квик формирует эти таблицы от коллбэков в коде на Си++, а на стороне клиента тоже ведь могут работать длл на Си.
Я ещё в прошлом году предлагал вместо этой таблицы от getQuoteLevel2, на построение которой тратится куча времени, передавать параметры в строке через разделители. Сделать для этого getQuoteLevel2Ex. getQuoteLevel2 в длл является бутылочным горлышком, которое тормозит работу: надо создавать строки, интернировать их, считать хеши... Но, конечно, этого, как всегда, не сделают.
Мне кажется, Квик формирует эти таблицы от коллбэков в коде на Си++, а на стороне клиента тоже ведь могут работать длл на Си.
Я ещё в прошлом году предлагал вместо этой таблицы от getQuoteLevel2, на построение которой тратится куча времени, передавать параметры в строке через разделители. Сделать для этого getQuoteLevel2Ex. getQuoteLevel2 в длл является бутылочным горлышком, которое тормозит работу: надо создавать строки, интернировать их, считать хеши... Но, конечно, этого, как всегда, не сделают.
Уу финама есть такая штука называется TRANSAQ Когда-то делал на ней робота. Вещь хорошая но тогда была еще сырая и было много глюков Потом ушел от них а TRANSAQ только их. Так вот в TRANSAQ передаются лишь изменения стакана. т е хотите сами стройте что угодно или не стройте. -------------------- В QUIK создали библиотку QLUA как мост бежду VMLUA и терминалом. Это не библиотека для написания роботов а скорее библиотека для написания отображения каких -то не сложных вычислений на экране. Поэтому все так.
QUIK clients support
Сообщений: Регистрация: 11.08.2025
23.04.2026 05:25:15
Цитата
Serge123 написал: Мне кажется, Квик формирует эти таблицы от коллбэков в коде на Си++, а на стороне клиента тоже ведь могут работать длл на Си.
Я ещё в прошлом году предлагал вместо этой таблицы от getQuoteLevel2, на построение которой тратится куча времени, передавать параметры в строке через разделители. Сделать для этого getQuoteLevel2Ex. getQuoteLevel2 в длл является бутылочным горлышком, которое тормозит работу: надо создавать строки, интернировать их, считать хеши... Но, конечно, этого, как всегда, не сделают.
Правильно понимаем, что вы уже регистрировали пожелание на доработку будущих версий? Если нет, то предлагаем сделать это сейчас.
Пользователь
Сообщений: Регистрация: 27.12.2022
27.04.2026 23:39:40
Цитата
Oleg Kuzembaev написал: Правильно понимаем, что вы уже регистрировали пожелание на доработку будущих версий? Если нет, то предлагаем сделать это сейчас.
Я только помню, что давно высказал такое пожелание. Поэтому, на всякий случай (а вдруг сделают) зарегистрируйте пожелание: сделать функцию getQuoteLevel2Ex аналогичную getQuoteLevel2, но чтобы она возвращала результат в строке. Напр., пусть в настройках Квика глубина стакана = 4. Тогда, к примеру, по тикеру LKOH возвращалось бы
Вообще-то аналогично можно также таблицу alltrade для ускорения обработки возвращать тоже в виде строки, но там много параметров (которые нужны не все).
Ваше пожелание зарегистрировано. Мы постараемся рассмотреть его и сообщить Вам результаты анализа. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожелания в будущих версиях ПО.
Пользователь
Сообщений: Регистрация: 27.12.2022
28.04.2026 22:25:02
Вот ещё вопрос возник: что по правилам Квика возвращает getQuoteLevel2, если 1) вызвать его с ошибочными данными, 2) если пришёл OnQuote перед окончанием вечерней сессии, а getQuoteLevel2 по этому коллбэку был вызван уже после её окончания? В документации этого нет. Возвращает ли в каких-то случаях getQuoteLevel2 вместо таблицы nil, или всегда возвращается таблица, но в этом случае в ней будет одна dummy нода (нода типа nil)?
Пользователь
Сообщений: Регистрация: 27.12.2022
03.05.2026 22:22:44
Кстати, в глобальной таблице _G уже есть недокументированная функция getQuoteLevel2Ex.
1. В этом случае ответ придет таким же, как при отсутствии данных. 2. Если терминал успеет получить информацию о котировках после вызова OnQuote, то вызов getQuoteLevel2 выдаст актуальные данные. В противном случае - как в п.1
Пользователь
Сообщений: Регистрация: 09.09.2022
12.05.2026 19:09:33
Цитата
Serge123 написал: Нормальному человеку трудно представить, как можно написать в док-ции, что bid имеет тип TABLE, но может возвращать пустую строку...
Из армейского фольклора: "В военное время величина синуса может достигать четырёх".
Это вы конечно смешно написали) Тоже удивлялся такому подходу с возвращением пустой строки. Но может по их внутренней логике так было проще, чем специально нилить поля таблицы. Да это же и не критично на самом деле. Достаточно же просто проверить варианты на пустую стоку, каунты на ноль, Ну и на nil проверьте если что. А вот зачем вариант со строками, где все цены и лоты в одну строку? Потом самому парсить эту строку в цикле? Потом из цикла всё это распихивать по своим таблицам или переменным? Зачем? Вам дана уже готовая таблица. Пользуйтесь. Если вам нужна компактность, сохранение, ну так кто мешает написать свои функции и из готовых таблиц слепить себе нужные строки? Ваш вариант будет ещё хуже, так как надо будет разбирать строки на отдельные данные через регулярки, это ещё дольше, чем у них на сях там всё уже по полочкам разложено.
Мне кажется, Квик формирует эти таблицы от коллбэков в коде на Си++, а на стороне клиента тоже ведь могут работать длл на Си.
Я ещё в прошлом году предлагал вместо этой таблицы от getQuoteLevel2, на построение которой тратится куча времени, передавать параметры в строке через разделители. Сделать для этого getQuoteLevel2Ex. getQuoteLevel2 в длл является бутылочным горлышком, которое тормозит работу: надо создавать строки, интернировать их, считать хеши... Но, конечно, этого, как всегда, не сделают.
Я конечно не знаю внутреннюю кухню организации работы getQuoteLevel2 внутри qlua. Но думаю, что всё там организовано именно так, как надо. Есть некий буфер, куда валятся данные котировок с сервера. Построена таблица, со ссылками на элементы таблицы. Вам возвращается ссылка на эту таблицу. Что вам ещё нужно? Какое узкое горлышко? Вам нужно внутри dll? Создавайте цикл, к примеру так:
Фактически и на стороне квика всё просто, у них идёт поток данных в буфер, и вы просто берёте нужные данные и делаете с ними что хотите, они уже в чистом виде вам даны. А так вам надо будет ещё дополнительно функции писать на разбор строк!
Пользователь
Сообщений: Регистрация: 30.01.2015
13.05.2026 06:05:13
Если рассматривать прямой доступ к данным биржи (минуя торговый терминал вроде QUIK),
то информация о заявках передается в виде потока сырых событий в бинарных протоколах,
а не в виде привычной таблицы «стакана».
Основной протокол для получения рыночных данных на Московской бирже — FAST (FIX Adapted for Streaming) .
Вы не получаете «готовый стакан» одной командой.
Вместо этого биржа присылает поток сообщений, по которым ваш алгоритм должен самостоятельно «собрать» и поддерживать актуальное состояние стакана.
Формат данных: поток событий (Market Data)
Вся информация передается через два типа сообщений :
Snapshots (Снэпшоты): Полный «слепок» текущего состояния стакана на определенный момент. Пригодится для первоначальной синхронизации.
Incremental messages (Инкрементные обновления): Сообщения об изменениях, которые приходят в режиме реального времени. Именно они составляют основную массу трафика.
Биржа предоставляет два дублирующих друг друга потока инкрементных обновлений — поток A и поток B (для отказоустойчивости) .
Структура инкрементного сообщения
Сообщение FAST содержит информацию о том, какое именно событие произошло. На основе этих событий вам нужно обновлять свою копию стакана. События бывают трех типов:
Новая заявка (Add Order):
ID заявки (уникальный идентификатор)
Направление (покупка / продажа)
Цена
Объем
Время
Исполнение заявки (Trade / Order Executed):
ID заявки (или нескольких заявок)
Объем сделки
(Если заявка исполнилась частично — нужно уменьшить ее объем; если полностью — удалить ее из стакана).
Удаление заявки (Order Delete / Cancel):
ID заявки (заявка была снята или аннулирована).
Важный нюанс: В сыром потоке присутствуют все заявки, включая «айсберг» — они видны в полном логе как одна заявка с полным объемом, но сам стакан (публичный) обычно видит только видимую часть . Также стакан может показывать не все заявки рынка, а ограниченный диапазон цен (например, до 50 пунктов от лучшей цены) .
FAST — это бинарный протокол сжатия данных на основе словарей. Чтобы декодировать поток, вам понадобятся файлы-шаблоны (templates.xml), которые биржа публикует на своем сайте .
Суффикс FIX в названии означает, что формат полей сообщений похож на стандарт FIX, но сам протокол передачи — бинарный и сжатый, а не текстовый.
Как выглядит сборка стакана на практике
Если вы пишете алгоритм, логика будет такой:
Подключиться к потоку (через платный доступ или в зоне колокации).
Получить Snapshot — начальное состояние стакана.
Читать Incremental сообщения:
Пришло Add → добавить заявку в нужную сторону (Buy/Sell).
Пришло Executed → уменьшить объем у заявки с таким ID или удалить её.
Пришло Delete → удалить заявку.
Агрегировать имеющиеся заявки по ценам: сложить все объемы заявок с одинаковой ценой. Результат этого агрегирования и есть тот самый стакан (OrderBook), который вы видите в терминалах .
Альтернативные варианты получения данных
MOEX ALGOPACK (через API): Это более современный и высокоуровневый платный продукт, который отдает уже готовые данные, включая агрегированный стакан (OrderBook), минуя низкоуровневую работу с FAST .
Файлы отчетов (Reports): Биржа также публикует отчеты в формате XML (схемы XSD) с историческими данными о заявках и сделках, например, SEM02 (реестр заявок на срочном рынке) . Это для post-trade анализа, а не для real-time.
Терминалы (QUIK, Транзакция): Если использовать скрипты на QLua ( getQuoteLevel2 ), то терминал уже сделал всю эту тяжелую работу за вас, агрегировав поток в таблицу . Это самый простой способ для частных трейдеров.
Если вы планируете писать своего торгового робота напрямую, стоит изучить разделы для разработчиков на сайте Московской биржи (например, страницы, посвященные рынку акций и срочному рынку). Если же вас интересует просто разбор стакана в терминале, то скрипты QLua — вполне рабочий вариант.
На прямых биржевых потоках время заявок есть (и с очень высокой точностью), а в статичных API или скриптах QLua — нет.
Способ 1: Прямые потоки биржи (Multicast FAST)
Если вы подключаетесь непосредственно к потокам рыночных данных Мосбиржи через протокол FAST, информация о времени присутствует. Каждое инкрементное сообщение (содержащее новую заявку, исполнение или удаление) включает временную метку .
Ключевая особенность — высокая точность:
На рынке акций: время передается с точностью до микросекунды (1 мкс = 0.000001 c) .
Срочный рынок (спектры): данные могут передаваться с точностью до наносекунды .
Поля и форматы: В сообщениях FAST время содержится в специальных полях:
MDEntryTime: текущее время события. В формате HHMMSSsssssssss (часы, минуты, секунды и 9 знаков для наносекунд) .
MDEntryDate: календарная дата события (добавлено в версии FAST v.5.1 в 2025 году для однозначной идентификации даты) .
SendingTime: время отправки сообщения биржей (также может быть указано) .
Пример, как выглядит значение MDEntryTime в коде: text 132230123456789 где: 13:22:30.123456789 Способ 2: Терминал QUIK и функция getQuoteLevel2
Если вы используете функцию getQuoteLevel2 в скриптах QLua, то получить время, когда каждая конкретная заявка попала в стакан, невозможно.
Эта функция возвращает только агрегированную информацию о текущем состоянии стакана: суммарный объем на каждом уровне цены. Она не предоставляет данных об отдельных заявках или времени их появления. Вы можете только относительно судить о возрасте заявки (чем ближе к лучшей цене, тем она, вероятно, "новее"), но точного времени вы не узнаете.
Если вам критично знать время заявок, то QLua не подходит для этого.
Способ 3: ISS API (например, через библиотеку moex-data-fetcher)
Публичный REST API Мосбиржи (ISS) предназначен для получения статистики и итогов торгов, но не предоставляет данные о стакане (Order Book) в реальном времени или с историей по заявкам.Вы можете получить исторические данные по сделкам, индексам и параметрам инструментов , но информацию о лимитных заявках и их времени, которые находились в стакане, этот API не отдает.