Использую мобильный интернет для торговли. После потери соединения Quik 8.11 начинает переподключаться. После переподключения останавливается скрипт и запускается только руками. Все расчеты в is_run = True function main() ....while is_run do ... end
Функцию OnStop() не использую, пробовал с ней, результат такой-же. function OnStop() ....is_run = false end
Скрипт не должен завершаться при разрыве соединения, если, конечно, это специально не реализовано.
Поэтому возникают следующие вопросы: 1) Скрипт молча останавливается или ошибку какую выдает? 2) Если вручную переподключиться, скрипт остановится? 3) Если ли в скрипте колбеки onConnected, onDisconnected, onCleanUp? Если есть, то что в них? 4) Используется ли проверка подключеия isConnected? Если используется, то как именно?
В идеале показали бы скрипт, предварительно удалив из него то, что считаете ком.тайной.
Пользователь
Сообщений: Регистрация: 07.12.2020
28.04.2021 19:59:24
Цитата
BlaZed написал: Скрипт не должен завершаться при разрыве соединения, если, конечно, это специально не реализовано.
Поэтому возникают следующие вопросы: 1) Скрипт молча останавливается или ошибку какую выдает? 2) Если вручную переподключиться, скрипт остановится? 3) Если ли в скрипте колбеки onConnected, onDisconnected, onCleanUp? Если есть, то что в них? 4) Используется ли проверка подключеия isConnected? Если используется, то как именно?
В идеале показали бы скрипт, предварительно удалив из него то, что считаете ком.тайной.
1. Останавливается без ошибок 2. Работает 3. Нет 4. Нет
--настройка параметров function strText(int) local m=tostring(int) local mLen=string.len(int)
if mLen==1 then Output="0" ..tostring(m) else Output=m end return Output end
function main() while is_run do for key, instrument in pairs(ticker_list) do --в цикле перебираем бумаги из ticker_list classcode=getSecurityInfo("",instrument).class_code --получаем класс бумаги (TQBR,SPBFUT,CETS,ect.) по ее тикеру out_file=io.open(pFile..instrument..".csv","w") --открываем с режимом для перезаписи
ds=CreateDataSource(classcode, instrument, iNterval ) --создаем источник данных ds:SetUpdateCallback(NewChartData) --обновление последних данных (NewChartData) local Size=ds:Size() if Size>0 then
if cBars>Size then cBars=Size-1 end
out_file:write("<DATE>,<TIME>,<OPEN>,<HIGH>,<LOW>,<CLOSE>,<VOL>\n") -- записываем название колонок
for i=Size-cBars, Size, 1 do local O=ds:O(i) local H=ds:H(i) local L=ds:L(i) local C=ds:C(i) local V=ds:V(i) local T=ds:T(i)
2. Если вручную переподключить соединение с интернетом, так же останавливается. После ручного запуска - работает до ручной остановки или переподключения интернета
Пользователь
Сообщений: Регистрация: 20.12.2020
28.04.2021 21:24:33
При потере связи скрипт ругается на строчку
Код
classcode=getSecurityInfo("",instrument).class_code --получаем класс бумаги (TQBR,SPBFUT,CETS,ect.) по ее тикеру
и вываливается с ошибкой
Код
C:\Scripts\Testers\1.lua:27: attempt to index a nil value
Я же спрашивал выдает ли скрипт какую ошибку... а говорите что молча останавливается
Тут решение сразу же напрашивается такое. Вынести расчет classcode (а так же out_file и ds) за пределы бесконечного цикла с проверкой наличия соединения isConnected(), и поместить в массив, а в цикле уже брать значения из массива. Нет никакого смысла каждый раз их заново находить, достаточно одного раза.
Пользователь
Сообщений: Регистрация: 20.12.2020
28.04.2021 21:33:09
Ну или можно обернуть в проверку соединения
Код
function main()
while is_run do
if(isConnected()==1)then
--- ТУТ ВАШ КОД --
end
sleep(3000)
end
end
но код вам явно причесать не помешало бы, слишком много ненужных повторов действий
Пользователь
Сообщений: Регистрация: 07.12.2020
28.04.2021 22:12:48
Цитата
BlaZed написал: Ну или можно обернуть в проверку соединения
Код
function main ()
while is_run do
if ( isConnected () = = 1 ) then
--- ТУТ ВАШ КОД --
end
sleep ( 3000 )
end
end
но код вам явно причесать не помешало бы, слишком много ненужных повторов действий
Благодарю за отклик и скорую помощь! Сделаю как вы советуете.
Пользователь
Сообщений: Регистрация: 07.12.2020
28.04.2021 22:38:52
Цитата
BlaZed написал: Ну или можно обернуть в проверку соединения
Эта конструкция не сработала. Попробую первый вариант, вынести 'classcode (а так же out_file и ds)' в OnInit()
Пользователь
Сообщений: Регистрация: 07.12.2020
28.04.2021 23:03:03
Я заметил, что classcode=getSecurityInfo("",instrument).class_code может быть nill даже когда связь установлена, вероятно не успевают загрузиться данные getSecurityInfo(). В init тоже не вариант.. Здесь бы очень подошло что-то вроде try-exeptions как в python, но я не знаю пока как это делать на lua
Пользователь
Сообщений: Регистрация: 07.12.2020
29.04.2021 07:26:59
Цитата
BlaZed написал: Ну или можно обернуть в проверку соединения
Забираю свои слова обратно, это работает. Хотя странно повело по началу, наверное мне показалось
Пользователь
Сообщений: Регистрация: 07.12.2020
29.04.2021 13:49:48
Все таки if (isConnected () == 1) then работает через раз, все-таки не показалось. Долго работало нормально, а сегодня после очередного дисконнекта скрипт снова отвалился, с той же ошибкой в 27 строке - nil . Сорри за столько сообщений, но я не нашел как редактировать или удалить написанные сообщения
Пользователь
Сообщений: Регистрация: 07.12.2020
29.04.2021 14:27:47
В общем, если у кого вдруг похожая проблема, решение банальное - проверкой на nil. Сейчас работает надежно, независимо от коннекта к серверу: while do ....if classcode~=nil then ........body
....end end Отдельное спасибо , за то, что натолкнул на мысли
Пользователь
Сообщений: Регистрация: 20.12.2020
29.04.2021 16:20:53
Цитата
Sergey написал: Сейчас работает надежно, независимо от коннекта к серверу:
Ну как вам сказать... скрипт ругался на невозможность получить getSecurityInfo("",instrument).class_code
Такая проверка не поможет, ибо classcode у вас глобальная и после первой же итерации всегда будет не nil если инструмент существует, и по такому условию просто каждую итерацию скрипт будет пропускать
написал: Сейчас работает надежно, независимо от коннекта к серверу:
Ну как вам сказать... скрипт ругался на невозможность получить getSecurityInfo("",instrument).class_code
Цитата
написал: if classcode~=nil then
Такая проверка не поможет, ибо classcode у вас глобальная и после первой же итерации всегда будет не nil если инструмент существует, и по такому условию просто каждую итерацию скрипт будет пропускать
classcode не глобальная - локальная в цикле for
Пользователь
Сообщений: Регистрация: 07.12.2020
29.04.2021 16:55:49
попробуйте сами: function main() ....while is_run do ....sleep(3000) ........for key, instrument in pairs(ticker_list) do ............classcode=getSecurityInfo("",instrument).class_code ............if classcode~=nil then ................тут без изменений
............end ........end ....end end
Пользователь
Сообщений: Регистрация: 20.12.2020
29.04.2021 18:03:41
Цитата
Sergey написал: classcode не глобальная - локальная в цикле for
Неа, она у вас именно глобальная. Обратитесь из любой другой функции к переменной classcode и удивитесь.
Тут дело в том, что ошибка плавающая, и будет появляться если удачно совпадет момент чтения данных из getSecurityInfo с моментом подключения к серверу, когда старые данные уже удалились, но еще не загрузились новые. При вашем sleep(3000) это может быть, ну скажем 1 раз из 10 раз, а поставьте sleep(100), так сразу увидите, что ошибка никуда не делась.
Тут дело в том, что ошибка плавающая, и будет появляться если удачно совпадет момент чтения данных из getSecurityInfo с моментом подключения к серверу, когда старые данные уже удалились, но еще не загрузились новые. При вашем sleep(3000) это может быть, ну скажем 1 раз из 10 раз, а поставьте sleep(100), так сразу увидите, что ошибка никуда не делась.
Похоже что вы правы, без sleep() вылетает сразу. Вариант вынести все в OnInit()? Но ведь там тоже нет гарантии что переменная classcode успеет записаться сразу после инициализации скрипта, даже при условии проверки соединения и не вылетит с ошибкой
Пользователь
Сообщений: Регистрация: 20.12.2020
29.04.2021 20:34:50
Цитата
Sergey написал: Вариант вынести все в OnInit()? Но ведь там тоже нет гарантии что переменная classcode успеет записаться сразу после инициализации скрипта, даже при условии проверки соединения и не вылетит с ошибкой
Именно вариант с OnInit() в данном случае самый надежный, надо всего лишь добавить парочку дополнительных проверок.
Смотрите
во первых, меняем ticker_list, делаем его двухуровневым массивом
во-вторых, переносим все одноразовые предварительные вычисления в OnInit(), данные скидываем в массив, сюда же добавляем дополнительные проверки
Код
function OnInit()
if(isConnected()==1)then
for key,value in pairs(ticker_list) do --в цикле перебираем бумаги из ticker_list
while(getSecurityInfo("",ticker_list[key][1])==nil)do sleep(100) end -- Ждем загрузки данных по инструменту
ticker_list[key][2]=getSecurityInfo("",ticker_list[key][1]).class_code --получаем класс бумаги (TQBR,SPBFUT,CETS,ect.) по ее тикеру
ticker_list[key][3]=CreateDataSource(ticker_list[key][2],ticker_list[key][1],iNterval) --создаем источник данных
end
end
end
в-третьих, убираем ненужные вычисления из main(), а данные берем из массива, который заполнили в OnInit()
Код
function main()
while is_run do
for key,value in pairs(ticker_list) do --в цикле перебираем бумаги из ticker_list
instrument=value[1]
classcode=value[2]
ds=value[3]
while(ds:Size()==0) do sleep(100) end -- Ждем загрузки данных графика
--ТУТ ВАШ КОД--
end
sleep(3000) -- приостановка на 3 секунды
end
end
Примерно так. Думаю должно работать без ошибок
Пользователь
Сообщений: Регистрация: 20.12.2020
29.04.2021 21:07:10
Ну и причесать код бы не помешало, а то смотреть больно вместо
ticker="FIVE" --код инструмента/бумаги classcode="TQBR" --код класса инструмента/бумаги, если нужен фондовый рынок - вводить TQBR вместо SPBFUT iNterval=INTERVAL_D1 --таймфрейм
и подставить все в:
ds=CreateDataSource(classcode, ticker, iNterval ) --создаем источник данных
в этом случае работает.
Похоже ошибка либо в getSecurityInfo(), либо в методе .class_code
Пользователь
Сообщений: Регистрация: 07.12.2020
07.05.2021 23:16:27
Проблема в .class_code. На этих инструментах он выдает "EQRP_INFO" а должен возвращать "TQBR"
Пользователь
Сообщений: Регистрация: 07.12.2020
08.05.2021 00:36:23
Вопрос по этому поводу задал здесь
Пользователь
Сообщений: Регистрация: 20.12.2020
08.05.2021 13:31:39
Цитата
Sergey написал: Проблема в .class_code. На этих инструментах он выдает "EQRP_INFO" а должен возвращать "TQBR"
Ну просто у вас существует два инструмента с одинаковым sec_code, но разными class_code А функция getSecurityInfo возвращает данные по первому из найденных под заданные параметры инструменту Надо для таких случаев явно указывать нужный class_code
Если использовали мой код, то вот небольшие изменения
Код
ticker_list = {{"SiM1"},{"SiU1"},{"FIVE","TQBR"},{"TCSG","TQBR"}}
function OnInit()
if(isConnected()==1)then
for key,value in pairs(ticker_list) do --в цикле перебираем бумаги из ticker_list
local n=10
while (getSecurityInfo((ticker_list[key][2] or ""),ticker_list[key][1])==nil)and(n>0) do sleep(1000) n=n-1 end -- Ждем загрузки данных по инструменту 10 секунд
if(n==0)then message("Инструмент "..ticker_list[key][1].." не найден") ticker_list[key]=nil break end
ticker_list[key][2]=getSecurityInfo((ticker_list[key][2] or ""),ticker_list[key][1]).class_code --получаем класс бумаги (TQBR,SPBFUT,CETS,ect.) по ее тикеру
ticker_list[key][3]=CreateDataSource(ticker_list[key][2],ticker_list[key][1],iNterval) --создаем источник данных
end
end
end
Пользователь
Сообщений: Регистрация: 20.12.2020
08.05.2021 13:37:47
Кстати, а в чем смысл для каждого инструмента искать class_code? По мне лучше указывать явно нужные sec_code и class_code, и понадежнее будет, да и код станет проще.
Пользователь
Сообщений: Регистрация: 07.12.2020
08.05.2021 13:48:15
Цитата
BlaZed написал: Кстати, а в чем смысл для каждого инструмента искать class_code? По мне лучше указывать явно нужные sec_code и class_code, и понадежнее будет, да и код станет проще.
Сейчас пока так и сделал, сделал с явным указанием кода. Но пригодится это когда инструментов много и с разных рынков. На основании некоторых предварительных критериев формируются динамические списки по ним и затем уже читаются lua скриптом. BlaZed спасибо за помощь!
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
08.05.2021 15:19:10
Цитата
BlaZed написал: Ждем загрузки данных по инструменту
Не нужно Нельзя в OnInit никаких ожиданий делать. Если данных нет, то они и не появятся пока из OnInit не выйдете.
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 20.12.2020
08.05.2021 16:11:30
Цитата
Старатель написал: Нельзя в OnInit никаких ожиданий делать. Если данных нет, то они и не появятся пока из OnInit не выйдете.
Вы правы, не подумал об этом. Да и основной поток ожиданиями напрягать тоже далеко не самая лучшая идея. Благодарю.
, код из OnInit лучше перенести в main перед вечным циклом