Блог им. Helsk

События в QLua

Добрый день, друзья!

Изучаю QLua, посмотрел несколько примеров, в том числе у Albus'a.
Обычно в цикле пишут sleep(n), при обновлении котировок или любых других значений.

Вопрос к опытным кулуйстам:

1. Есть ли возможность как-то подписаться на событие получения, к примеру, новой котировки, а не перезапускать цикл через n-млсекунд постоянно?
2. Есть ли интерфейс подключения к квику, чтобы программировать не через lua, а, например на c#?
| ★2
25 комментариев

quikluacsharp.ru/

вот, тут всё расскажут, подскажут 

на сколько я понимаю на оба вопроса ответ  - да

avatar
Igr, видно ссылка неправильная. 
Александр Правилов, не знаю, по моему всё верно, захожу по ссылке 
avatar
1. Да, возможность есть

DataSource = CreateDataSource(ClassCode, SecCode, INTERVAL_M1) — подписываемся на источник данных
DataSource:SetUpdateCallback(CallBackDataSource) --назначаем функцию обратного вызова
2. Стандартного интерфейса в квике нет. Нужно писать «прокладку» на С++ для передачи необходимых данных в прогу на С#.

avatar
Karim, есть где-то литература по этому, примеры может посмотреть?
Александр Правилов, Документация по Quik, раздел по QLua.
Просторы инета, например https://quikluacsharp.ru/bez-rubriki/s-chego-nachat/
avatar
Обычно в цикле пишут sleep(n), при обновлении котировок или любых других значений.

Я не клуист, но судя по этой логике, если бы была возможность подписки на событие, так бы и делали, просто вешали бы коллбек на событие. Скорей всего, там котировки получаются по запросу на сервер. То бишь, pull-технология, она самая распространенная на текущий момент, даже в вебе.
ru.wikipedia.org/wiki/%D0%A2%D0%B5%D1%85%D0%BD%D0%BE%D0%BB%D0%BE%D0%B3%D0%B8%D1%8F_pull
Смотрите какой в цикле запрос.
Для того, чтобы было то что Вы хотите в чистом виде, нужно чтобы сервер квика сам рассылал обновления котировок.
ru.wikipedia.org/wiki/%D0%A2%D0%B5%D1%85%D0%BD%D0%BE%D0%BB%D0%BE%D0%B3%D0%B8%D1%8F_push
Не факт что эта фича там есть. Поинтересуйтесь у техподдержки на эту тему
avatar
По первому вопросу, функция обратного вызова OnAllTrade(alltrade), из описания: «Функция вызывается терминалом QUIK при получении обезличенной сделки».
Один нюанс, в quik должна быть открыта таблица обезличенных сделок с необходимым инструментом.
это к примеру, а так есть несколько функций обратного вызова, они описаны в документации
avatar
Не знаю о каких примерах идет речь, но когда я писал роботов на QLua, то для событийной модели обязательный sleep нужен был только в Main(), дабы робот не загружал процессор на 100%, т.к. Main() был совсем крохотным кусочком кода. Также, например, при подписке на свечки, я ставил sleep, т.к. квику требовалось некоторое время на получение данных и их запись в таблицу. Если попытаться проверить наличие данных сразу после подписки, то часто получал nil.
avatar
Для вызова колбэков их необходимо прописывать в main?
Например OnDisconnected(), можно просто отдельно прописать и он вызовется при разрыве соединения или его необходимо указать и в main?
Александр Правилов, не можно, а нужно отдельно.
avatar
Дмитрий, Вот что-то не срабатывает :(
Александр Правилов, попробуйте

function OnDisconnected()
     message('Disconnected')
end

function OnStop(s)
     bStopped = true
end

function main()
     bStopped = false
     while not bStopped do
          sleep(100)
     end
end

avatar
Дмитрий, уже разобрался, всё ок :) 
Вы лучше подскажите всем, когда разберетесь, как определить оптимальный n. Или задать динамический n (если это возможно).

Интересно, поймут ли меня сейчас?

Если очень кратко, то примерно так — примите во внимание наличие в QUIK независимых потоков Windows, претендующих на использование процессора(ов) ПК.

Все индикаторы (OnCalculate) и все асинхронные выходы (OnStop, OnTrade, OnConnect, OnTransReply, …, много их там) вызываются-выполняются после возникновения каких-либо событий (связь ли разорвалась, в стакане что-то поменялось, ...) последовательно в одном (основном) потоке QUIK. По этой причине крайне нежелательно загружать этот поток длительной обработкой – можно серьезно затормозить работу QUIK, а при зацикливании, например, индикатора – вовсе блокировать. 

Все скрипты (main) выполняются каждый в своем отдельном потоке, с претензией на параллельность, насколько это позволяют аппаратные возможности ПК (многоядерность) и возможности Windows по разделению времени процессора(ов) между потоками-претендентами. 

Синхронизация потоков и совместная обработка общих данных требует определенной аккуратности от программиста.
Одно дело – когда основной поток в рамках отработки асинхронного выхода OnStop просто взведет где-то флажок, а скрипт его заметит.

Другое – когда в основном потоке и в скрипте (main) вы обновляете одни и те же таблицы или пишете в один и тот же файл – приключения вам гарантированы. Рано или поздно возникнет ситуация, когда вы частично (не до конца) обновили совместно используемый ресурс, но вдруг ваш поток на полуслове прервали, а поток, который получил управление, прошелся своим обновлением по этому же ресурсу. Что получится, когда первый поток снова получит управление и завершит обновление ресурса – непредсказуемо.  

Поэтому обычно используют схему периодического засыпания-просыпания скрипта (sleep) со сканированием таблиц QUIK, а возможности асинхронных выходов используются по минимуму. Для передачи данных между основным потоком и скриптом разработчики дали несколько потокобезопасных функций: sinsert, sremove,sconcat.

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

Можно устранить этот дефект с помощью нескольких фукций API Windows.
Например, скрипт (main) ждет наступления какого-либо события с помощью функции WaitForMultipleObjects (в ней есть и отсчет временного интервала), а асинхронные выходы оповещают main о наступлении событий с помощью функции SetEvent. Дополнительно потребуются функции CreateEvent, ResetEvent, CloseHandle.

С уровня LUA эти функции доступны через использование w32.dll. Подробно см. “Вызов WinAPI функций в Lua” (https://quik2dde.ru/viewtopic.php?id=78) .

Если не было опыта работы в многозадачных средах, то придется что-то почитать, типа “Многопоточность и синхронизация. Процессы и потоки” (http://www.kurzenkov.com/Articles/multithreading1.html)

Вполне приличный простой потокобезопасный движок для робота получается, события не пропускаются и нет холостых ходов. LUA + несколько DLL (еще одна на С++ может потребоваться для ускорения мощной арифметики).

Предварительную быструю фильтрацию событий можно делать и в программах асихронных выходов. Например, заказывая источник данных (CreateDataSource) и функцию асинхронного выхода (обратного вызова, SetUpdateCallback), я передаю из нее в скрипт (main) через sinsert/sremove (данные) и SetEvent (событие) только около 10% изменений текущей свечки.


P.S. Еще где-то встречал полезную testc.dll, одна из функций — GetCurrentThreadId (узнать идентификатор потока), для ориентации в многопоточности. О, она и в w32 есть!

В QUIK исследователькой работы очень много, но для программиста это преодолимо.

Кстати, WaitForMultipleObjects ожидаемо используется в самом QUIK (taskinfo показывал).
Борис Гудылин, вчера как раз читал про потоки :)
Александр Правилов, вопрос 1 у Вас хороший, мало кто им задается. Кажется, я такого и не встречал здесь. 
Борис Гудылин, получать котироку по факту прихода намного важнее нежели перезапускать цикл, особенно когда нужно быстро реагировать 
По пункту 2 Вам сюда: https://github.com/finsight/QUIKSharp
avatar
по второму пункту S#.API и только он) всё остальное чудовые рыдания.
Придётся повозиться с документацией и форумом, т.к. есть не очевидные вещи, с которыми наскоком не разобраться) но если разобраться, даёт неограниченные возможности.
avatar
Павел Валин, есть рекомендации по форумам? Ссылки? или Литература?
Александр Правилов, http://stocksharp.ru/
если что пиши в личку, помогу чем смогу
avatar
Павел Валин, стокшарп вроде через dde сервер делал коннект с квиком… Посмотрю, чего там есть нынче 
Александр Правилов, давно уже через lua коннектор работает) я DDE даж не застал)))
avatar

Читайте на SMART-LAB:
Облигации на пальцах: как устроен главный инструмент инвестора
Если у вас все еще нет облигаций в портфеле — вы либо неверно инвестируете, либо не совсем понимаете, зачем они нужны и по какому принципу...
Фото
Каждый инвестор желает знать, где сидит доходность? Взгляд Goldman Sachs на инвестиции до конца года
Если вы инвестируете свой капитал на фондовом рынке, то каждый год легко может принести вам как большие потери, так и несметные богатства....
Фото
💡 ГК «Мать и дитя»: тренд на долгосрочный рост
🔹 Группа компаний «Мать и дитя» — качественная идея в несырьевом секторе российского рынка. По мнению начальника управления торговых операций ВТБ...
Фото
Башнефть: есть шанс на переоценку, но нужно запастись терпением. Прогноз сошелся с фактом в высокой точностью, ищем инвест идею
Башнефть отчиталась по МСФО за 2025 год — внимание, квартальных отчетов в прошлом году не было вообще! Традицицинно сравниваем прогноз...

теги блога Александр Правилов

....все тэги



UPDONW
Новый дизайн