26

Re: Общие вопросы по написанию скриптов LUA.

Всё ужасно))
У меня была такая проблема, когда рядом начали строить торговый центр. Логи всегда были битыми после короткого замыкания и боты не запускались. Есть еще вариант, когда не получилось торговать дня 2-3, тогда Ваша 100% система рухнет без лога.

Делается просто - запись в 2 файла в таком порядке:
  если Второй! файл не записался, то есть корректный первый и бот запустится.
  если Первый! записался - второй удаляем.

На старте бот считывает Первый файл, если не успешно - Второй. Бот запустится Всегда.
Естественно, после запуска бота нужно проверить запись в файле с реальными данными в таблицах, если таковые есть, но это не долго.

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

И да, никогда не  открывайте шорт, как бы этого не хотелось. Лонг - потеряешь свои, а шорт - убыток не ограничен ничем.

27 (2022-10-16 12:36:13 отредактировано dark184)

Re: Общие вопросы по написанию скриптов LUA.

когда не получилось торговать дня 2-3, тогда Ваша 100% система рухнет без лога.

Да в общем то не рушится, было дело и неделю не торговал. Запустился без всяких логов и все роботы до единого восстановили свое предыдущее состояние... Дело в том, что таблица "depo_limits" вообще ни от чего не зависит, ей глубоко все равно на прихоти брокера, разрывы соединения, синие экраны... При восстановлении соединения в ней появляется весь мой портфель и вся необходимая мне информация, в том числе и заблокированные инструменты под покупку/продажу. В общем я сначала читаю таблицу заявок, всю, не обращая внимания на статус заявок и восстанавливаю уникальный идентификатор(если в таблице присутствуют заявки в любом статусе, то нахожу наибольший идентификатор и восстанавливаю, если же таблица пуста, то нумерация сначала, ибо мне уже наплевать каким был последний, заявок то больше не существует). После чего читаю "depo_limits" и делаю соответствующие выводы о предыдущем состоянии робота. Почему я могу сделать выводы? Потому что именно таким образом у меня все построено. Элементарная логика. Робот не может торговать на интуиции, он строго следует заданной мной логике, поэтому и восстановить состояние робота только по "depo_limits" не составляет проблем. Таблица заявок нужна только для восстановления идентификатора в случае, если все таки заявки имеются(например после синего экрана смерти в течение одного торгового дня или вылета квика). Мне даже не нужен статус заявки знать, наличие активных заявок определяю по "depo_limits". А вот если таблица "depo_limits" ненадежна, то грошь цена такому терминалу или брокеру! Ибо она работает с реальными деньгами, хоть и электронными! Потеря данных из этой таблицы равносильна воровству! Так что как не убеждайте логгировать, пока сбоев именно в этой таблице не обнаружил. Да, из таблицы заявок данные держатся исключительно один торговый день, не более. Но и она мне нужна только чтобы определить, продолжать ли нумерацию с последнего или начинать сначала.
Другое дело, что я в долго и среднесрок торгую вручную, а вот роботы заточены исключительно на интрадей, ибо вручную торговать уходит слишком много времени. Да, я стараюсь роботами не переносить сделки на следующий день, но если это случается, на следующий торговый день робот запустится, но будет в режиме ожидания. Ибо одно из условий запуска робота, это пустой портфель по его инструменту... Вот здесь уже я сам решаю что мне делать, закрывать сделку или оставлять и замораживать деньги...

У брокера всегда есть рубильник, который отрубает клиентов от торгов,

есть такое, не спорю, по два три и больше раз за день может отрубать. Роботы восстанавливаются без проблем. Другое дело что нужно успеть вовремя обратно подключиться вручную. С другой стороны, на стационарном компьютере было дело и каждый час брокер принудительно рвал соединение... Пару недель назад перешел на ноут, брокер стал рвать соединение только в конце торгового дня, что то в районе 23:45 - 23:50. Почему не знаю.

28

Re: Общие вопросы по написанию скриптов LUA.

я понял, вы размышляете, как пользователь одной единственной стратегии.
когда у вас появится 2 стратегии, которые могут торговать на одном инструменте, тогда вы пересмотрите свой подход.

если пк часто рвет соединение, снесите винду и не ставьте всякий шлак-ПО на пк.

29 (2022-10-16 18:39:46 отредактировано dark184)

Re: Общие вопросы по написанию скриптов LUA.

я понял, вы размышляете, как пользователь одной единственной стратегии.

Ну да, один робот одна стратегия. Хотя... Вы мне подкинули идею как совместить хоть сколько стратегий в одном роботе smile Взял на заметку smile С другой стороны я уже на двух инструментах торгую по двум разным стратегиям, но там принцип, если по одной стратегии есть вход в сделку, то ждем закрытия сделки. Т.е. по принципу "кто первый встал, того и тапки". Так что это нельзя назвать полноценной торговлей по двум стратегиям, скорее это "полудуплекс".

30

Re: Общие вопросы по написанию скриптов LUA.

dark184 пишет:

Ну да, один робот одна стратегия. Хотя... Вы мне подкинули идею как совместить хоть сколько стратегий в одном роботе smile

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

31

Re: Общие вопросы по написанию скриптов LUA.

успехов вам.

Спасибо. Пока роботы три дня подряд закрывали все сделки с профитом. Правда что интересно, по факту моя стратегия показывает лучшие результаты на падении, чем на росте, причем играю в лонг, шорта нет smile Парадоксально, но факт! Надо бы доработать и на рост smile

32

Re: Общие вопросы по написанию скриптов LUA.

В очередной раз столкнулся с проблемкой. Мой скрипт в процессе работы читает таблицу "depo_limits", как я понимаю это Таблица лимитов по бумагам. Но, данные в этой таблице очень похоже обновляются с большой задержкой, даже если дождаться OnOrder(), а он у меня срабатывает три раза на одну заявку, данные все три раза приходят еще предыдущие. Т.е., например портфель пустой, выставляю заявку на покупку, дожидаюсь OnOrder() и из нее читаю таблицу "depo_limits" и получаю что currentbal = 0, locked_buyl = 0(а должен быть не ноль, а количество выставленное на покупку, в моем случае пусть будет 1). Причем читаю ее именно уже в OnOrder(), срок расчетов Т2, в общем все верно, ибо данные идут корректные, но позже. Далее заявка исполняется полностью, приходит OnOrder() и опять читаю таблицу currentbal = 0, locked_buyl = 1(а должно быть уже наоборот). И точно таким же образом все остальные циклы... Что это? Отсюда рушится весь алгоритм, причем рушится как на демо счете, так и на реальном. Придется отказываться? Кстати, из "depo_limits" вся информация читается абсолютно корректно, ибо использую ее для восстановления состояния робота при запуске/перезапуске, разрывах соединений, после начала очередной сессии торгов и прочее. Вот здесь она работает абсолютно корректно.
Отсюда вопрос, могу ли я доверять флагам OnOrder()? Просто там нет нужной мне информации, в частности о блокированных инструментах на покупку/продажу.

33

Re: Общие вопросы по написанию скриптов LUA.

Извиняюсь, совсем забыл. Есть еще таблица "состояние счета". Там есть нужная мне информация, но как к ней обратиться? Т.е. в квике заголовок таблицы "состояние счета", а вот как к ней обратиться из скрипта?
К таблице лимитов по бумагам, из которой я сейчас и беру нужные мне данные я обращаюсь так

    local n = getNumberOf("depo_limits")
        local quantity    = 0
    local price        = 0
    local block_s    = 0
    local block_b    = 0
    local y            = 0
    for y = 0, n-1 do
        trade = getItem("depo_limits", y)
        if    (trade.client_code == CLIENT_CODE)    and
            (trade.sec_code ==    SEC)            and
            (trade.trdaccid == TRADE_ACC)        and
            (trade.limit_kind == _KIND)                then
                quantity    = Rounding(trade.currentbal, 0)
                price        = Rounding(trade.wa_position_price, PRICE_SCALE)
                block_s        = Rounding(trade.locked_sell, 0)    
                block_b        = Rounding(trade.locked_buy, 0)
                break
        end
    end

Т.е. таблица лимитов по бумагам это "depo_limits", а состояние счета бог знает что...

34

Re: Общие вопросы по написанию скриптов LUA.

К таблице состояние счета нет доступа из Lua.
С другой стороны, эта таблица не содержит уникальной информации, все что в ней есть содержится в клиентской портфеле, таблицах лимитов по деньгам и бумагам и таблицах фьючерсных ограничений и позиций.

35

Re: Общие вопросы по написанию скриптов LUA.

Вот c depo limits и работаю... Но там какая то задержка. Еще сейчас кстати, вспомнил, так как сработала заявка, в OnOrder() появляется корректная информация как придет сообщение от брокера "заявка № зарегистрирована". Вот буквально только что, было три вызова OnOrder() перед сообщением брокера(причем информация не обновилась в таблице, что логично и правильно!), затем сообщение брокера "заявка № зарегистрирована", и затем еще два раза подряд вызов OnOrder() с уже обновленными данными. Что тоже в принципе логично. НО! насколько я помню, далеко не всегда после этого сообщения вызывается OnOrder(). Хотя надо бы понаблюдать еще smile
Нельзя ли каким то образом из скрипта перехватить это сообщение брокера "заявка № зарегистрирована"? Я конечно могу и по другому подловить изменение, но это опять вычисление, хоть и простейшие до безобразия, но все таки вычисления. В идеале конечно просто словить сообщение брокера и после него уже попробовать обрабатывать.

36 (2022-10-25 13:02:06 отредактировано swerg)

Re: Общие вопросы по написанию скриптов LUA.

dark184 пишет:

Вот c depo limits и работаю... Но там какая то задержка.

Специфичная для лимитов информация быстрее чем в лимитах не появится нигде.

dark184 пишет:

Нельзя ли каким то образом из скрипта перехватить это сообщение брокера "заявка № зарегистрирована"?

Это не сообщение брокера. Это сообщение биржи в ответ на транзакцию.
Технически заявка с биржи может приехать как раньше ответа на транзакцию, так и позже. Никаrой "логичности" тут нет, это технически разные интерфейсы биржи, не связанные между собой. Соответственно робот должен это учитывать.

37

Re: Общие вопросы по написанию скриптов LUA.

Я правильно понял, что другого способа поймать обновление таблицы, кроме как запоминать предыдущее состояние и сравнивать текущее, просто нет? И даже OnOrder() здесь может вызваться как раньше обновления таблицы так и позже?

38 (2022-10-25 13:27:25 отредактировано swerg)

Re: Общие вопросы по написанию скриптов LUA.

Именно так. callback-функции могут вызываться в произвольном порядке, это надо учитывать при проектировании логики робота.

Скажу больше, вперёд всех может прийти OnTrade, если выставляемая заявка сразу сыграла.

39 (2022-10-25 13:41:00 отредактировано kalikazandr)

Re: Общие вопросы по написанию скриптов LUA.

привет!
В OnOrder, OnTrades и тем паче OnTransreply нельзя принимать решение по изменению состояния заявки.
Пока эти изменения не будут обработаны терминалом и занесены в соответствующие таблицы.

OnTransreply - заявка:
зарегистрирована - курим, ждем OnOrder;
отклонена - обрабатываем ошибку, исправляем, пытаемся выставить заявку по новой.

OnOrder - заявка:
новая - ждем блокировки лимитов под заявку, т.е. ждем запись в таблице заявок, этого достаточно;
изменение - ждем запись в таблице сделок или заявок(если снята без остатка).

Всё. по другому работать не будет.
Нужно понимать, что запись в соответствующей таблице можно обнаружить из main раньше, чем прилетит калбэк.
Т.е. все действия по заявке обрабатываются в main и нигде больше.
А калбэки нужны лишь для того, чтобы тупо не пылесосить соответствующие таблицы в main, а заглядывать в них по событию.

40

Re: Общие вопросы по написанию скриптов LUA.

swerg пишет:

Именно так. callback-функции могут вызываться в произвольном порядке, это надо учитывать при проектировании логики робота.

Скажу больше, вперёд всех может прийти OnTrade, если выставляемая заявка сразу сыграла.

не может, OnTransreply  придет первой, потом всё остальное в любом порядке.

41 (2022-10-25 13:54:24 отредактировано kalikazandr)

Re: Общие вопросы по написанию скриптов LUA.

dark184 пишет:

Вот c depo limits и работаю...

считайте лимиты самостоятельно

42

Re: Общие вопросы по написанию скриптов LUA.

kalikazandr пишет:

не может, OnTransreply  придет первой, потом всё остальное в любом порядке.

Если заявка сразу исполнится (рыночная или лимитная с ценой "лучше" рынка), то OnTransreply  запросто может прийти позже всех (и тогда и возникнет особенно много OnOrder на изменение одной и той же заявки).

43 (2022-10-25 14:22:32 отредактировано kalikazandr)

Re: Общие вопросы по написанию скриптов LUA.

swerg пишет:

Если заявка сразу исполнится (рыночная или лимитная с ценой "лучше" рынка), то OnTransreply  запросто может прийти позже всех

Спросите у арки, это не возможно, сначала OnTransreply, потом - что угодно. За 10 лет ни разу не было по другому.
А вот OnOrder и OnTrades как попало, это да.
OnTransreply может прийти намного раньше всех остальных событий, т.к. биржа ее первой отправляет пользователю и расчетов перед её отправкой нет никаких, в остальных изменениях по заявке расчеты биржа производит, хоть и быстро, но всё же.

44

Re: Общие вопросы по написанию скриптов LUA.

зарегистрирована - курим, ждем OnOrder;
отклонена - обрабатываем ошибку, исправляем, пытаемся выставить заявку по новой.

status NUMBER Статус транзакции. Возможные значения: 
«0» – транзакция отправлена серверу; 
«1» – транзакция получена на сервер QUIK от клиента; 
«2» – ошибка при передаче транзакции в торговую систему. Так как отсутствует подключение шлюза Московской Биржи, повторно транзакция не отправляется; 
«3» – транзакция выполнена; 
«4» – транзакция не выполнена торговой системой. Более подробное описание ошибки отражается в поле «Сообщение»; 
«5» – транзакция не прошла проверку сервера QUIK по каким-либо критериям. Например, проверку на наличие прав у пользователя на отправку транзакции данного типа; 
«6» – транзакция не прошла проверку лимитов сервера QUIK; 
«10» – транзакция не поддерживается торговой системой; 
«11» – транзакция не прошла проверку правильности электронной цифровой подписи; 
«12» – не удалось дождаться ответа на транзакцию, т.к. истек таймаут ожидания. Может возникнуть при подаче транзакций из QPILE; 
«13» – транзакция отвергнута, так как ее выполнение могло привести к кросс-сделке (т.е. сделке с тем же самым клиентским счетом); 
«14» – транзакция не прошла контроль дополнительных ограничений, установленных брокером; 
«15» – транзакция принята после нарушения дополнительных ограничений, установленных брокером; 
«16» – транзакция отменена пользователем в ходе проверки дополнительных ограничений, установленных брокером

Вы имеете ввиду вот это? Я вот думаю, почему этот колбэк приходит по 3-4 раза. Случаем ли дело не в этом поле? Надо бы проверить, может действительно повторяется как раз из за изменения статуса...

Согласен. Пока робот писался и все было относительно просто, изменение статусов робота прямо в колбэках не вызывало каких либо неразрешимых проблем. В принципе и проблем то особо не было smile
Но сейчас, когда робот начал обрастать дополнительными функциями, начались проблемы smile Подумываю об изменении концепции построения всего робота. Надо действительно думать как вынести практически все в майн, а колбэки оставить только как сигнальные, руководство к действию в майн, что бы попусту не шерстить то, что пока не требуется smile.

45 (2022-10-25 17:11:05 отредактировано kalikazandr)

Re: Общие вопросы по написанию скриптов LUA.

dark184 пишет:

Вы имеете ввиду вот это? Я вот думаю, почему этот колбэк приходит по 3-4 раза. Случаем ли дело не в этом поле? Надо бы проверить, может действительно повторяется как раз из за изменения статуса...

Да, смотреть нужно статус = 3, всё остальное - ошибка и нужно остановить бота и разобраться что к чему.
Этот калбэк не приходит по 3-4 раза, приходит 1 раз на новую транзакцию, если у вас 3-4 раза, значит в майн бот выставляет заявку 3-4 раза.

46

Re: Общие вопросы по написанию скриптов LUA.

Подскажите еще такой вопрос. Который день отлаживаю отработку частичного исполнения заявки на покупку. Вывожу отладочную информацию и вот по ней я делаю вывод, что OnTrade() почему то отрабатывает только на первую частичную покупку! Допустим, заявка на покупку 10 лотов. Допустим... Заявка отработала частично, пусть будет 1 лот, затем 2, затем 7. Так вот, судя по отладочной информации OnTrade() вызывается только на первой покупке 1 лота. Следующие покупки он не вызывается, у меня по крайней мере. Т.к. я только отлаживаю этот механизм, сделано только самое начало. Что либо изменить пока не сложно. У меня вопрос, так и должно быть? Если да, то придется давать пинок от OnOrder()?

47

Re: Общие вопросы по написанию скриптов LUA.

А сделки есть?
Если сделки есть и нет вызовов OnTrade - то такого не может быть.
Разбирайтесь с логированием почему не все логируется. Наверняка над логированием хитрое условием вставлено.

48

Re: Общие вопросы по написанию скриптов LUA.

Да, по факту сделки есть. Любой вызов OnTrade() выводит сообщение

message("OnTrade() Статус " .. NAME .. " " .. cur_state)

само собой если совпадает uniq_trans_id. А он остается постоянным для одной и той же заявки, пусть и исполненной частично...

function OnTrade(trade)

    if ((uniq_trans_id & 0xFF000) == (trade.trans_id & 0xFF000)) then

        if (cur_state == ("confirm_buy" or "part_buy")) then
            message("OnTrade(), Name = " .. NAME .. ", " .. "количество = " .. tostring(tonumber(math.floor(trade.qty))))

            local temp_percent =  buy_price / 100 * percent + buy_price --tonumber(cur_price.param_value)    --
            sell_price = buy_price
            while temp_percent > sell_price do
                sell_price = sell_price + PRICE_STEP
            end
            SendOrder("S", sell_price, tonumber(math.floor(trade.qty)))
            message("OnTrade() Выставлено на продажу " .. NAME .. " sell_price= " .. tostring(sell_price))
            
            if tonumber(math.floor(trade.qty)) == (portfolio * LOT_SIZE) then
                cur_state = "e_sell"
            else
                cur_state = "part_buy"
            end
        
        end

        if cur_state == "confirm_sell" then
            message("OnTrade() Все лоты проданы! ")
            cur_state = "sell"
        end
    message("OnTrade() Статус " .. NAME .. " " .. cur_state)
    end
end

Я могу предположить все что угодно, но! Сообщение

message("OnTrade() Статус " .. NAME .. " " .. cur_state)

в любом случае должно быть в случае совпадения uniq_trans_id. Да, с этой строкой

(uniq_trans_id & 0xFF000) == (trade.trans_id & 0xFF000)

есть проблема, но на время отладки я пока сделал так, не спрашивайте почему, просто старшие 8 бит отвечают именно за уникальность и я их пока отсеиваю, а вот младшие просто инкременирую и все.

49

Re: Общие вопросы по написанию скриптов LUA.

Ну т.е. вместо того, чтобы без условий в начало OnTrade вставить логированием параметров - вы вставили какое-то условие и говорите, что "не вызывается". Зачем?

50

Re: Общие вопросы по написанию скриптов LUA.

У меня больше 15 роботов запущено, если это условие не вставить там штук 50 сразу.

говорите, что "не вызывается"

Я не говорил что не вызывается, я говорил что вызывается только раз, когда заявка первый раз частично исполнится. В остальные разы не ловится.