Александр Правилов
Александр Правилов личный блог
22 марта 2017, 10:29

События в QLua

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

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

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

1. Есть ли возможность как-то подписаться на событие получения, к примеру, новой котировки, а не перезапускать цикл через n-млсекунд постоянно?
2. Есть ли интерфейс подключения к квику, чтобы программировать не через lua, а, например на c#?
25 Комментариев
  • Igr
    22 марта 2017, 10:40

    quikluacsharp.ru/

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

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

      • Igr
        22 марта 2017, 10:51
        Александр Правилов, не знаю, по моему всё верно, захожу по ссылке 
  • Karim
    22 марта 2017, 11:17
    1. Да, возможность есть

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

      • Karim
        22 марта 2017, 11:46
        Александр Правилов, Документация по Quik, раздел по QLua.
        Просторы инета, например https://quikluacsharp.ru/bez-rubriki/s-chego-nachat/
  • sortarray sortarray
    22 марта 2017, 11:22
    Обычно в цикле пишут 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
    Не факт что эта фича там есть. Поинтересуйтесь у техподдержки на эту тему
  • Дмитрий
    22 марта 2017, 11:38
    По первому вопросу, функция обратного вызова OnAllTrade(alltrade), из описания: «Функция вызывается терминалом QUIK при получении обезличенной сделки».
    Один нюанс, в quik должна быть открыта таблица обезличенных сделок с необходимым инструментом.
    это к примеру, а так есть несколько функций обратного вызова, они описаны в документации
  • Prophetic
    22 марта 2017, 12:32
    Не знаю о каких примерах идет речь, но когда я писал роботов на QLua, то для событийной модели обязательный sleep нужен был только в Main(), дабы робот не загружал процессор на 100%, т.к. Main() был совсем крохотным кусочком кода. Также, например, при подписке на свечки, я ставил sleep, т.к. квику требовалось некоторое время на получение данных и их запись в таблицу. Если попытаться проверить наличие данных сразу после подписки, то часто получал nil.
    • Дмитрий
      22 марта 2017, 14:26
      Александр Правилов, не можно, а нужно отдельно.
        • Дмитрий
          23 марта 2017, 08:10
          Александр Правилов, попробуйте

          function OnDisconnected()
               message('Disconnected')
          end

          function OnStop(s)
               bStopped = true
          end

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

  • Чарльз Маккей
    22 марта 2017, 14:49
    Вы лучше подскажите всем, когда разберетесь, как определить оптимальный n. Или задать динамический n (если это возможно).
  • Борис Гудылин
    22 марта 2017, 18:30

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

    Если очень кратко, то примерно так — примите во внимание наличие в 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 показывал).
      • Борис Гудылин
        23 марта 2017, 12:03
        Александр Правилов, вопрос 1 у Вас хороший, мало кто им задается. Кажется, я такого и не встречал здесь. 
  • buybackoff
    22 марта 2017, 18:35
    По пункту 2 Вам сюда: https://github.com/finsight/QUIKSharp
  • Павел Валин
    23 марта 2017, 09:37
    по второму пункту S#.API и только он) всё остальное чудовые рыдания.
    Придётся повозиться с документацией и форумом, т.к. есть не очевидные вещи, с которыми наскоком не разобраться) но если разобраться, даёт неограниченные возможности.
      • Павел Валин
        23 марта 2017, 11:22
        Александр Правилов, http://stocksharp.ru/
        если что пиши в личку, помогу чем смогу
          • Павел Валин
            23 марта 2017, 19:03
            Александр Правилов, давно уже через lua коннектор работает) я DDE даж не застал)))

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн