Спорить ни с кем не буду. У каждого своё мнение. nikolz: "Поэтому без прошлого нельзя прогнозировать будущее" - здесь скажу, что прогнозировать без прошлого конечно нельзя, ибо вообще тогда и прогнозировать-то по сути нечего будет, но один хрен точно спрогнозировать это прошлое всё равно не поможет, будущее будет не таким как прогнозы в 99% случаев, а то и больше. Владимир: "Суходрочка в стакане и вообще HFT является лучшим доказательством отсутствия нормального алгоритма торговли." - тут по поводу HFT не знаю вообще ничего, а индикаторы рисуют графики по стаканам в качестве тестирования, мониторинга ситуации в течении дня, анализируются мной(не роботом, не индикатором) пары - и базовый актив и фьючер одновременно на разных графиках, тенденции они показывают чётко, например приближение к поддержке или сопротивлению существующим или новым(графики с линиями этого не покажут или покажут ложные[исходя из "старых" данных]), практически с ооооочень высокой вероятностью! Решения на покупки-продажи принимаются не роботом в этом случае, не индикатором, а вручную после анализа. Пока ни разу не подводил такой подход. Всё в пределах дня в основном.
Вообще эти свечи все "старые", как и вообще весь этот ТА как по мне, так это всё ерунда. Что бы там не рисовал нам ТА, рано или поздно он соврёт. Анализировать конечно можно, но нужен чисто свой ТА, котрый будет работать по набору чисто твоих данных, которые могут динамически менятся во времени от разных ситуаций, да и сам алгоритм ТА нужно постоянно менять под меняющийся рынок. Только так ТА будет работать. Но это такие сложности постоянно обновлять входящие данные и их количество и постоянно корректировать код(и то только после определённого слежения за рынком), а как поменяется код, то нет никаких гарантий, что рынок не изменится и код будет рабочим определённое время. Вобщем ТА не вариант в плане свечей и графиков прошлых цен, вернее вариант, но очень сложный, требующий постоянной корректировки скрипта. А вот анализ стакана может помочь при дневных сделках и общем анализе ситуации на рынке если мониторить несколько инструментов например основных фишек индекса.
nikolz написал: Бесплатный совет.Так как Вы начинающий писатель, то рекомендую Вам писать скрипты без циклов.Так пишут профи софт для систем обработки данных в реальном времени.Если научитесь, то индикаторы будут в десятки раз считаться быстрее.
Да в этом индикаторе нет никаких циклов вообще, он наипростейший до немогу. Мне по сути то вообще и свечи эти не нужны и считать мне по ним ничего не надо. Мне надо было в реальном времени отображать 2 объёма в стакане - для BID и OFFER для инструмента. И чтобы эти объёмы в виде кривых соотносились с графиком инструмента. Т.е. я OnCalculate() просто использую как функцию для расчёта в реальном времени этих нужных мне объёмов. Свечи как таковые с их данными просто игнорирую. Резульаты расчёта 2-х объёмов вывожу через return. Расчёт каждого объёма по любому в цикле, так как надо же пробежаться по стакану.
nikolz написал: Про два раза, да я тоже когда-то возмущался этим. Первый раз Size меняется до максимального. А второй раз он уже не меняется пока не придет новая свеча. Я делал так, чтобы считалось лишь один раз, но есть хитрость двух разового расчета . Поэтому просто забил на это.
Этот Size() я ранее вызывал в Init. При загрузке индикатора он показывает последний индекс последней свечи. При загрузке квика ещё до логина с сервером если Size() остаётся в Init, то он возвращает НОЛЬ! А при ноле логика скрипта не работает. OnCalculate делает проверку индекса свечи с сохранённым Size(), чтобы отбросить всё что меньше, а там ноль. Поэтому, чтобы не менять логику с Init убрал Size() и начинаю его вызывать только после isConnected() == 1 и только 1 раз внутри OnCalculate(1 раз чтобы - использую флаг true/false). Так логика остаётся прежней и Size() возвращает уже не ноль. Хотя как вариант с первого пробега по свечам можно брать последнее максимальное значение(при этом возвращая везде nil), а при втором прогоне откидывать все свечи до максимальной с первого прогона так же возвращая везде nil, а потом уже начинать обрабатывать новые свечи, но так логика кода будет совсем иной(по Вашему примеру как-то так). Да, и ещё про 2 прогона, что Вы пишете - это когда индикатор грузится на график, а если загружается квик, то сначала идёт 2 прогона до одного максимального значения каждый, а потом после коннекта с сервером(ввод логин/пароля) происходит ещё 2 прогона и только последний, т.е. фактически 4-й по счёту начинает считать новые свечи с сервера.
Вернее индикатор(код) один, а на инструменты разные код в начале прописан, вот и получается, что если хочу установить на новый инструмент, то в начале меняю код инструментов ClassCode, SecCode, а остальной код оставляю как есть. Поэтому плодиться скрипты могут по мере того, что мне надо. Хотя вот думаю надо универсальный сделать через getDataSourceInfo().
nikolz написал: проблему с отключением индикатора я решаю так :Перед запуском квика в индикаторе пишем аброкадабру т е делаете явно ошибки. При запуске КВИК грузит индикаторы, а при их загрузке работает компилятор байткода. Он находит ошибку и квик такой индикатор не загружает.
Как вариант можно да, если один индикатор. У меня несколько, поэтому проще думаю переименовать LuaIndicators. В любом случае индикаторы не загрузятся. Но лучше конечно, чтобы они загружались и исправно работали.
А на счёт замыканий я раньше и не слыхал. Может в интерпретируемых языках такое есть? Типа Lua, Pyton и прочих? На си так вообще никаких проблем с такими переменными нет. Передал в функцию переменные не явно, а по ссылке, или просто их адреса(что с точки зрения компиляции одно и тоже фактически будет) и все дела. Явные то переменные через стек в функцию попадают, после выхода из функции стек режется и переменные пропадают, а по ссылке или через адрес функция обращается к ним не через стек, а через косвенную адресацию. Поэтому эти переменные при выходе из функции сохранятся после их изменения внутри функции. Может из-за того, что интерпретируемые языки так не могут ввиду их простоты, поэтому и ввсели эти замыкания. Но это только догадки. Пока я сам в смысл этих замыканий ещё не вникал, не читал ещё.
nikolz написал: 1) про замыкания.индикаторы здесь не причем. Это способ программирования функций, при котором значения переменных сохраняются после выхода из функции.Он используется в различных языках программирования.Не знает, не используйте. тоже самое делают глобальные переменные.--------------2)если надо не обрабатывать старые, то сравнивать i с size()
1) Про замыкания возник вопрос из-за того, что у кваика есть справочный .pdf файл "Использование Lua в Рабочем месте QUIK.pdf" в C:\Open_Broker_QUIK\Doc\Lua, в нём есть п. 3.7 "Расчёт EMA" и там написано: "Нет возможности обратиться напрямую к предыдущим рассчитанным значениям индикатора. Это значит, что для вычислений текущего значения необходимо хранить и предыдущие значения. Для таких целей в Lua используется механизм замыканий. Определение такой функции нужно вынести в отдельный файл и в отдельный каталог, который не сканируется при создании индикатора." И далее идут примеры, функции, возвращающие функции(короче замыкания как я понял). Они используются именно для индикаторов. В чём там прикол, я так и не понял. Можно тоже самое написать и не использовать возврат функции в функции(замыкания). Что они хотели этим показать я не понял. И зачем это всё в отдельный каталог, который не сканирует квик при создании индикатора? Зачем весь этот изврат с каталогами, dofile и замыканиями в придачу??? 2) Это да согласен, что i c Size() надо тогда сравнивать, это так. Просто у меня сначала скрипт начинался с того, что в init сначала запоминал Size(), а в OnCalculate() отбрасывал всё, что меньше Size(), повторные свечи >= Size() тоже обрабытывал, для меня это не важно было. Вобщем такой скрипт при загрузке на индикатор нормально загружался и работал без проблем, рисовал кривые мои 2 шт в отдельной области. Проблема возникла только тогда, когда я выходил из квика, повторно запускал квик и вот тут то квик у меня вообще начал зависать, вернее в цикле без конца то подключится к серверу, то отключится, при этом куча окон всяких на экран выдаёт, в сам квик войти невозможно стало. А чтобы зайти нужно было как то отключить индикаторы. Я даже по началу вообще не понял, что в этом виноваты мои индикаторы, так как проблема то явно выглядела как подключения-отключения к серверу. Потом дошло, что могут влиять на это индикаторы. А как их отключить то если квик не запускается. Вот пришлось переименовывать папку с индикаторами, чтобы квик при загрузке их не находил. Папку переименовал, в квик стал заходить, ну иначал искать причину чё к чему. Выяснил, что квик этот почему-то еще до коннекта с сервером по паролю 2 раза(зачем 2 не знаю, только разрабам видно известно) пробегает по свечам по всем начиная с первой, потом после второго прогона останавливается и пока не залогинишься более никакие свечи не прогоняет. Потом как залогинишься квик опять таки ещё 2 раза опять заного пробегает по всем свечам(точно так же как и до залогинивания) но потом уже начинает и дальше свечи обрабатывать, что новые грузит. Так вот в самый первый раз до залогинивания Size() выдаёт почему-то 0(ноль) Ха - ха - ха Ноль, а не то что надо - максимальный индекс свечи. Отсюда получалось то, что даже при закрузке квика(после переименования папки с индикаторами) и при работающем квике если название папки с индикаторами вернуть обратно, то индикаторы то всё равно не заработают на открытых графиках, а чтобы заработали надо зайти в график, удалить их и заного загрузить на график, только тогда квик их загрузит из папки. Ну а потом я эту проблему решил как описал выше через isConnected() и подкорректировал всю логику индикатора, убрав Size() из Init. Просто вычислений на свечу видимо много было и квик так долго всё обсчитывал и обсчитывал, что не догонял чё так долго то и разрывал соединение установленое с сервером, потом опять по кругу - подключался, считал, отключался и т.д. и т.п. Потом, когда сделал так, что Size() начал мне выдавать нормальное значение вместо ноля, квик стал подключаться, так как все свечи до логина мой индикатор считал в nil, а потом отсчитыал только свечи новые, видимо так как новые то идут не так часто, квику хватает времени и на свою работу и на просчёт свечей. Всё стало работать. А так то это их косяк - почему Size() выдаёт ноль если он в Init и квик загружается с существующим ранее индикатором? Ведь всечи то есть и он их прогоняет до какого-то значения аж 2 раза. Почему же тогда Size() не возвращает это значение? Вот в этом и косяк. Не будь его всё бы работало и в процессе загрузки на индикатор и после перзагрузки, ан нет, пришлось извращаться и корректировать код.
1) Посмотрю. Вникну подробнее. Мельком глянул - ничего с наскоку не понял. Для чего эти замыкания в квике в индикаторах? Если можно на пальцах, хоть кратко, просто для того, чтобы уловить суть необходимости. 2) Не, мне так не пойдёт. Это отсекёт повторы если будут, а так то всё-равно все свечи пробегать будет. А мне надо, чтобы "старые"(до момента коннекта) все отбрасывались. Я в принципе уже нашёл решение как это сделать, хотя и Size() в Init возвращает 0 при запуске квика с индикаторами. Вызыываю Size() только после коннекта с сервером и только 1 раз, чтобы зафиксировать значение и обрабатываю свечи > этого значения только. Несколько вызовов на 1 свечу мне не страшно, пусть будут, график рисует как надо. А так то да, можно использовать, чтобы одну свечу 1 раз только вызывать, может и заиспользую.
Не нужные мне свечки ранее отсекал сохранение значения через вызов функции Size(), обрабатывал только вновь пришедшие свечи. При загрузке индикатора такое работало. После перзагрузки Size() внутри Init возвращает 0, буду пробовать выкручиваться, может отсекать свечи до подключения и после подключения? Попробую, а то виснет же - видимо много считает и считает при загрузке.
Вобщем сейчас долго тестит-тестил. Оказалось, что простейший индикатор всё-таки свечки новые вызывают вызов функции OnCalculate. Просто новых выводов функции PrintDbgStr в окне DebugView не было видно, что они появляются снизу как и положено видимо потому, что очень много инфоормации в окне накопилось и чтобы их увидеть, что они действительно пиишли надо было понажимать PageDown клавишу и тогда их видно новые, а я мышкой пытался двигать позунок вниз и ничего не происходило, чтобы мышкой двинуть оказывается надо сначала вверх ползунок двинуть, а потом вниз до конца - только тогда окно отображет последние выводы, а если только ползунок вниз до конца, то так не катит, такие особенности вот, ктоб знал, что у них так, раньше всегда просто вниз ползунок и всё видно что последнее в окно пришло.
А, ещё добавлю. В тестовом режиме по крайней мере хоть виснуть перестал, хотя всё равно при входе то подключится квик, то отключится и так несколько раз, хотя потом вроде подключается окончательно и более не отключается. Но это так и раньше было до индикаторов. Может из-за того, что на каждом индикаторе много рассчётов было и поэтому из-за этого квик постоянно подключался-отключался и не мог совсем из этого режима выйти - фактически как висел, а когда упростил индикатор до немогу и оставил его один на одном графике, тогда квик таки соизволил выйти из этого бесконечного цикла подключился-отключился от сервера.
Здравствуйте. Простейший индикатор на минутном графике работает когда его добавляешь на график. После перезагрузки без конца квик то подключится, то отключится, постоянно выводит информационное окно с разными сообщениями, получается всё время циклится - висит. Индикаторов таких несколько на разных графиках. Чтобы после перезагрузки вообще загрузиться приходится переименовать папку LuaIndicators, тогда удаётся зайти в квик и работать. Чтобы запустить графики, надо опять переименовать папку обратно в LuaIndicators, удалить на каждом графике индикатор и загрузить индикатор заного. Для тестирования ошибки оствил один график и один свой индикатор, так же попробовал в режиме ЗАМЫКАНИЙ. Кстати совсем не понятно, что это за режим такой и зачем он нужен, чем он отличается от обычного режима - очень хотелось бы получить на это ответ. Ну так вобщем сделал из индикатора совсем наипростейший, фактически оставив там только return nil и всё, тестил далее в режиме ЗАМЫКАНИЙ, так как никаой разницы с простым режимом не увидел. В теле OnCalculate поставил вывод через PrintDbgStr("Index = " .. tostring(index)). И что получилось. Судя по выводам отладки видно, что все свечи вызываются последовательно начиная с 1 и до какой-то свечи, потом опять с 1 и до какой-то свечи, потом опять, короче раза 3 или даже 4 прогоняются свечи с 1 до последней. На этом всё. Болеее функция OnCalculate вообще НЕ ВЫЗЫВАЕТСЯ!!! График при этом работает, свечи на нём идут, а OnCalculate не вызывается ВООБЩЕ. Почему такое? Почему при добавлении графика работает и OnCalculate вызывается и не один раз даже на свечу минутную, а при перезагрузке вызываются какие-то старые не нужные мне свечи последовательно и причём не один раз, а при приходе новых свечей OnCalculate перестаёт вызываться. И что за ЗАМЫКАНИЯ такие, как их использовать и в чём их смысл?
Для разбора описанных Вами проблем, нам нужны примеры скриптов, один с 4-мя параметрами, когда таблица будет обновляться, второй без этого параметра. Просьба прислать запрошенную информацию нам на quiksupport@arqatech.com со ссылкой на данную ветку форума.
Все тонкости проблемы описаны выше и достаточно подробно. Нет никакого смысла отправлять примеры скриптов. Всё расписано до мелочей просто. Зачем примеры скриптов с SetCell с 4-мя параметрами и с тремя? С 4-мя это когда 4 параметра, 3 - это когда 3. Что тут не ясно то? Отсутствует последний параметр когда 3 параметра. Если будете реально разбирать проблему, то разработчики пусть читают эту тему, последние сообщения все. Они знают свою программу и lua. Если они прочитают что написао в теме, то всё им и так будет ясно. Вобщем если кто реально будет вникать в проблему из разработчиков, то прочитав тему и все мои сообщения, он всё поймёт.
Anzhelika Belokur написал: Ваше пожелание зарегистрировано. Мы постараемся рассмотреть его и сообщить Вам результаты анализа. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожелания в будущих версиях ПО.
Ещё добавляю информации. Как я и писал ранее удалось таки заставить обновляться таблицу используя функцию Highlight, но косяки остаются при уходе подсвечиваемой строки за пределы таблицы при прокрутке и надо опять подсвечтвать строку в поле видимости таблицы или тыкать в заголовок мышкой. А дополнение такое - если в таблице вывод идёт строковой переменной через SetCell и SetCell без последнего 4-го числового параметра, то Highlight не помогает и жутко тормозит, прокрутка таблицы идёт с лагом в секунды, а может и минуты. Поэтому, чтобы Highlight работала и заставляла принудительно обновлять таблицу, вызовы SetCell делаю с передачей ей 4-го параметра равного числовому значению, я использую 1, хотя можно и любое другое число, хоть ноль, лишь бы было число. Хотя по умолчанию это число при выводе строки не нужно. Вот такие вот особенности. Может поможет Вам разобраться в проблеме.
И ещё, если все вызовы SetCell будут с 4-м параметром числом и хотя бы один из них SetCell будет без этого параметра, то таблица обновляться не будет и будет подвисать, как только все SetCell-ы будут со всеми 4-мя параметрами, так начинает обновляться и не тормозит, но косяки с выходом подсвечиваемой строки за пределы видимости таблицы так и не пропадают.
Anzhelika Belokur написал: Ваше пожелание зарегистрировано. Мы постараемся рассмотреть его и сообщить Вам результаты анализа. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожелания в будущих версиях ПО.
Ещё добавляю информации. Как я и писал ранее удалось таки заставить обновляться таблицу используя функцию Highlight, но косяки остаются при уходе подсвечиваемой строки за пределы таблицы при прокрутке и надо опять подсвечтвать строку в поле видимости таблицы или тыкать в заголовок мышкой. А дополнение такое - если в таблице вывод идёт строковой переменной через SetCell и SetCell без последнего 4-го числового параметра, то Highlight не помогает и жутко тормозит, прокрутка таблицы идёт с лагом в секунды, а может и минуты. Поэтому, чтобы Highlight работала и заставляла принудительно обновлять таблицу, вызовы SetCell делаю с передачей ей 4-го параметра равного числовому значению, я использую 1, хотя можно и любое другое число, хоть ноль, лишь бы было число. Хотя по умолчанию это число при выводе строки не нужно. Вот такие вот особенности. Может поможет Вам разобраться в проблеме.
Разработчики, ответьте же хоть что-нибудь! Так же добавляю новую информацию для размышления. Попробовал отправлять сообщения WM_PAINT в цикле с задержкой 100 мс непосредственно окну таблицы из другой программы(написал на C++). Дескриптор окна необновляемой таблицы можно увидеть через Spy++. Сначала просто его использовал. Потом сделал автоматический поиск дескриптора в программе через FindWindow и FindWindowEx начиная с родительского окна QUIK. Так вот отправка WM_PAINT непосредственно процедуре обработки сообщений окна таблицы никакого результата не даёт, хотя SendMessage проходит без ошибок. Так же если отсылать в цикле UpdateWindow - тоже результата нет. UpdateWindow так же срабатывает без ошибок. Косяк на стороне квика. Выходит, что окно получает WM_PAINT, но перерисовывает его с необновлённого буфера. SetCell-ы видимо обновляют один буфер, но есть ещё другой буфер из которого WM_PAINT рисует окно, так вот из первого буфера во второй информация не попадает, а она туда должна попадать с периодичностью хотя бы 100 мс, тогда и WM_PAINT будет обновлять окно. Разработчики готовы вникнуть в суть проблемы или нет?
Alexander написал: , точно. Попробовал использовать Highlight и действительно помогло! Спасибо. Но разрабам не помешает всё-таки сделать функцию UpdateWindow.
Помогло то помогло, да вот только не совсем. Если подсвечивать строку, которая ушла из поля видимости, например скроллингом, то таблица опять перестаёт обновляться. Я сделал так, чтобы подсвечивалась любая строка на которую ткнуть мышкой. Получается, что чтобы заствить таблицу обновляться - сначала тыкаю в любую строку в таблице, она подсвечивается и таблица обновляется. Если таблица большая и делаешь скроллинг(прокрутку) содержимого таблицы, то как только подсвечиваемая строка уходит за пределы таблицы, т.е. исчезает из поля видимости, то тут же таблица обновляться перестаёт. И нужно опять тыкать на любую видимую строку в таблице. Это не практично. Лучшее решение как я и писал выше - нужна функция UpdateWindow, но поддержка категорически молчит по этому поводу.
Alexander написал: Пробовал: 1) получать заголовок окна через GetWindowCaption и заново его же выставлять через SetWindowCaption - не помогает. 2) получать координаты окна через GetWindowRect и заново выставлять окно по тем же самым координатам через SetWindowPos - не помогает. При этом окно становится поверх всех окон, только наведёшь другое окно на него, как моё окно становится поверх наведённого, причём данные в окне как не обновлялись, так и не обновляются. Чтобы обновились - по прежнему нужно либо ткнуть в окно мышкой, либо навести её на заголовок окна. 3) пробовал тоже самое что и п.1, только ещё плюс менять координаты на 1 пиксель, затем возвращать обратно - тут вообще смех просто получается - окно дёргается туда-сюда, а результат точно такой же как в п.1 Решения на данный момент нет. Программирование на Lua теряет всякий смысл при выводе данных в таблицу. Данные обновляются только в буфере программы, а окно не перерисовывается. Что делать? Писать отдельную программу на C? Искать окно в недрах Windows? Получать его хэндл и отправлять принудительно окну сообщение WM_PAINT на перерисовку? Это извращение какое-то.
Пункт 3 не помог потому, что окно сдвигал на 1 пиксель туда-сюда, при этом не меняя размер самого окна, а только изменяя координаты его верхнего левого угла. А вот если координаты левого верхнего оставить прежними, а менять координаты правого нижнего на 1 пиксель туда-сюда(фактически меняя размер всего окна получается), то окно начинает таки обновляться как положено. Но работать так невозможно, потому что окно во-первых дёргается, а во-вторых всегда поверх всех окон, только перекроешь его другим окном, как оно опять сверху.
Пробовал: 1) получать заголовок окна через GetWindowCaption и заново его же выставлять через SetWindowCaption - не помогает. 2) получать координаты окна через GetWindowRect и заново выставлять окно по тем же самым координатам через SetWindowPos - не помогает. При этом окно становится поверх всех окон, только наведёшь другое окно на него, как моё окно становится поверх наведённого, причём данные в окне как не обновлялись, так и не обновляются. Чтобы обновились - по прежнему нужно либо ткнуть в окно мышкой, либо навести её на заголовок окна. 3) пробовал тоже самое что и п.1, только ещё плюс менять координаты на 1 пиксель, затем возвращать обратно - тут вообще смех просто получается - окно дёргается туда-сюда, а результат точно такой же как в п.1 Решения на данный момент нет. Программирование на Lua теряет всякий смысл при выводе данных в таблицу. Данные обновляются только в буфере программы, а окно не перерисовывается. Что делать? Писать отдельную программу на C? Искать окно в недрах Windows? Получать его хэндл и отправлять принудительно окну сообщение WM_PAINT на перерисовку? Это извращение какое-то.
serggio написал: Вам ровно пять сообщений назад поддержка ответила .
Я видел, что ответила поддержка. Заметьте, что после этого так же nikolz задал свой вопрос и поддержка не ответила. Вообще поддержка ответила, что такой стакан "огрызок" по сути - транслирует биржа. Т.е. биржа у себя имеет полный стакан котировок на акции, а брокеру она транслирует "огрызок" этого стакана. Вам не кажется это странным? Как поддержка вообще взялась тут ответить за брокера? Квик оперирует данными брокера, но не биржи. Поэтому думаю вопрос этот пока открыт и напишу брокеру - пусть он ответит какой полный стакан на бирже и какой стакан ему транслирует биржа и почему. Толи сам брокер делает у себя такие настройки, что биржа ему даёт не полный стакан, толи брокер получает таки полный стакан с биржи, но по каким то своим понятиям транслирует нам в квик не полный стакан.
nikolz написал: Вопрос к разработчиками. Как я понимаю, глубина стакана - это размер очереди заявок на сервере биржи. -------------------- Регулируется ли на сервере КВИК брокера размер транслируемой очереди т е глубина стакана. Еесли да , то какая максимальная, если нет , то какая максимальная на сервере биржи. Спасибо
Скорее всего биржа всё-таки даёт брокеру полный стакан, а вот брокер уже режет его по своему усмотрению. Но пусть ответит поддержка. И почему например на акции только 20 глубина максимум, а на фьючерсы - 50? Кто это так решил?
Прочитал тему. Поднимаю вопрос в 2022 году. Проблема как была, так и осталась. У меня вообще наипростейший скрипт - SetCell в main заполняет ячейки, без всяких там подсветок. Поставил как рекомендовали sleep(100) не помогает. Перепробовал разные задержки - ничего не меняется. Чтобы таблица обновилась нужно либо ткнуть мышкой в неё в любое место, либо навести курсор мыши на верхнюю часть окна с заголовком. По другому никак. Это не порядок. Проблему надо решать. Что хочу сказать разработчикам. Причина - не прорисовка окна. Насколько мне помнится, чтобы заставить окно перерисоваться принудительно, есть такая функция, UpdateWindow когда пишешь на C, она отправляет сообщение WM_PAINT непосредственно в процедуру указанного окна, обходя очередь приложения. Неужели нельзя для qlua разработчикам сделать аналог? У вас всё для этого есть. Квик создаёт окно таблицы для пользователя, у вас все хэндлы всех окон есть и окна таблицы пользователя тоже. Вот сама функция на C: BOOL UpdateWindow([in] HWND hWnd); Напишите же свою функцию для qlua и внутри неё воткните UpdateWindow. Вам это совсем просто сделать, так как вы знаете hWnd окна таблицы. А нам где его брать? Вобщем думаю вы можете это сделать. А то переписывал весь день с qpile скрипт на lua. переписал, а тут такой косяк. На qpile и то стабильней работает. Там выставил 1 сек период расчёта и хотя бы раз в секунду будет обновляться окно. Хотя заметил, что на qpile обновление окна тоже идёт только в самом конце скрипта независимо делаем мы add_item из мапа или нет, он только буфер таблицы заполняет, а непосредственно прорисовка окна в самом конце скрипта идёт. Надеюсь проблему решите. PS. Вы разработчики саму программу quik на каком языке пишите?
Что Вы понимаете под полным стаканом? Если у Вас в терминале по ФР и ВР показывает 20 строк покупки и 20 продажи это количество и транслируется с биржи (если у Вас не стоит настройка на уменьшение вкладка "Система"-Настройки-Параметры инструментов, глубина стакана), больше стакан Вы не увидите. Если Вам нужно увеличить глубину стакана на СР, Вам необходимо обратиться к Вашему брокеру по данному вопросу.
Под полным стаканом я понимаю весь стакан, который есть на бирже. Я могу ставить заявки в стакан на любую цену какую хочу, лишь бы она была в пределах MAX - MIN(регулирует биржа) по инструменту. Так вот поэтому я могу выставить заявку с такой ценой, что она будет принята биржей, т.е.попадёт в её стакан, но я её у себя в стакане в квике не увижу. Т.е. она может попасть за пределы 20 лучших. Вот поэтому я и хочу видеть не какой-то там огрызок стакана, а весь стакан целиком.
В Настройках параметров инструментов для всех классов и всех инструментов выставил глубину стакана 1000. Для акций ничего не изменилось - как было 20 туда-сюда, так и осталось, для фьючерсов увеличилось с 20 до 50. Я только так и не понял - это биржа так ограничивает стакан или брокер? Можно ли увидеть весь стакан полностью, какой он есть на самой бирже?
Mikhail написал: Перед подачей заявки на бирже у мен стоит такая функция, работает как часы.
Код
local tostring_ = tostring
local math_tointeger = math.tointeger
function t_ (x)
return tostring_(math_tointeger(x) or x)
end
Этот код будет работать. Но... 1) Зачем здесь вводить переменную tostring_ и загонять в неё адрес функции tostring и потом вызывать косвенно tostring через tostring_, когда можно сразу вызвать напрямую саму tostring? 2) Если в используемой версии Lua есть функция math.tointeger, то проблем не будет, адрес функции будет и присвоится переменной, а если нет? Косяк... Функция появилась в 5.3 версии.
На смартлабе нашёл вот такой код;
local tointeger = math.tointeger or (function(x) return x end)
function tryInt(x) return tointeger(x) or x end
Работает чётко. Мой разбор синтаксиса такой: в tointeger присваивается адрес либо math.tointeger (если таковая есть в используемой версии), либо адрес безымянной функции, возвращающей то же число, что ей передано(имени нет, но адрес то есть, только он и нужен по сути) на этапе интерпретации скрипта. return косвенно вызывает либо math.tonteger либо безымянную функции в зависимости что попало в переменную tointeger . В случае косвенного вызова через tointeger безымянной функции ошибок не будет и в любом случае вызов tointeger(x) вернёт целое значение, оно и вернётся при любом x , а вторая часть " or x " в return не сработает. В случае же косвенного вызова через tointeger функции math.tointeger если без ошибок сработает, то вернётся целое число и так же вторая часть " or x " не сработает, но если вернёт ошибку, то сработает как раз вторая часть " or x " и она вернёт исходное x . Думаю, что этот вариант лучше и надёжнее. Дальнейшее преобразование в строку через tostring() это уже по надобности.
А...да. Тут ещё добавлю, что если вызов tryInt в выражении, то ничего более не надо, а если в чистом виде, то пришлось добавлять в качестве выражения ещё +0(ноль число), тогда чётко работает. Это придётся учитывать.
Что касаемо типов данных в Lua, то считаю, что Владимир прав. На сайте Lua по этому поводу так прямо и написано: "Lua is a dynamically typed language. This means that variables do not have types; only values do. There are no type definitions in the language. All values carry their own type." Так что никаких integer в природе у него нет. Как он там конкретно хранит целые и вещественные и как он их преобразует из одних в другие - только ему и известно. Всё это типа для "упрощения" программирования замутили.
Mikhail написал: Перед подачей заявки на бирже у мен стоит такая функция, работает как часы.
Код
local tostring_ = tostring
local math_tointeger = math.tointeger
function t_ (x)
return tostring_(math_tointeger(x) or x)
end
Этот код будет работать. Но... 1) Зачем здесь вводить переменную tostring_ и загонять в неё адрес функции tostring и потом вызывать косвенно tostring через tostring_, когда можно сразу вызвать напрямую саму tostring? 2) Если в используемой версии Lua есть функция math.tointeger, то проблем не будет, адрес функции будет и присвоится переменной, а если нет? Косяк... Функция появилась в 5.3 версии.
На смартлабе нашёл вот такой код;
local tointeger = math.tointeger or (function(x) return x end)
function tryInt(x) return tointeger(x) or x end
Работает чётко. Мой разбор синтаксиса такой: в tointeger присваивается адрес либо math.tointeger(если таковая есть в используемой версии), либо адрес безымянной функции, возвращающей то же число, что ей передано(имени нет, но адрес то есть, только он и нужен по сути) на этапе интерпретации скрипта. return косвенно вызывает либо math.tonteger либо безымянную функции в зависимости что попало в переменную tointeger. В случае косвенного вызова через tointeger безымянной функции ошибок не будет и в любом случае вызов tointeger(x) вернёт целое значение, оно и вернётся при любом x, а вторая часть "or x" в return не сработает. В случае же косвенного вызова через tointeger функции math.tointeger если без ошибок сработает, то вернётся целое число и так же вторая часть "or x" не сработает, но если вернёт ошибку, то сработает как раз вторая часть "or x" и она вернёт исходное x. Думаю, что этот вариант лучше и надёжнее. Дальнейшее преобразование в строку через tostring() это уже по надобности.
Alexander написал: Кто подскажет как выкрутиться? Вызов getParamEx по инструменту CHZ2(фьючерс на Северсталь) по "OFFER" Беру результат param_value(число), прибавляю к нему целое число. Отправляю транзакцию с этой суммой в цене(через tostring()). Транзакция не проходит. Не правильно указана цена "75941.0" Сообщение об ошибке: Число не может содержать знак разделителя дробной части. Пытаюсь использовать вместо param_value -> param_image(строка с числом без точки и знаков после неё). Но к стрингу не прибавляет число, прогоняю его через tonumber(), - возвращает ошибку nil. Как конкретно взять целое число, сложить и отправить стринг без дробной части? Неужели извращаться и обрезать строку? Вообще не понятно почему не работает tonumber() по параметру param_image? Если просто например написать tonumber("7777777"), то всё нормально - возвращает число. Просто бред какой-то.
Написал тестовый код: PriceBaseSell = tonumber(getParamEx(ClassCodeBase, SecCodeBase, "BID").param_image) - SpredOnSellBase PriceFutBuy = tonumber(getParamEx(ClassCodeFutures, SecCodeFutures, "OFFER").param_image) + SpredOnBuyFut local row = InsertRow (tbl.t_id, - 1 ) SetCell (tbl.t_id, row, 1 , tostring(PriceBaseSell), PriceBaseSell) SetCell (tbl.t_id, row, 2 , tostring(PriceFutBuy), PriceFutBuy) Результат с ошибкой: scripts\test2.lua:56: attempt to perform arithmetic on a nil value
Если поменять param_image на param_value то будеn работать, но в таблицу выводит числа с дробной часть после точки.
Кто подскажет как выкрутиться? Вызов getParamEx по инструменту CHZ2(фьючерс на Северсталь) по "OFFER" Беру результат param_value(число), прибавляю к нему целое число. Отправляю транзакцию с этой суммой в цене(через tostring()). Транзакция не проходит. Не правильно указана цена "75941.0" Сообщение об ошибке: Число не может содержать знак разделителя дробной части. Пытаюсь использовать вместо param_value -> param_image(строка с числом без точки и знаков после неё). Но к стрингу не прибавляет число, прогоняю его через tonumber(), - возвращает ошибку nil. Как конкретно взять целое число, сложить и отправить стринг без дробной части? Неужели извращаться и обрезать строку? Вообще не понятно почему не работает tonumber() по параметру param_image? Если просто например написать tonumber("7777777"), то всё нормально - возвращает число. Просто бред какой-то.
Ваш ответ похоже соответствует действительности. Я пришёл к такому же выводу. Но... Так как описано в документации квика, это нечто. Там нет разделения описания по акциям и по фьючерсам. В этом самом 5-ом разделе есть подраздел "Вввод заявки", а в нём подподраздел "Окно «Ввод заявки»", там есть пункты 4 и 5 и там так написано, что ничего конкретного относительно акций и фьючерсов и вообще как попало написано
Alexander написал: Вот ещё хочу тут спросить старожилов по такому поводу. Скрипт на Lua сначала делает продажу акций Лукойл по рынку в шорт 10 шт через sendTransaction() при этом естественно ставлю TYPE="M", PRICE="0". Транзакция проходит, заявка исполнилась нормально. Следующая транзакция на покупку фьючерса "LKZ2", т.е. LKOH-12.22 в количестве 1шт так же по рынку, где в sendTransaction() установлено так же TYPE="M", PRICE="0". Но при этом транзакция с ошибкой: Ошибка создания заявки. [GW][332] "Нехватка средств по лимитам клиента." Пытаюсь купить данный фьючерс вручную в квике, установив галочку в окне ввода заявки "Рыночная" - результат опять та же самая ошибка! В результате фьючерс купил таки вручную, указав цену на покупку из стакана равную лучшей цене продажи. Транзакция прошла без ошибок и заявка тут же исполнилась. Да мог бы поставить цену покупки и выше чем лучшая цена продажи на несколько пунктов, это я знаю, и заявка ушла бы так по лучшей рыночной цене. Но вопрос: почему sendTransaction() работает на покупку/продажу акций по рынку с значениями TYPE="M", PRICE="0", а на покупку/продажу фьючерса с значениями TYPE="M", PRICE="0" выдаёт ошибку: "Нехватка средств по лимитам клиента." и я вынужден ставить цену хуже рынка, чтобы заявка ушла по рынку? Заявка то в конечном итоге прошла, значит средств достаточно!
Рыночных заявок на срочном рынке нет, на самом деле. Брокер Они отправит их по верхней|нижней границе допустимого ценового диапазона. Так происходит, потому что размер ГО, блокируемого под сделку, зависит от цены сделки. И чем дальше цена от цены последнего клиринга, там ГО будет выше. Хотя реальная сделка и будет не так далеко, но расчет ГО у брокера будет по цене ордера. Так что на сделку в 200 пунктах от цены клиринга может и хватает, а вот уже на сделку в 2000 пунктах - нет. Но такое происходит, если торговать на границе доступных средств. Когда средств достаточно, то и "по рынку" пройдет сделка.
Ну как бы есть или нет на срочном рынке заявки по рынку это вопрос отдельный, потому как например фьючерсы на юань у меня спокойно скрипт покупал и продавал по рынку по 1 шт(от шёлка мышкой, так просто для ускорения исполнения писал, чтобы не вводить вручную). Я так же склонялся и склоняюсь к тому, что ГО разное на разных ценах и по границам Min/Max оно скорее всего превысило - об этом подумал сразу. Но, что интересно, раньше вроде бы, если мне память не изменяет было такое, да - вручную ввод заявки по фьючерсу на одной цене - ГО показывает одно, на другой цене дальше к границе стакана - ГО другое. Но сейчас хоть на какой цене ни щёлкай - ГО одно и то же показывает в окне ввода заявки, оно точно соответствует тому ГО, что в ТТТ для инструмента. Поэтому и решил здесь спросить.
Вот ещё хочу тут спросить старожилов по такому поводу. Скрипт на Lua сначала делает продажу акций Лукойл по рынку в шорт 10 шт через sendTransaction() при этом естественно ставлю TYPE="M", PRICE="0". Транзакция проходит, заявка исполнилась нормально. Следующая транзакция на покупку фьючерса "LKZ2", т.е. LKOH-12.22 в количестве 1шт так же по рынку, где в sendTransaction() установлено так же TYPE="M", PRICE="0". Но при этом транзакция с ошибкой: Ошибка создания заявки. [GW][332] "Нехватка средств по лимитам клиента." Пытаюсь купить данный фьючерс вручную в квике, установив галочку в окне ввода заявки "Рыночная" - результат опять та же самая ошибка! В результате фьючерс купил таки вручную, указав цену на покупку из стакана равную лучшей цене продажи. Транзакция прошла без ошибок и заявка тут же исполнилась. Да мог бы поставить цену покупки и выше чем лучшая цена продажи на несколько пунктов, это я знаю, и заявка ушла бы так по лучшей рыночной цене. Но вопрос: почему sendTransaction() работает на покупку/продажу акций по рынку с значениями TYPE="M", PRICE="0", а на покупку/продажу фьючерса с значениями TYPE="M", PRICE="0" выдаёт ошибку: "Нехватка средств по лимитам клиента." и я вынужден ставить цену хуже рынка, чтобы заявка ушла по рынку? Заявка то в конечном итоге прошла, значит средств достаточно!
Владимир написал: 1. Я уже говорил, что Ваше выставление и снятие 200 тысяч заявок за 4 часа иллюстрирует лишь полную беспомощность алгоритма торговли - у нормальных людей заявки ставятся не для того, чтобы их снимать, а для того, чтобы они исполнялись. Мои заявки, например, исполняются в 90% случаев и более.
Владимир, а может быть nikolz специально ставит в стакан заявки и потом их снимает не для того, чтобы исполнить, а может быть для того, чтобы сбить с толку других роботов, заставить их сработать, или нет, мало ли?
Alexey Danin написал: Здравствуйте. Но я спрашиваю конкретно для своего наипростейшего случая, что описал выше. Например - покупка 1 лота. Нужен контроль того, что покупка 1-го лота 100% прошла и только тогда подавать на продажу того же 1-го лота. Какой алгоритм контроля применить посоветует техподдержка? Уж куда проще то? Мой алгоритм подойдёт? Или можно его упростить, например - вообще не использовать OnTrade()? Достаточно проверить OnOrder() где баланс = 0? Сейчас использую и то и то. А надо ли? Вроде работает.
Объясняю как я делаю это. -------------------------------- Например, циклический тест выставления и снятия заявки. Это тест подобен Вашей задаче. Отличие лишь в том, что я контролировал снятие заявки, а Вы контролируете исполнение заявки. Но алгоритм , описанный ниже решает обе задачи. ================ Результат тестирования алгоритма, показал его безошибочную работу при случайном выставлении и снятии заявки по 200 инструментам. За 4 часа теста на демо сервере выставлено и снято 200 тысяч заявок без единой ошибки. ================== Алгоритм: ------------------------------ Преамбула: Робот - это конечный автомат, который изменяет свое состояние в зависимости от внешних сигналов и своей цели. Источником внешних сигналов являются колбеки. ------------------------ В моем роботе задействованы все колбеки, описанные в документации библиотеки QLua Заверяю Вас, что лишних колбеков нет. Вы можете не использовать какие-либо колбеки, но это подобно тому, что у человека отключить какой-либо орган. ------------------------------- Если Вы колбек выкидываете, то ваш робот не видит многих событий и просто зависнет в один прекрасный момент. =========== Если инструмент, по которому я хотел бы выставить заявку активен ,т е произошло событие по данному инструменту ( сделка, изменение заявки), то проверяем по таблице заявок есть ли активная и по таблице транзакций есть ли активная по этому инструменту. ---------------------- Если есть активная , то новая заявка не выставляется, иначе выставляется. ----------------- В более продвинутом алгоритме выполняется анализ актуальности текущего состояния , но это уже другая задача.
Ну я собственно использую большинство колбэков, и для контроля исполнения использую и OnOrder() и OnTrade() впаре чисто для повышения надёжности. Хотя уверен, что и OnTrade() было бы вполне достаточно. Работает и ладно.
Alexander написал: Какой алгоритм контроля применить посоветует техподдержка? Уж куда проще то? Мой алгоритм подойдёт? Или можно его упростить, например - вообще не использовать OnTrade()? Достаточно проверить OnOrder() где баланс = 0? Сейчас использую и то и то. А надо ли?
Вы можете протестировать Ваши алгоритмы, проанализировать и выбрать более эффективный для Вас. Протестировать можно на учебном сервере QUIK Junior .
О как! Интересно. Даже не знал, что есть такая возможность. Учтём.
А я вот решил почему-то ещё и ждать прихода самой сделки, использую OnTrade(). Может это и не надо. Что скажут разработчики? Нужен ли двойной контроль?
Владимир написал: Alexander, У меня заявки могут исполняться за произвольное количество сделок, так что любой приход OnTrade, не отфильтрованный как дубль, корректирует оставшееся количество лотов в заявке, а сам элемент стека удаляется уже в другом месте - либо по снятию, либо действительно по нулевому остатку.
Ваш алгоритм в принцине понял. В конечном итоге полное исполнение всё равно идёт по балансу в OnOrder().