Проблемы с трансляцией данных о лимите свободных средств, Трансляция данных о свободных средствах в терминале, а также в таблицах Quik-Lua противоречива и в ряде случаев некорректна.
Проблемы с трансляцией данных о лимите свободных средств, Трансляция данных о свободных средствах в терминале, а также в таблицах Quik-Lua противоречива и в ряде случаев некорректна.
Сервер QUIK определяет максимальное количество бумаг при котором не будут нарушены условия используемой маржинальной схемы.
Цитата
Иван Ру написал: В терминале, в "Итогах" таблицы "Состояние счета", в поле "Свободно" объем денежных средств также отражается верно.Фактически можно выставить заявку на существенно больший объем чем отображается в поле "Max" - пропорционально объему денежных средств, которые видно, через поле "Свободно" в "Итогах".
Как Вы поняли, где отображается верно, а где нет? Вы выставляли заявку на большее количество чем есть в "МАХ"?
Уважаемая Анжелика, я же изначально написал : "Фактически можно выставить заявку на существенно больший объем чем отображается в поле "Max"". Таки да, это именно это и значит: я выставлял заявки на больший объем вручную. Уточняю: прямо непосредственно в том окне заявки вводил большее чем в поле "макс" количество в лотах, и она выставлялась. Для меня это настолько странно и непривычно, что я довольно долго вообще не подозревал, что так было можно, попробовал только после разговора с брокером. А поскольку через quik я торгую уже много лет, я позволю себе опять повторить: случается то, чего в принципе быть не должно, часть транслируемых значений о лимитах стабильно некорректны. И еще раз: я давно использую несколько терминалов и несколько счетов. Проблема только в одном.
Проблемы с трансляцией данных о лимите свободных средств, Трансляция данных о свободных средствах в терминале, а также в таблицах Quik-Lua противоречива и в ряде случаев некорректна.
Использую Quik версии 11.0.0.92 на нескольких счетах. На одном из счетов неверно транслируются данные о лимите свободных средств.
Неверные данные получаемые в поле таблицы lim_non_margin (функция getPortfolioInfoEx) при работе с LUA В самом терминале также неверно отображается лимит на количество лотов, которое можно приобрести на срочном рынке (поле "Max", ниже окошка ввода количества лотов). В терминале, в "Итогах" таблицы "Состояние счета", в поле "Свободно" объем денежных средств также отражается верно. Фактически можно выставить заявку на существенно больший объем чем отображается в поле "Max" - пропорционально объему денежных средств, которые видно, через поле "Свободно" в "Итогах". Разница между некорректным (заниженным) и истинным значением (поле "Свободно") - несколько порядков. Пробовал: обновление, смену сервера, перезаказ данных - безрезультатно. Проблему наблюдаю несколько недель.
В чем проблема? Вручную заявки выставлять еще можно, но робот без верных данных работать не может.
Старатель написал: Как вариант, где-то в цикле main используется return Иван Ру, ваш вопрос звучит примерно так: "Угадайте, что в чёрном ящике"? Вряд ли кто-то сможет помочь.
Речь об инструментах устранения ошибок, не о том, чтобы это кто-то сделал за меня. Хотя за подсказки тоже благодарен. Вот был уверен что return у меня в цикле нет, но после вашего замечания решил перепроверить и один таки нашел...
Nikolay написал: Отладчик Вам не поможет, если ошибка спонтанная, т.е. зависящая от данных. Допустим индексация значения nil, ожидая table.
В этом случае Вам проще обернуть критические функции в pcall, перехваченные ошибки записывать в лог. При этом надо обязательно добавить assert на входяшие данные. Если ожидаете таблицу, проверьте что она и пришла. Ждете строку, проверьте, что она есть. Тогда исключение по таким проверкам Вам и дать искомую ошибку.
На данном этапе проблема в том, чтобы понять в каком месте ошибка, т.к. сообщения нет, а код очень велик... Если бы проблема была в неверном типе данных, сообщение об ошибке должно было бы приходить, насколько я понимаю...
Простой пример. Торгую я (вы) фьючерсами. Скрипт не трогаем, хотим чтобы он работал сам многие дни. Значит у нас периодически, желательно ежедневно, надо инициировать инструментов вплоть до выбора их корректного названия кода, на основе соответствующей таблицы из Квик, которая периодически меняется/обновляется. У меня эта задача реализована так - в двух случаях, 1) при смене даты, 2) при проходе через временную точку 9 часов 40 минут вызывается функция инициализации инструментов-стратегий. Задача делается отчасти с помощью подгружаемого модуля, который сравнивает короткие коды инструментов, их календарный индекс с данными настроек стратегии в роботе. Раньше вызов этих функций делал в OnInit и Main, теперь - только в main. Правда периодически случается что дата на сервере меняется после 10.00 !! По крайней мере такие данные прилетают... Интересно, кто как решает типовые задачи, какую архитектуру при этом использует. Например, чтение последней цены, бид-аск - в пределах main (быстрее) или вызовом отдельной функции. Ну ок, у вас отдельная функция, что функционально, пардон за тавтологию. Но если я читаю бид-аск 20 раз за секунду, по 10-ти инструментам, позволительно ли это делать в отдельной функции? Все относительно, но все же - какое количество вызовов сторонней функции позволительно для ресурсов мощной машины на ваш взгляд (очень грубой оценки достаточно).
Иван Ру написал: Тогда вопрос: возможен ли такой вариант, что при остановке скрипта в результате ошибки никакое сообщение об ошибке (в окне "Доступные скрипты" в поле "Ошибки выполнения скрипта") не выводится. Или ошибка исполнения всегда сопровождается соответствующим сообщением?
Нет.
Цитата
Иван Ру написал: П.С. Код на 2600 строк, в нем непросто разобраться.
тогда без шансов.
Можете посоветовать внешние отладчики или другие методы позволяющие выявить место ошибки в скриптах в случаях, когда никакого сообщения о ней не приходит?
Иван Ру написал: - Целесообразно ли минимизировать использование колбэков и как?
Это вопрос архитектурный. Варианта два.
Первый - это event-driven архитектура, тут колбеки движущая сила всего, пришел колбек - это событие, вы это событие как-то обрабатываете, если обработка предполагает что-то тяжелое - вы только запускаете операцию и возвращаетесь из колбека, а о ее завершении вам сообщит другой колбек, уже ваш собственный.
Второй это поллинг, ваш мейн шаг за шагом следует какому-то плану. Где ему нужны какие-то данные, он их заказывает и ждет ответа, где нужно что-то отправить он отправляет и ждет ответа. Уже по описанию видно, насколько шустро оно будет работать, хотя есть, несомненно, задачи, в которых и так сойдет. Другой недостаток - вы видите какое-то событие только в тот момент, когда решили на него посмотреть, а оно может уже часа два как произошло. Например, пока вы считали что-то и готовили транзакцию, квик потерял соединение, но вы еще об этом не знаете и продолжаете готовиться к своей сделке века, которая закончится ничем, бо нет коннекта. Утрирую для наглядности.
Третий вариант это как тут часто в вопросах попадается, когда смешали все в кучу и получилась, естественно, куча
Что касается этого аспекта - выбор я уже давно сделал в пользу второго варианта, коллбэки я либо не использую, либо они играют второстепенную роль. Колбэк я считаю вариантом не надежным (задержки, не сработал и т.п.), в то время как обработка в теле main позволяет не только получать данные, но и разные статусы, например, соединения нет, торгов нет, данные ни фига не получены, или они получены, но вряд ли актуальны. Картина получается куда полнее. С учетом того, что скорость транзакции у меня составляет порядка 150 мс, мне достаточно раз в 50 мс пробежаться по нужным параметрам в main, не вижу особого смысла в коллбэках разве только как в страховке или способе финальной верификации данных (о транзакции). Меня больше интересует архитектура в плане разделения на модули и классы, степени их универсальности, способе подгрузки, компоновки рабочей стратегии из разных элементов конструктора.
Ребята, вы о высоком, признаться я уже не все понимаю. Если вернуться к реальности, где основная масса, включая меня - любители, а не профессионалы в программировании, и мы имеем, то что имеем, остаются интересные вопросы с потенциально возможными интересными ответами.
- Целесообразно ли минимизировать использование колбэков и как? - Стоит ли писать общие классы-таблицы для роботов? - Как конкретно оптимально подгружать универсальные функции... И т.п. и т.д.
Иван Ру написал: Интересно мнение форумчан - как предпочитаете писать скрипты - все в одном файле или в виде конструктора - с подгрузкой отдельных файлов: 1. Отдельных функций/процедур (выставление заявки, считывание определенных данных и т.п.) 2. Отдельных классов (стратегия, позиция и т.п.)
Существующая структура QLUA имеет существенный недостаток. Все колбеки вызываются из одного потока и каждый из них повторяется в различных скриптах. В итоге получается дублирование одних и тех же действий многократно. Я устранил эту проблему и сделал механизм при котором колбеки в скриптах не повторяются, а скрипты могут запускать функции друг у друга и получать данные из других скриптов.. ------------------------- В итоге не только повышается скорость, но и размер кода сокращается в десятки раз.
Признаться, все более склоняюсь в сторону такой модели, в первую очередь из-за разрастания скрипта и усложнения его логики из-за чего работа и модификация скрипта становится все более затруднительной... Полагаю можно использовать такую структуру: - базовый скрипт, который определяет статус сессии и агрегирует информацию из коллбэков - описание классов (стратегия, позиция и т.п.) - типовые универсальные модули, например, удаление устаревшей части данных таблиц (цены, бид аск и т.п.), ежедневное определение ключевых временных точек сессии в формате posix, визуализация и логгирование информации и т.п. - собственно скрипты с описанием стратегий, логики определение сигналов на вход и выход и сопутствующих действий...
Если кто-то поделится своим видением организационной структуры - буду признателен
Поясню свое прежнее беспокойство - у меня большинство скриптов работает одновременно с большим числом инструментов, предполагается большой объем расчетов, опасаюсь, что в тех случаях когда они осуществляются не в теле основного потока (main), а путем многократного вызова функции, это может негативно сказаться на быстродействии скрипта.
Nikolay написал: Когда у Вас скрипт на тысячи, десятки тысяч строк, то писать в одном файле это смело. А когда у Вас уже написано много скриптов, то придешь к модулям, т.к. каждый раз писать одно и тоже - это тоже смело. При этом модуль - это не команда dofile в глобальном окружении, а нормальный модуль, подключаемый через require.
Я тоже думаю об этом, но вижу определенные минусы - если блок кода выносишь в отдельную функцию / подключаемый модуль, мы теряем в загрузке памяти и скорости. Вызов отдельной функции требует больше времени, чем исполнения кода в основном потоке. Универсальный функционал модуля требует бОльшего числа полей, которые должны удовлетворять самые широкие потребности. Вот и интересно, кто как пишет, в каких ситуациях какие варианты предпочитают. Используют ли подгружаемые классы-таблицы... и т.п.
Sergey Gorokhov написал: Иван Ру, По присланной части кода разобраться не представляется возможным, думаю Вы сами это понимаете. если хотите чтобы Вам помогли пришлите весь код.
Скрипт может остановиться в трех случаях либо его остановили вручную либо был выход из main либо произошла ошибка.
Всё никаких других вариантов нет и быть не может и это совершенно точно. Без полной версии кода, очевидно что мы не сможем проверить ни один из пунктов.
Тогда вопрос: возможен ли такой вариант, что при остановке скрипта в результате ошибки никакое сообщение об ошибке (в окне "Доступные скрипты" в поле "Ошибки выполнения скрипта") не выводится. Или ошибка исполнения всегда сопровождается соответствующим сообщением?
П.С. Код на 2600 строк, в нем непросто разобраться.
спасибо, нашел дурацку ошибку, объявил булеву переменную с тем же именем в oninit, поэтому сначала функция срабатывала как и полагается, а потом - получал ошибку.
Под программной проверкой - имею ввиду скрипты на языке LUA Кстати, OnTransReply в описываемом случае возвращает статус "4", а не "6" (нехватка лимитов).
Робот пытается выставить заявки и по части из них на разных счетах приходит сообщение о неудачной попытке. "Ошибка создания заявки [GW][332]. Нехватка средств по лимитам клиентам" Срочный рынок, инструменты AFZ0, CHU0, MNU0 и др. При этом данные таблиц свидетельствуют что средств достаточно. Например, пытается выставить две заявки CHU0 по которым ГО составляет около 33 тысяч рублей. При этом в соответствии с данными таблицы "Состояние счета" свободных средств порядка 300 тыс. руб., а доступное количество заявок на покупку и продажу - 9 и т.п. С чем может быть связана проблема? Есть ли способ программно проверить достаточность лимитов непосредственно перед выставлением каждой заявки?
Вот так ругается на строку кода в цикле расположенном в пределах main, где пытаюсь считать статус соединения... while is_run do sleep (50) if isConnected() == 1 then .. -- не могу понять, что тут написал не так, ругается на эту строку ... end
swerg написал: Sergey Gorokhov , скажите: я верно понимаю, что скрипт останавливается только в 2-х случаях: 1) Либо произошел корректный выход из main() -> тогда в окне скриптов не будет ошибки (и других сообщений) 2) Либо произошла какая-то (любая) ошибка -> тогда в окне скриптов гарантированно будет отображена ошибка
Верно? других вариантов нет? Точно нет?
Если так, то Иван Ру будет достаточно добавить логирование условия выхода из цикла main() и всё станет понятно.
Добрый день! Я стараюсь придерживаться этого принципа - логгировать все... 1. Нет в логике скрипта возможности выхода из main, только остановка вручную. Скрипт должен после запуска крутиться бесконечно - и крутился, неделями. Плюс есть логгирование, которое фиксирует такой выход... Скрипт обрывается обычно в периоды частого выставления заявок, например, в начале сессии. Может, судя по логгированию, останавливаться в разных местах выполнения. Обычно это дополнительные функции по обработке заявок - стандартная Ontrasreply или функция написанная мной. Но четкой закономерности проявления ошибки нет. 2. В том и проблема, что никакого сообщения об ошибке нет... Если бы ошибка отображалась, было бы просто...
Интересно мнение форумчан - как предпочитаете писать скрипты - все в одном файле или в виде конструктора - с подгрузкой отдельных файлов: 1. Отдельных функций/процедур (выставление заявки, считывание определенных данных и т.п.) 2. Отдельных классов (стратегия, позиция и т.п.)
Nikolay написал: Что значит по нескольким? Где: в скрипте или в индикаторе
1. Текущий день - несколько дней до этого - исторические данные 2. В скрипте 3. Нужно по большому числу инструментов, использование графиков в терминале нежелательно или невозможно.
Константин Рейм написал: у меня бзик - по "феншую" должно быть и все))).
чтобы было по фэншую можно сделать так
Код
CLASS_CODE = "SPBFUT" -- Класс бумаги
SEC_CODE = "RIM0" -- Код бумаги
IsRun = true
function main ()
-- Округление по Фэншую
-- status = tostring(math.modf(getParamEx(CLASS_CODE, SEC_CODE, "TRADINGSTATUS").param_value)) -- Вариант 1
status = tostring( math.modf ( getParamEx (CLASS_CODE, SEC_CODE , "STATUS" ).param_value)) -- Вариант 2
message (status)
while IsRun do
sleep ( 1 )
end
end
function OnStop () -- Функция вызывается когда пользователь останавливает скрипт
IsRun = false
end
Но сейчас наверное уже все забыли чего я добивался. Этой функции нужно давать пинка под зад, чтобы каждую минуту мониторился статус. У меня скрипт завязан на минутные бары и получается, что без статуса не грузятся некоторые значения в таблицу в 13:59, 18:44 и 23:49. Пытался сделать кикстартер на основе os.time, но ничего не получилось.
А в чем проблема? Переменную переместите в цикл while do, только задержку слип сделайте побольше, например 100 миллисекунд, - соответственно 10 раз в секунду будете получать данные по текущему статусу
Иван Ру написал: Как в такой ситуации определить причину неожиданной остановки скрипта?
Добавить в скрипт логирование всего, и по факту остановки смотреть что было последним.
У меня как раз такая реализация, но она прояснить проблему не позволяет... Судя по логам дело происходит так. Мой скрипт периодически удаляет заявки, затем проходит обработка для того чтобы учесть факт успешного/неуспешного удаления заявки. Все это в цикле с частотой около 50 миллисекунд. Остановка происходит обычно так - происходит успешное удаление заявки, в OnTransReply происходит обработка данных + специальная функция успешно обрабатывает /учитывает полученный результат и благополучно завершается. После этого скрипт работает доли секунды (прокручивается несколько циклов) и прекращает работу без сообщения об ошибке... OnStop не инициируется и не запускается, т.е. она ни при чем. В подавляющем большинстве случаев при наступления события (успешная транзакция по удалению заявки) никакой остановки не происходит, все работает штатно. Ошибка наблюдается на терминалах версии 8.5 Код:
function fProcessReply (reply, place, clos, sec_code, pos, order_num, trans_id, Price) -- reply - отклик по транзакции, place -- на размещение TRUE, clos - закрытие позиции TRUE, sec_code, pos - позиция ОБЪЕКТ, order_num - номер заявки, trans_id - номер транзакции, Price - цена -- обработка ошибок if clos == nil then clos = pos.temp ; end local dir = 1 -- направление сделки if pos.dir == "S" then dir = -1; end -- корректируем его при необходимости local result = "" writeLog('fProcessReply'..";".."Try to process"..";"..sec_code..";"..tostring(place)..";".."order_num"..";"..tostring(order_num)..";".."trans_id"..";"..tostring(trans_id)) if reply ~= '' then -- ОШИБКА (Это верно и для заявок на размещение и для заявок на удаление, значит необходимо оставить неизменным прежний статус заявки !!!! result = false ; writeLog('fProcessReply'..";".."Error") fRejectedOrderCase (sec_code, pos) -- запуск функции по обработке ошибочной транзакции !!! перепроверить else -- УСПЕШНАЯ ОТПРАВКА (ответное сообщение нулевое) result = true -- Формируем базовые переменные local SubDir = 0 -- поднаправление (размещение / закрытие) local dirQty = 0 -- изменение лотов с учетом направления local lotSize = pos.lotSize -- объем заявки в лотах (для заявки на удаления - остаток в лотах) if pos.executedLots then lotSize = lotSize - pos.executedLots ; end -- корректируем с учетом остатка -- Записываем общие (для заявок на размещение и удаление) флаги pos.trans_id = trans_id; -- записываем номер ордера (uniq_trans_id - далее userId) в соответствующее поле позиции - это будет нужно для последующего поиска сделки pos.placed = place writeLog('fProcessReply'..";".."Placed flag"..";"..sec_code..";"..tostring(place))
if place == true then ----------- если заявка на РАЗМЕЩЕНИЕ ------------------------------------- writeLog('fProcessReply'..";".."Place order success") SubDir = 1 pos.PricePlaced = Price; -- записываем цену заявки pos.posixOrig = tpCurTime -- записываем текущее время сделки -- заявки на закрытие if temp == true then -- блокирование снятой временной позиции на закрытие -- writeLog('fProcessReply'..";".."Block pose after killed"..";"..sec_code..";".."index"..";"..tostring(pos.index), true) else -- размещена постоянная позиция на ВХОД -- устанавливаем верхнюю и нижнюю границы для позиции на вход local dopuskForPos = pos.dopusk local dopuskHigh = 1 + pos.dopusk/100 local dopuskLow = 1 - pos.dopusk/100 pos.lowP = pos.basePrice * dopuskLow -- Базовая цена (оффер или бид) умножается на верхний коэффициент (верхний допуск) pos.highP = pos.basePrice * dopuskHigh writeLog ('fProcessReply'..";".."Define price limits"..";"..sec_code..";".."Price"..";"..tostring(Price)..";".."lowP"..";"..tostring(pos.lowP)..";".."highP"..";"..tostring(pos.highP), true) end ----------- если заявка на УДАЛЕНИЕ ---------------------------------- else writeLog('fProcessReply'..";".."Delet order success") SubDir = -1; -- Обнуляем ключевые параметры pos.PricePlaced = 0; -- записываем цену заявки pos.donttuch = curPosixTime + IdleTimeAfterKill writeLog('fProcessReply'..";".."Change qty for killord"..";"..sec_code..";".."pos.lotSize"..";"..tostring(pos.lotSize)..";".."pos.executedLots"..";"..tostring(pos.executedLots), true) checkOrder, dirCheck, balanceQty = fFindOrderAndCheckDirBalance (order_num) -- ищем заявку в таблице заявок if checkOrder == true then -- если удалось найти заявку в общем списке заявок lotSize = balanceQty dir = dirCheck writeLog('fProcessReply'..";".."Rechange qty for killord"..";"..sec_code..";".."balanceQty"..";"..tostring(balanceQty)..";".."dirCheck"..";"..tostring(dirCheck), true) end -- если удалось найти заявку в общем списке заявок --Заявка на закрытие if temp == true then -- блокирование снятой временной позиции на закрытие pos.block = true writeLog('fProcessReply'..";".."Block pose after killed"..";"..sec_code..";".."index"..";"..tostring(pos.index), true) else pos.basePrice = 0 ; pos.lowP = 0 -- Базовая цена (оффер или бид) умножается на верхний коэффициент (верхний допуск) pos.highP = 0 end -- удаление снятой временной позиции на закрытие end -- если заявка на РАЗМЕЩЕНИЕ -- Корректировка баланса dirQty = SubDir * lotSize * dir writeLog('fProcessReply'..";".."Lots to balance"..";"..sec_code..";".."dir"..";"..tostring(dir)..";".."SubDir"..";"..tostring(SubDir)..";".."dirQty"..";"..tostring(dirQty), true) if dir == 1 then -- если заявка на ПОКУПКУ tShares [sec_code]['PlacedL'] = tShares [sec_code]['PlacedL'] + dirQty else -- если заявка на ПРОДАЖУ tShares [sec_code]['PlacedS'] = tShares [sec_code]['PlacedS'] - dirQty end -- если заявка на покупку if pos.temp == false then -- если заявка на ВХОД tShares [sec_code]['placedEnter'] = tShares [sec_code]['placedEnter'] + dirQty else -- если заявка на ЗАКРЫТИЕ (temp = true, "C") tShares [sec_code]['placedClose'] = tShares [sec_code]['placedClose'] + dirQty end -- если заявка на вход writeLog('fProcessReply'..";".."Change Balance"..";"..sec_code..";".."dirQty"..";"..tostring(dirQty)..";".."placedEnter"..";"..tostring(tShares [sec_code]['placedEnter'])..";".."placedClose"..";"..tostring(tShares [sec_code]['placedClose'])..";".."PlacedL"..";"..tostring(tShares [sec_code]['PlacedL'])..";".."PlacedS"..";"..tostring(tShares [sec_code]['PlacedS']), true) end writeLog('fProcessReply()'..";"..tostring(result), true) -- return result end
UPD Может ли кто-либо поделиться актуальной библиотекой для проигрывания звуковых файлов, подходящей под 8.5. Использовал w32 bot4sale - больше не работают.
Давно использую скрипт, который работает без ограничения по времени (ночью комп не выключается, утром он обновляет настройки и продолжает работу - очень удобно). В теле main он "бегает" по циклу с определенной паузой. В последнее время он стал самостоятельно спонтанно выключаться по непонятной причине. При этом логи показывают что функция OnStop не запускается, также в окне "Доступные скрипты" нет указания на какую либо ошибку работы скрипта. Соответствующее окно сообщений пусто. Единственная обнаруженная закономерность - работа прекращается после успешного выполнения транзакции по удалению заявки... (это частое действие и в большинстве случаев оно завершается без проблем...) Как в такой ситуации определить причину неожиданной остановки скрипта?
Выше писал единственный, по-моему, более-менее рабочий вариант: открыть ТВС со ВСЕМИ инструментами и засунуть ее куда-нибудь на дальнюю вкладку навечно. Из столбцов можно один какой-нибудь выбрать, значения не имеет. Правда, с этим тоже были какие-то глюки, если другие ТВС открывать-закрывать
Вроде такой вариант не работает. Полагаю с точки зрения потребления ресурсов компа это также не самое удачное решение. Попробовал удалить единственный тиковый график, пока, вроде все работает нормально, возможно дело именно в нем.
Иван Ру написал: Тиковые графики работают корректно, у меня одно окно привязанное к таблице текущих торгов, при переключении между инструментами данные перегружаются.
Вот этот момент раньше не был озвучен и, сдается мне, собака здесь и порылась. Если так, то когда
Цитата
устанавливается фильтр с экспортом данных по одному инструменту (инструмент может быть разный)
, этот "разный" инструмент должен быть как раз тот, на котором стоит фокус в таблице торгов (и, соответственно, открыт тиковый график).
Возможно, перепроверю. Будут ли какие-то рекомендации по исправлению проблемы? В любом случае поведение Квика странно.
Правильно понимаем, что Ваше затруднение по-прежнему актуально? Если так - просьба уточнить, независимо от Ваших наблюдений за фильтром в пункте меню Система/Заказ данных/Поток обезличенных сделок - при работе с таблицей обезличенных сделок и тиковыми графиками - получаете ли Вы данные по обезличенным сделкам для наполнения таблица и построения графиков? Или напротив - в какой-то момент замечаете, что данные перестают поступать - и Вы проверяете настройки заказа данных по обезличенным сделкам, где обнаруживаете сброшенные фильтры?
Также просьба уточнить, до и после (произвольного) отключения заказа данных по обезличенным сделкам - отмечаете ли Вы какие-либо конкретные действия, которые стабильно приводят к описанному эффекту? - какие? Имеют ли место при этом переподключения к серверу/перезапуск терминала/загрузка настроек из файла?
Кроме того - Вы упомянули, что используете некие lua-скрипты. Просьба сообщить, если работать без них - воспроизводится ли описанный эффект?
Здравствуйте! Да, проблема наблюдается постоянно. Пробовал сбрасывать галочку "Фильтр" - выбора инструментов, также добавлять все инструменты с использованием фильтра. Приблизительно через 1-3 часа настройки сбрасываются, устанавливается фильтр с экспортом данных по одному инструменту (инструмент может быть разный). Тиковые графики работают корректно, у меня одно окно привязанное к таблице текущих торгов, при переключении между инструментами данные перегружаются. Я замечаю проблему по статистике которую выводят роботы (они у меня фиксируют количество колбэков в OnAllTrade и выводят статистику, если цифра не растет - очевидно, проблема). Захожу в настройки и вижу что фильтр сброшен. Нет, я не вижу каких-либо действий которые приводят к проблеме, кроме того, что у меня функционируют роботы, которые регулярно запрашивают данные по стаканам порядка 10-15 инструментов. Без скриптов я не работаю (торгую только ими), но попробую провести такую верификацию.
Денис написал: А если использовать нижеследующий алгоритм: 1.Выбираем нужный график 2.Нажимаем Ctr+N 3.Имеем два идентичных графика . 4.Правой кнопкой мыши по графику, выбираем параметры диаграммы. 5. Нажимаем заменить инструмент 6.Выбираем нужный инструмент. 7.Сохраняем. 8.Имеем две одинаковые диаграммы с разными инструментами. 9. При желании переносим график на другую вкладку.
То тогда пусть хотя-бы меняет автоматически заголовк окна на новое название инструмента.
А вообще моя мечта, чтоб двойным кликом в окне
Можно, но так 9 действий, не считая переноса окна, а в нормальном исполнении - одно. Если надо много окон создать - проблема.
Старатель написал: Под импортом я подразумеваю загрузку настроек из wnd-файла вручную.
Да, я так и понял. Просто, насколько я понимаю, если бы дело было в wnd файле, проблема проявлялся бы после перезапуска Квик, но никак не в процессе его работы, - а именно так наблюдается у меня.
Nikolay написал: Обычно для фондовой секции требуется добавить символ "/", как разделитель. Плюс, часто брокеры требуют наличие "/" в поле код клеинта.Получается два "/".
Формат такой: client_code/my_comment
При этом число символов ограничено, поэтому после // особо не разгуляешься.
Спасибо, в основном разобрался! СДелал это следующим образом: открыл специальное окно - tri файл, добавил туда заявку отправленную в ручном режиме, проверил форматы полей и код клиента, фирму и т.п. Пока остается вопрос как делать заявки с переносом на следующий день (дни)
На срочном рынке (фьючи) все работает, а вот отправку транзакции на фондовом рынке никак не могу настроить. Кому не жалко - покажите фрагмент кода (желательно, отправка с переносом на следующие сутки) и как должен выглядеть код-клиента. В поддержку финама не дозвониться, код для срочного рынка озвученный сбером никак не подходит... ((
} else -- Выставляем ордер без переноса через клиринги t = { ["CLASSCODE"] = CLASS_CODE , --заявки выставляются только на рынке theClass ["SECCODE"] = SEC_CODE, ["ACTION"] = "NEW_ORDER", ["ACCOUNT"] = accounForSection, --задано в начале функции по умолчанию ["CLIENT_CODE"] = accounForSection, --задано в начале функции по умолчанию !!! раньше было roboNameWithSufix ["COMMENT"] = roboName, --задано в начале функции по умолчанию ["TYPE"] = "L", -- лимитированные заявки ["OPERATION"] = dir, -- направление продажи ('B' или 'S') ["PRICE"] = tostring(CORRECT_PRICE), ["QUANTITY"] = tostring(NumberOfLots), ["Move order"] = "No" , ["EXECUTION_CONDITION"] = execCond, ["TRANS_ID"] = tostring(1234234) }
Воот, такое ближе к телу. Хотя, признаться, у этой техники я вижу слабое место -- одна из ключевых проблем, отключение ПК из-за выключения света на длительный срок, или краш Windows. Такие проблемы данная технология не позволит отследить. А что за функционал для отправки смс?
Kolossi написал: Почему-то у меня все просто, наверное что-то не так делаю )
Робот сваливает логи в заданную папку, а Automator отправляет их мне по e-mail по расписанию. Сообщения, которые кладутся в аварийную папку, Automator отправляет немедленно.
В таком случае надо регулярно смотреть почту, тут идея немного другая - программа читает лог автоматически и анализирует его, информируя (включая звуковой сигнал) при необходимости. В общем - дополнительная автоматизация процесса и страховка когда Вы на отдыхе.
настройте телефон так, чтобы он выдавал уведомление со звуком при получении почты. Стардартная функция того же андроида или любых умных часов.
Зачем? Это будет просто регулярное дрыньканье. Информирование нужно именно в случае наличия проблемы (сообщения нет, или его содержание указывает на появление проблемы).
Kolossi написал: Почему-то у меня все просто, наверное что-то не так делаю )
Робот сваливает логи в заданную папку, а Automator отправляет их мне по e-mail по расписанию. Сообщения, которые кладутся в аварийную папку, Automator отправляет немедленно.
В таком случае надо регулярно смотреть почту, тут идея немного другая - программа читает лог автоматически и анализирует его, информируя (включая звуковой сигнал) при необходимости. В общем - дополнительная автоматизация процесса и страховка когда Вы на отдыхе.
Что-то она не очень простая. Я б завел дешманский хостинг, поставил трехстрочный пхп, который проверяет юзер-агент post или даже get запроса и при его правильности (UUID например или хэш какой-нибудь) пишет тело запроса в файл. А другой примитивный пхп этот файл отдает на правильно сформированный запрос, а на неправильно сформированный не отдает ничего или, если не лень, какую-нибудь заглушку, бесполезный* лендинг, чтобы не будоражить кулхацкеров. И смотреть файл можно откуда угодно браузером или примитивной прогой.
* На практике у меня подобная штуковина (не для квика) на вполне себе полезном сайте стоит, для всех сайт как сайт, а для своего юзер-агента еще и апи.
На вопросы: 1. Путем поглядывания на монитор периодически. 2. Не знаю. Я б вообще поостерегся таких конфигураций, дыряво может получиться.
По п.2. - по-сути нужен доступ к одному файлу в отдельной папке и только на чтение, не вижу ничего особо страшного
Мониторинг работы скрипта - полагаю сверхактуальная задача для большинства поклонников алгоритмической торговли. Особо она важна в тех случаях, когда используются лимитные заявки. Упал скрипт, упал квик, упал комп, нет соединения... - все эти события могут привести к серьезным проблемам... Пришла в голову простая схема, как этот мониторинг может осуществляться: скрипт регулярно, скажем с периодичностью в 1-10 секунд, записывает в специальный файл время и статус / результаты работы, например, наличие соединения, величину вариационной маржи, или количество сделок по счету. На мобильном телефоне используется программа, которая регулярно считывает содержимое файла и сигнализирует пользователю (звуковой сигнал, будильник и т.п.), если время значительно отличается от текущего (что-то "упало"), или же статус / результат торговли не отвечает заданным критериям. Вопрос форумчанам: 1. Как мониторите состояние скриптов Вы? Что думаете по-поводу такой схемы? 2. Знаете ли программу для Андроид, имеющую подобный функционал для удаленного мониторинга ПК, чтения логов и оповещений?
Anton написал: Поэкспериментировал с тиковыми графиками. Адъ. Единственное "пожелание по развитию квика", которое тут все должны единогласно выразить, это убрать фильтры ТВС. Все остальное только усилит наши страдания. Тиковые графики тоже ковыряют фильтры .
Закрываем ТВС, сбрасываем все фильтры, очищаем alltrade.dat. Коннектимся к брокеру. Фильтров нет, таблиц нет, графиков нет, ничего не едет, красота. Открываем один тиковый график RIM0 - ставится фильтр по этому интрументу, заказывается ТВС (именно один RIM0, см. ниже как узнал). График плавненько прирастает. Открываем еще один тиковый график RIU0. Добавляется фильтр по второму инструменту и заказывается RIU0, при этом первый график останавливается и стоит, пока второй не дорастет до того же времени, потом оба двигаются дальше синхронно. Можно погадать, чего он стоит-то, но не будем. Лезем в фильтры и ставим все доступное. Опаньки, поехала вся ТВС. Кто ее заказывал? У нас же только два графика открыты? Ладно, ждем, пока доедет вся. Закрываем первый график - фильтр по нему остается . Закрываем второй график - все фильтры , в том числе поставленные вручную, сбрасываются. Открываем ТВС по всему доступному. Квик долго жужжит вентилятором (ну почти как при массовой подписке из луа), потом успокаивается и показывает нам ТВС, там все ок. Чего он жужжал? А он, ребятки, сортировал ТВС в окне . У нас же сперва один инструмент приехал, потом другой, потом все остальные, а в табличке нам все как положено показали. Да, я в курсе, тысячу раз сказано, что квик ничего не сортирует. Это правда, в alltrade.dat оно как приехало, так и лежит. Сортирует таблица, ну окно то есть. Как увидеть, как оно в alltrade.dat лежит? А из луа экспортнуть, оно как раз в том порядке и сохранится, сначала (почти) весь RIM0, потом в него вклиниваются записи RIU0, потом гуртом все остальные, а уж дальше как обычно, остатки RIM0 и RIU0 вперемешку с прочими.
Короче вывод - в топку фильтры ТВС. Чем быстрее тем лучше. И всем будет счастье.
Признаться я так и не понял, какой вывод для моей ситуации - вручную поменять SPBFUT=ALL ? Тиковые графики у меня есть, пару штук...
CreateDataSource нет, но есть многократный вызов Subscribe_Level_II_Quotes(--). Раньше (до 8ой точно) тот же скрипт работал корректно. В настроечном файле отображается так как и в квике текущие настройки - всего один инструмент в секции фьючей, хотя вот эта строка меня смущает "req-all-trades-from-curr-moment=0": [ALL_TRADES_DATA] EQBR=LKOH, MSNG, RTKM, RTKMP EQNE= TQBR= SPBFUT=BRK0 req-all-trades-from-curr-moment=0 SPBXM= CETS= CROSSRATE= SPBBND= EQOB= EQEO= EQDB= SMAL= INDX= EQRP_INFO= TQDE= TQOB= TQIF= TQTF= TQOD= INDXC= RTSIDX= USDRUB= TQTD= TQCB= TQTE=
Использую квик 8.2.13. брокер Финам Для торговли в Lua использую поток обезличенных сделок по классу FORTS, Использую меню Система / Заказ данных / Поток обезличенных сделок и добавляю все инструменты из этого класса в число выбранных, по которым должны импортироваться обезличенные сделки. Однако через короткий промежуток времени (минуты, часы) импорт соответствующих данных прекращается, если зайти в упомянутое выше меню, видно, что там ничего не выбрано или выбран лишь один инструмент, сейчас это ближний фьючерс на нефть). Что за чудеса?
При попытке логгирования изредка появляется ошибка доступа к открытому текстовому файлу: attempt toi use closed file. Как корректно обработать эту ошибку, чтобы она не приводила к остановке работы скрипта? Как проверить открыт ли файл или нет, перед попыткой записи?
Используя меню Система-Заказ данных - Поток обезличенных сделок - выбираю все доступные инструменты по классу "ФОРТС фьючерсы" (Добавить все - Сохранить). Однако, по прошествию некоторого времени вижу, что выбранные инструменты вновь переходят в недобавленные - надо повторять операцию по новой. Что это такое? Пытался ставить галку "Получать информацию по всем обезличенным сделкам с текущего момента" - не помогает...