Тема: Советы по написанию Lua-роботов от профессионалов
На форуме QUIK наткнулся на совершенно шикарный список советов про создание скриптов на Lua от пользователя _sk_
Скопирую сюда.
Что надо продумать при создании торгового робота на Lua
Порядок OnTransReply -> OnTrade -> OnOrder обычно соблюдается, но может нарушаться. Программу надо писать так, чтобы она работала всегда. Вы ведь не хотите получить внезапно ошибку и убыток из-за неё.
Многократные ответы OnTrade() появились в 7-й версии. В повторных ответах могут добавиться некоторые поля.
Функция sendTransaction() может успешно выполниться, а OnTransReply() не придёт. Такое бывает, но очень редко. Однако, программу надо писать так, чтобы она работала всегда.
С асинхронностью нужно разобраться сразу и навсегда, чтобы не словить внезапных глюков. Один из способов такой: при получении коллбэка передавать данные через очередь из потока коллбэков в поток main(). В потоке main() периодически проверять очередь и обрабатывать данные, которые из неё приходят.
Проблему можно решить без участия команды QUIK. Надо прочитать документацию, разработать модель, запрограммировать её. Форум поможет при решении более тонких вопросов.
Основные шаги реализации примерно такие.
1) Нужны статусы заявок типа WAITING (ещё не отправлена), EXECUTING (отправлена на биржу), STOPPING (снимается, но не вся информация дошла), STOPPED (снята), EXECUTED (исполнена полностью), KILL_REJECTED (kill-заявка отвергнута), ERROR (ошибка).
2) Нужны таймауты для борьбы с неопознанными "посторонними" заявками (от других скриптов), а также заявками, для которых не пришёл OnTransReply().
3) Нужно следить за UID экземпляра QUIK, чтобы фильтровать "чужие" заявки.
4) Нужна функция генерации уникальных номеров транзакций, обеспечивающих непересекающиеся множества transId для разных скриптов.
5) Нужна таблица актуальных limit-заявок, куда заявка попадает при успешном вызове sendTransaction(), а удаляется при полном или частичном исполнении и ошибках.
6) Нужна таблица актуальных kill-заявок, куда заявка попадает при попытке снять limit-заявку, а удаляется при ошибках и исполнении.
7) Нужна таблица ответов о сделках на актуальные limit-заявки.
8) Нужен фильтр событий от "чужих" OnTrade(), например, работающий по комментарию к заявке.
9) В limit-заявке нужно помнить volume, volumeTraded, volumeLeft. Обычно volumeTraded + volumeLeft == volume, но иногда при снятии частично исполненной заявки становится понятно, чему равен volumeLeft и надо дождаться событий OnTrade(), которые ещё пока не пришли. При приходе OnTrade() нужно отбрасывать дубликаты (в 7-й версии) и корректировать volumeTraded, volumeLeft. Как только volumeLeft == 0, так удалять заявку из таблицы актуальных вместе со всеми связанными с ней kill-заявками и ответами на них.
10) При попытке снять limit-заявку иногда надо ждать, чтобы понять, какой order_num у отправленной заявки, поскольку ещё мог не придти ответ OnTransReply().
11) Периодически проверять, не стали ли известны order_num для лимитных заявок, для которых есть kill-заявки.
12) Периодически проверять, не стало ли известно, каким лимитным заявкам соответствуют OnTrade(), которые пришли раньше, чем OnTransReply().
13) Периодически разбираться с тем, сработали ли отправленные kill-заявки.
14) Удалять старые "неопознанные" сделки.
15) Реагировать на OnTransReply(), связывая transId скрипта и order_num биржи для limit-заявок. Понимать, как сработали kill-заявки. Проверять ждущие kill-заявки, если они есть.
16) Реагировать на OnTrade(), игнорируя дубликаты, логгируя соответствующие сделки.
17) Реагировать на OnOrder(), связывая transId скрипта и order_num биржи для limit-заявок. Понимать, что для некоторых уже неактивных заявок не дошли OnTrade() и логгировать сообщения об ошибках.
18) Периодически обрабатывать kill-заявки, чтобы понять, какие из них остались без OnTransReply(). Посылать новые, если что.
19) Периодически обрабатывать limit-заявки, чтобы понять, для каких из них получились кросс-сделки, а какие остались без OnTransReply(). Проверять, limit-заявки, которые почему-то неактивны, а volumeLeft не равен 0, и логгировать ошибки.
Как-то так.