verder написал: сразу останавливает работу скрипта во всех потоках
У скрипта один поток - мейн, второй поток, в котором выполняются колбеки - это главный поток квика.
Если вы сами создаете какие-то еще потоки, только вы и знаете, как их остановить. Вообще задача красивой остановки потока, выполняющего произвольный код, решения не имеет. Как пример потоки в c++, если в одном потоке случается unhandled exception, рушится все приложение без раскрутки стеков других потоков.
Если говорить только о стандартных потоках в квике, то вариантов два, либо ошибка в колбеке, либо в мейне. В мейне можно просто сгенерировать error и скрипт остановится. В колбеках надо выполнять все под pcall, если возникает ошибка, переправлять ее в мейн, а тот ее же бросит в своем потоке и сведет все к первому варианту. Это легко, если мейн построен как обработчик сообщений, тогда он просто вместо очередного сообщения получит сообщение об ошибке. Если в мейне свободно выполняемый код, придется периодически смотреть, не было ли в колбеках ошибки.
Чтобы в процессе распространения ошибки колбеки не продолжали посылать сообщения, можно завести глобальный флажок, устанавливаемый при любой ошибке, где бы она ни случилась. Каждый колбек в самом начале проверяет этот флажок, если установлен - просто сразу return.
nikolz написал: если бы все было так просто, то проблему многопоточности в луа не поднимали бы на форумах уже лет ..надцать.
Это именно проблемы многопоточности как таковой, а не многопоточности в луа. В приведенной статье тоже. Как раз автор пришел в конце к правильному выводу, асинхронность рулит. Надо только не забывать, что нынче практически все процессоры многоядерные, даже контроллеры многие, так что многопоточность все равно будет присутствовать, главное ее локализовать и не позволить ей разползтись по всему коду. Конкретно в квике уже отступать некуда, архитектура выбрана такая и трудно предположить, как ее можно обратно-совместимо поправить. Теперь только костыли лепить.
MOEX Фьючерсы. Открытые позиции intraday, Мосбиржа тестирует фишку которая позволяет в течение дня получать статистику по открытым позициям физических и юридических лиц с пятиминутными интервалами (BR, Si, RI)
Оно ж демо, по словам биржи. То есть а) все может меняться, следовательно, раз закодить и радоваться - рано; б) в обозримом будущем выставят некий ценник, порядок можно на соседних вкладках оценить. Ежли ценники такого порядка не проблема, то и закодить индикатор для квика (или не для квика), качающий данные напрямую с биржи, тоже не проблема.
Что я выше описал, это на стороне qlua.dll, то есть аркино производство. В самой lua53.dll правки если и есть, то крайне незначительные, практически все строка в строку ложится на сорцы луа из репозитория, как выше из разбора дампа видно.
Цитата
nikolz написал: Проблема многопоточности в луа - это проблема луа.
Луа дает lua_lock/lua_unlock и на этом его проблемы с многопоточностью закончены. Можно поспорить, здорово ли, что в некоторых функциях 5.3 вытащили часть обращений к стеку из-под лока, если говорить о проблемах луа. Но вот как сделаны эти самые локи (и не только), это уже вопросы к арке.
Nikolay написал: где это описано в справке? Скажем, чтобы новичок разобрался. Я уже не говорю про англоговорящего пользователя.
Если качать обновление, там есть все в pdf и в том числе англоязычная версия. Почему-то брокеры считают хорошим тоном перепаковать апдейт по-своему, некоторые еще и заведомо нерабочим способом (например, делают инсталлер в Program Files), при этом документация куда-то исчезает.
Еще раз поправлюсь. Падает на lua_getglobal. В qlua.dll основным потоком квика вызывается некая функция, она пытается вызвать lua_getglobal(state, "OnAllTrade") и, если успешно, далее заполняет табличку all_trade и вызывает полученную луа-функцию. То есть это как раз место, где вызывается OnAllTrade. В дампе крэш происходит вот где
Unhandled exception at 0x000007fef3d6420f in info_20200817_223941.dmp: 0xC0000005: Access violation writing location 0x0000000001882900.
То есть lua_getglobal что-то (функцию OnAllTrade или nil) извлекает из реестра, пытается засунуть на вершину текущего стека, а туда нельзя писать. Осталось догадаться, а почему собсна нельзя-то, то ли стек реаллоцирован (как? все же под локом), то ли весь стейт (опять - как? все же под локом), то ли страница памяти недоступна. Последнее звучит глупо, но там дальше вызов колбека идет с установкой se_translator, это наводит на мысль, что могла случиться рекурсия под транслятором и in-page-error была неожиданно слопана. Мож попробовать транслятор заменить на явный SEH-фрейм и ловить в нем только то, что стоит ловить?
По всем признакам разрушение стека луа. Второй вариант попробовал, словил дамп со второй попытки перезаказа, access violation. Поковырял его, что мы видим
Скрытый текст
Курсор на момент падения находится в функции lua53!auxgetstr(). Сама эта функция из lua53 не экспортируется, что-то еще по пути компилятор выбросил при оптимизации, видимо. Прошел по колстеку вверх, не нашел, чтобы где-то был лок захвачен перед вызовом, а сама функция, как внутренняя для луа, его не захватывает. Оно ничего не значит, конечно, не нашел и не захвачен разные вещи, накидываю как идею для арки, куда посмотреть.
это создавать свой стейт для каждого своего потока и пользоваться только им в этом потоке. Ваш подход с разделяемым стейтом - это грязный хак, по случайности в 5.1 он у вас работал, а в 5.3 перестал, и это не проблема арки и не проблема луа, это чисто ваша проблема.
TGB написал: с использованием критической секции ОС
Цитата
TGB написал: на "защелках", без переключения потоков
Это все прекрасно, к стейту-то вы как доступ синхронизируете? Это можно сделать только той же критической секцией, которую внутренне использует квик, как вы до нее добрались?
TGB написал: найдете ответы на возникающие у вас вопросы
Падает-то у вас. При этом вы шарите стейт между потоками. Этого вообще-то делать нельзя, если вы не знали. Для каждого своего потока вы должны создать новый стейт через lua_newthread и работать только с ним, тогда основную часть синхронизации за вас будет делать луа (но не всю). Если вы лезете в общий стейт из разных потоков, вы просто рано или поздно ломаете стек и получаете крэш. Именно это и подтверждает ваш тест.
TGB написал: В этой функции запрашиваются строки в цикле (5 раз) и передаются функции function SendTS_CQ(NC) работающей в другом отдельном потоке и что-то делающей с этими строками (смотрите текст). Все это происходит в одной lua_State.
Вы работаете с одним lua_State из двух разных потоков, верно я понял?
Все же речь была о заинтересованных в отладке квика, а не вашей операционной системы. А для этого нужен (насколько возможно примитивный) луа-скрипт, показывающий, что гарбидж коллектор в квике работает некорректно, как вы утверждаете. Из описанного поведения пункт 2 это ТОЧНО дедлок у вас в коде, пункт 1 может быть от чего угодно, как из него следует косяк именно в коллекторе, непонятно. Попытался найти, где у вас этот тестовый код зарыт, не нашел. В чем смысл такого теста остается неясным.
Кто хочет результата, выкладывает здесь тестовый скрипт, здесь есть достаточно заинтересованные люди, чтобы потратить время, прогнать у себя, подтвердить баг и тем самым сподвигнуть арку на подвиги, либо обнаружить косяк в самом тесте.
Leonid написал: что где может быть во всех деталях не знаю
Так вот и написал, что где может (не) быть. Дело не в луа, а вообще в подходе, на каждом выборе надо в голове составить "полную группу" всех возможных вариантов и особенно крайние случаи рассмотреть. Вариант получить nil из getQuoteLevel2 вы предусмотрели, а вариант получить пустой массив - нет.
QApplication написал: где можно посмотреть описание этого кода?
Скорей всего квик просто транслирует то, что получил с биржи, никак не пытаясь ответ интерпретировать. Конкретно для спота коды описаны здесь. Для фортса, видимо, надо в спектре смотреть, для других рынков тоже где-то на самих рынках. Несколько удивляет, конечно, что для англоязычного рабочего места не запрашивается ответ на английском, а выводится самопальная заглушка. Возможно, на стороне брокера недонастроено.
Александр написал: Не удается снять стоп-заявку N [401280598].
Дык стоп уже исполнился, была выставлена заявка по 165.10, поэтому и нельзя снять СТОП. Теперь надо заявку снимать, по стопу выставленную, если она была выставлена (а не выброшена из-за запрета шортов), искать в таблице заявок.
if Quotes_1 then
offer_1= tonumber(Quotes_1.offer_count)
fxrl_pr = tonumber(Quotes_1.offer[1].price)
SetCell(Table, 1, 1, tostring(fxrl_pr))
end
Смотрим внутрь вашего условного блока. Что сама по себе таблица получена (не nil), вы проверили в условии. Далее получаете offer_count, это ок, там какое-то число, в том числе и 0 может быть. Далее без проверки пытаетесь получить offer[1].price. Так-так, а если в offer_count был 0, сколько элементов в массиве offer? Нисколько, надо полагать? А что же будет тогда в offer[1]? Не nil ли? А что будет, если из этого нила попытаться вытащить поле price?
У каждой длл свой рантайм, в одной длл он один общий. Это не просто две копии в каждой длл, они и работают каждая сама по себе, у каждой свое состояние. Работать оно будет, конечно, плюсов там нет, сям в общем все равно. Можно также вынести рантайм в одну общую длл, но придется еще и redistributable вместе с дллками распространять. С точки зрения как-то радикально обновить sqlite и оставить обертку как есть тоже сомнения, обертка все же затачивалась под конкретную версию, могут (в будущем) вылезти какие-нибудь несовместимости.
s_mike@rambler.ru написал: Цикл перебора по getitem гоняет ВСЕ данные через бутылочное горлышко между скриптом и терминалом. На этом много потерь.
Звучит логично. Но вот сделал поиск с колбеком, всегда возвращающим false. То есть он всегда пройдет по всему диапазону и не вернет в итоге ничего. И вариант с циклом, тоже тупо весь диапазон getItem. Два прохода, один - первый миллион записей ТВС, второй - второй миллион, дабы видеть, зависит ли от положения диапазона в таблице. Ожидал, что SearchItems даст график ниже цикла. А вижу вот такую вот картиночку
Посмотрел еще на посылаемые главному потоку сообщения. В процессе вызова SearchItems в мейне никаких сообщений главному потоку не обнаружено. Гипотезу о выполнении поиска всегда в главном потоке отклоняем. Остается выяснить вопрос об асимтотической сложности функции.
Сергей написал: Но, где написано, что SearchItems не может выполняться в основном контексте квика, будучи запущенной из майна?
Вопрос интересный. По идее, если искать надо в окне (а не в хранилище), вариантов, кроме как послать сообщение поиска этому окну, не просматривается. То есть фактически поиск будет выполняться в основном потоке. Предположил, что в этом случае колбек SearchItems будет выполняться в том потоке, в котором собственно идет поиск. Запустил поиск в all_trades - колбек вызывается в мейне. Ну ок, поиск в ТВС идет прямо в хранилище. Запустил поиск в money_limits - колбек вызывается в мейне. Не подтверждается предположение. Это таки еще ничего не значит, впрочем.
, откуда и как взялся циркон. Это вот практика. А если бы да кабы повторить весь рисерч за 50 лет (зачем?) и в итоге получить ыщо один линукс тока без крыльев - это бла-бла.
Это как раз не на практике, а бла-бла заинтересованных лиц. На практике ядро циркон написал один человек достаточно быстро, гуголь потом на нем фуксию налепил (опять по привычке выкачав весь гитхаб со всем мусором и списав на это баблеца, но это уже другая история). Затем, сама идея делать ось на все существующее железо - провальная, надо делать платформу на конкретных деталях и под нее пилить конкретную ось с конкретными драйверами, главное тут зафиксировать апи оси и придерживаться его в дальнейшем, а не менять в каждой минорной версии. И все, будет щасте. Конкретно для рф по шагам: поддержать байкал-м, на нем сделать линейку плат по типу хоть бы малины, под платы разработать ось, опубликовать апи и сдк, портировать несколько приложений, файрфокс там, ллвм, еще что-то. И все, полетит штуковина, если ценник не ломить (продотировать из бюджета по первому времени).
новичок написал: куда розтелеком якобы вбухал 9 ярдов
Примерно 2500 человеко-лет хорошего программиста. По идее, за этот бюджет должны были сделать свой компилятор, свой рантайм, свое ядро и весь софт тоже свой.
Сергей написал: Если SearchItems выполняется в основном контексте, то вызов с тяжелой функцией, скорее всего, заблокирует коллбэки, причем во всех скриптах.
Тут у вас путаница. Каким образом она может выполняться в основном потоке квика? Только будучи вызванной в колбеке каком-то. Так вот сам по себе вызов колбека не даст основному потоку делать что-либо еще, в том числе вызывать другие колбеки, пока вы из колбека этого не вернетесь, независимо от выполняемых в нем действий. Следовательно, без разницы, SearchItems в нем или явный цикл.
По вопросу что лучше - лучше не строить алгоритм так, чтобы приходилось снова и снова что-то искать, это в любом случае повышает сложность (в смысле о большое). Явный цикл имеет линейную сложность. Если, например, пройти по ТВС, на каждом тике вызывая поиск в той же ТВС, получим сложность уже квадратичную. Всегда лучше алгоритм с меньшей сложностью, даже если в нем константы больше, т.к. он остается работоспособным при масштабировании, а полиномиалка начинает тормозить уже с малых размерностей и с какого-то момента вешается навеки. Насчет сложности SearchItems послушал бы из первоисточника.
s_mike@rambler.ru написал: если вдруг у кого то есть sqlite для 5.3 x64 - буду очень рад
По-хорошему там под 64 бита надо поправлять, много ворнингов вылезает, что пихают 64-битное в int. Но поглядел поверхностно - вроде пихают только индексы на стеке, ничего ужасного вроде не ожидается, попробуйте, коль не лень. Сам sqlite3 интегрирован в эту же длл, отдельно его добавлять не нужно.
Тогда на этом наборе существует всего одно значение SMMA и оно равно значению SMA на этом же наборе, то есть сумма пяти цен, деленная на пять. Никаких дальнейших действий при пяти точках нет.
Это рекуррентная формула, т.е. каждое следующее значение рассчитывается на основе предыдущего. Самое первое значение там просто как в SMA, т.е. сумма первых пяти цен (первой - пятой), деленная на 5. Второе - сумма вторых пяти цен (второй - шестой) минус предыдущее значение SMMA плюс последняя в группе (шестая) цена, все деленное на 5. Третье - сумма третьих пяти цен (третьей - шестой) минус предыдущее... и т.д.
Старатель написал: Делать лок перед началом колбека и анлок по окончании, не?
Это и без арки можно сделать тем же ssort'ом, когда нужно. Всем и всегда - не нужно. Простой пример: в колбеке вызываете функцию из своей длл, она без лока выполняется. Если квик лок захватит, будет выполняться под локом. Нужен ли ей лок? Скорее всего нет, там в основном нативный код, в начале из стека выдрали аргументы, в конце засунули результат, чего бы мейну параллельно не поработать.
Минимальное значение видимой части 1 лот или 10 лотов установлено для ценных бумаг, указанных в Таблице А-6 Уведомления о дополнительных условиях проведения торгов на рынке акций.
Для остальных ценных бумаг минимальное значение видимой части - 100 лотов (подпункт 1.12.3.1 пункта 1.12 Уведомления о дополнительных условиях проведения торгов на рынке акций).
Скрытая часть айсберг-заявки:
Скрытое значение определяется минимально допустимым соотношением 1:100 (видимая часть айсберг-заявки : скрытая часть айсберг-заявки). Устанавливается решением Биржи (см. подпункт 1.12.2 пункта 1.12 Уведомления о дополнительных условиях проведения торгов на рынке акций).
Старатель написал: вреда от main больше, чем пользы.
Это логичное следствие устройства самого луа, смотрим например в сорцы одной из функций, видим лок в начале и анлок в конце. Если функции вызываются параллельно из двух потоков, а это неизбежно при их параллельной работе, это будет приводить к переключению контекста между мейном и основным потоком квика на каждой итерации цикла. Отсюда накладные расходы и отсюда выгода от блокировки, захват критической секции в начале функции становится рекурсивным и не приводит к переключению контекста. Трудно придумать, как арка могла бы это изменить в текущей архитектуре с отдельным мейном. Только если отдать всю синхронизацию скриптописцу, что закончится известно как.
Интересное исследование. Однако есть сомнения в корректности бинарного поиска, записи в хранилище не обязаны быть строго упорядоченными по номеру. Если, например, подключены фортс и спот, там будут перемежающиеся кучки с совершенно разными диапазонами номеров, хотя в пределах кучки номера и упорядочены.
nikolz написал: не надо отслеживать новые версии и исправлять то, что перестает работать
Это, конечно, важный плюс, спору нет. Но если один мейн рушится, что с остальными делать? Очевидно, тоже прибивать и завершать весь скрипт, т.к. очень сомнительно, что большинство скриптов следуют RAII (до предыдущей версии это было физически невозможно даже и никто не бухтел, т.е. буквально никто этим не морочился). В таком раскладе мультипликативно снижаем общую надежность скрипта, если (утрированно) надежность одного мейна 0.5 и всего скрипта тоже, то при двух таких мейнах надежность скрипта в целом уже 0.25.
shr540i написал: Мне лично важнее выставлять лимиты
Да и всем, по рынку можно всегда сымитировать, поставив лимитную цену нереально далеко от цены срабатывания.
Цитата
shr540i написал: те кто торгуют большими объемами обычно дружат с головой
Поддержу эту прекрасную мысль картиночкой, показывающей объем выставляемых заявок за день (некий неопределенный день более пяти лет назад). Как можете видеть, ребята с головой и деньгами ставят ордера не то что не близко, а даже так, чтобы в стандартном стакане их не видать было до поры. Хвостики хуже рынка это как раз рыночные заявки, которыми потом цену нагоняют на себя, и объем их мизерный по сравнению с тем, что ребята поставили по-настоящему.
Точнее ордерлог. Картиночка выше как раз по нему построена, а стакан там только середину бы показал, то есть все самое интересное осталось бы за кадром.
А вдруг я злопамятный и щас вас под лося подведу? Ок, давно раньше сбер очень хорошо исполнял телефонные заявки, катал рынок даже под относительно мелкого клиента, либо кучками их собирал и катал под кучку, как там сейчас не знаю. Взять можно хоть бы и мосэнерго или что-то подобное, подавать заявку прямо после открытия без указания цены, иначе поставят в стакан и ваши проблемы.
и перечисление измышлений. Квик не мамба, квик заточен в основном под мамбу, равно как мт заточен под дилеров. На мамбе много что возможно, но суть не в этом, суть в том, что дилер дал квоту и готов принять по ней объем, мамба дала тик и все, это не значит, что под тиком в стакане вообще что-то есть. Никакой терминал попадоса при этом избежать не позволит, будет разный попадос, у квика зависнет неисполненный лимитник, мт в биржевом режиме будет лить в пол до победного. Все эпитеты вы сами выдумали, тут сорян, сами их и обосновывайте.
Цитата
shr540i написал: как с учетом вышесказанного улучшить квик чтобы он при просадке с 1000 до 10 защищал трейдера
А тут ответ простой - никак. И не цепляйтесь вы к этим цифрам утрированным. Даже по газику в середине дня рыночный ордер развезут на процент и глазом не моргнут, хотя вы лупили вроде бы по крупному уровню в стакане. А потом в ТВС посмотрите, какой объем перед вами прошел, был ли этот уровень выкуплен? А не было там объема, сняли уровень исключительно для вас.
shr540i, не утрируйте, возьмите что-то, где нормальный стакан, но вы успеете увидеть процесс. Нормальный брокер вашу покупку исполнит вблизи минимума дня, а как именно он этого добьется, я предложил вам посмотреть воочию.
shr540i, дружеский совет (тм). Закажите у нормального брокера покупку чего-нибудь не очень ликвидного по телефону на хотя бы $10к и смотрите через квик, как ее исполнять будут. Потом можете эту "муть" с кем-нибудь обсудить, только не со мной, пожалуйста, меня ваши лексические конструкции печалят.
shr540i написал: чтобы разработчики quik могли улучшить инструмент
В какую сторону улучшить? Тема была о том, что квик отступ не оттуда считает, привели в пример чудесный мт, в котором, оказывается, вообще никакого отступа нет и льется тупо в пол, а когда в это носом натыкали, начались метания экскрементов. Эмоции, говорите?