Владимир написал: BlaZed, Ну и замечательно! Квик загружает исторические данные, скрипт их читает, если хочет по прерыванию - заказывает коллбек на событие "пришла новая свеча". В любом случае, данные с сервера получает Квик,а не юзер - в том виде, в каком удобнее именно ему.
Так и есть, только одно замечание, колбек не на событие "пришла новая свеча", а на событие "поступили новые данные" в источник.
Цитата
Владимир написал: График-то построить можно, но это РАЗНЫЕ процессы - зачем же их смешивать? Мне вот графики нафиг не нужны, а свечи на что-то и пригодились бы.
Опять согласен с вами по сути данные функции и есть работа со свечами. Хотя назвали их "работа с графиками", но вот не пофиг ли.
Цитата
Владимир написал: Да, конечно, можно и сразу получить часы - я имел в виду, что даже для минутных свечей при нынешних каналах связи объёмы никакие. И потом: откуда Квику знать, что нужно Вам? Он вполне может отдавать Вам то, что нужно Вам, а получать от сервера то, что нужно ему. Может, ему выгоднее получить один массив на все таймфреймы и формировать данные для юзера "на лету"? А нам какое дело, как именно он готовит для нас данные? Это проблемы Квика, а не наши.
Тут я думаю логика в том, что проще один раз посчитать свечи на сервере и отдать пользователю сразу, то что он запросил, чем на каждой рабочей станции, будут производиться такие вычисления. Да и объемах данных разных таймфреймов различаются во много раз (например минутные от дневных в 60*24=1440 минус нерабочее время), и если учесть, что пользователей на сервере брокера могут быть многие тысячи, то все же это экономия трафика, а следовательно и скорость реакции увеличиться. Но это всего лишь мои предположения.
Цитата
Владимир написал: Кстати, и на низколиквидных инструментах свечи могут идти обычным порядком - мои так и считаются: вот включил я комп в 7 часов, так у меня все рублёвые и евровые активы и большинство долларовых не торгуются, а свечки тикают - просто у них цена не меняется. Я именно по ним и определяю, торгуется данный инструмент в данный момент или нет.
Значит для ваших задач такое решение подходит, но может не подходить другим. Свечи в классическом понимании по сделкам формируются, и кому-то это может быть важным для стратегии.
Цитата
Владимир написал: Так ведь актуальные данные это ТОЖЕ исторические данные! Прилетать новые свечки могут, изменяться - нет.
Тут есть маленький ньюанс, актуальные данные станут историческими только после закрытия свечи. А последняя свеча всегда меняется, если еще не закрыта и прилетает сделка.
Владимир написал: Во-первых, почему CreateDataSource? Ведь алгоритмически задача проста до безобразия: получить с сервера некий массив данных, причём исторических данных! Что здесь вообще можно "Create"?
Тут немного сложнее реализовано, CreateDataSource создает источник данных (обычно обзываемый в примерах ds) в который сначала загружаются исторические данные, после чего постоянно добавляются актуальные (если запросить обновления через SetEmptyCallback, хотя по наблюдениям они прилетают даже без этого запроса)
Цитата
Владимир написал: Во-вторых, какого хрена она в разделе "Функции для работы с графиками"? При чём тут вообще графики? У меня никаких графиков нет, не было и не будет, а со свечами я активно работаю.
А что это еще как ни данные для построения свеч из которых можно строить график?
Цитата
Владимир написал: В-третьих, данные нужно получать фактически по одному интервалу (минутному), поскольку все остальные интервалы (даже полюбившиеся кому-то нестандартные) при необходимости прекрасно считаются из него прямо на клиенте (тики здесь явно инородное тело и должны быть выброшены нафиг).
Конечно можно, вот только зачем например мне получать минуты и высчитывать часы, если я могу сразу получить часы, а минуты меня не интересуют? Я могу и сам все высчитать, только зачем это делать, если мне дают сразу то, что мне надо.
Цитата
Владимир написал: В-четвёртых, объём этих данных для одного тикера даже при круглосуточной работе: 60 минут * 24 часа * 30 дней * 12 месяцев * sizeof одной свечи = курам на смех даже за год, при этом более-менее востребованным является интервал размером в сутки, а время можно даже не указывать: порядковый номер свечи в массиве однозначно его идентифицирует.
А как быть на низколиквидных инструментах, когда, ну скажем сутки, не было сделок? Слетит весь порядок же. Да тоже чисто для удобства, чтобы не делать лишних вычислений.
Цитата
Владимир написал: В-пятых, какого хрена здесь делает SetUpdateCallback?! Какая может быть "обработка изменившихся свечек"?! Повторяю: это ИСТОРИЧЕСКИЕ данные! Всё, поезд ушёл, ничего уже не меняется!
Потому что созданный источник данных это НЕ исторические данные, в него прилетают и актуальные данные. Вот коллбек на них и срабатывает.
Цитата
Владимир написал: Какой-то тихий ужас, господа! Неужели вся эта кухня вообще хоть как-то работает?
В таблицах после обновления не видны первые буквы тикеров в первой колонке, как исправить и есть ли формат таблиц?, В таблицах после обновления не видны первые буквы тикеров в первой колонке, как исправить и есть ли формат таблиц?
Проблема то известная, сходу находятся такие же темы https://forum.quik.ru/forum8/topic6475/ https://forum.quik.ru/forum1/topic6410/ Вроде как в версии quik 8.13.0 таблицы могут съехать, а в 8.13.1 уже исправили Если проблема в таблице текущих торгов, то "редактировать таблицу" -> "транспонировать" должно помочь Так же можно сбросить ширину столбцов, нажав ctrl+w на таблице
Ну или пересоздать таблицу
И не помешает обновиться на версию 8.13.1 чтобы проблема не повторилась
Сирануш написал: торгую роботами, некоторые активы выходят, некоторые стоят на очереди, все это рутинная работа которую хотелось бы автоматизировать.
Активы стоят на очереди, входят и выходят, замечательно выходят )) Очень похоже что вы фьючами торгуете и просто желаете автоматизировать определение актуального фьючерса.
Если я прав, то алгоритм следующий. Через getClassSecurities получаем список инструментов, выдергиваем из него инструменты с нужным префиксом, для каждого из них вытаскиваем параметр количество дней до экспирации (DAYS_TO_MAT_DATE) и определяем у кого данный параметр минимален (либо в заданном диапазоне), с тем и работаем.
Делал я такое, там кода даже 10 строчек не наберется, насколько помню
Цитата
Сирануш написал: Для этого я и хочу сверять "Текущие торги"( формируемы мною портель) с "Состояние счета"( что имею в наличие), вот основная затея.
А это совершенно лишнее, если я, конечно, угадал с вашей задачей.
Евгений написал: Предлагаю удалить данный функционал о предложениях с этого форума, так как он не имеет никакого смысла. И не морочить голову регистрацией предложений и признанием их потенциально полезными.
Да ладно с плеча то рубить. Система предложений работает, просто нам не известно подробностей и повлиять на нее мы не можем. Поэтому и создается впечатление о бессмысленности.
Вот если бы видеть список зарегистрированный предложений и возможность как-то влиять на их приоритет, разработчикам было бы действительно понятно что надо пользователям. Эх, мечты-мечты... Но как я понимаю разработчики против такой открытости.
Andrey Bezrukov написал: Регистрация пожеланий и их количество (по какому-либо определённому функционалу) позволяет оценить востребованность этого функционала, это влияет на принятие решения о реализации и выделения на это соответствующих ресурсов.
Вы по количеству пожеланий оцениваете востребованность? Это одновременно и логично и не логично.
Поясню. Увидел я например в какой либо тебе пожелание нужное мне, вы отписались что зарегистрировали его и сочли целесоообразным. Я это вижу и успокоился, мол приняли в разработку и все хорошо.
А получается, что мне и всем кому надо данный функционал требуется отписываться в теме что мол "надо, надо"?? Иначе вы его 10 лет делать будете.
Так мы все темы с пожеланиями заспамим подтверждениями востребованности.
Прошу зарегистрировать мое пожелание, которое почему-то оставили без внимания.
Цитата
BlaZed написал: Да с этим окном еще и не работают горячие клавиши Alt+L - "Закрепить окно" и Alt+B - "Убрать заголовок". Вот со всеми остальными окнами горячие клавиши работает, а с этим нет. Тоже бы исправить.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Владимир написал: Насколько я понял, BlaZed, говорил про подачу заявки по рыночной цене. Меня это не устраивает - хрен знает, что там с рынком может произойти, так что я предпочитаю совершать сделки именно по той цене, которая указана. Или, по крайней мере, не худшей, так что заявки у меня всегда лимитированные.
У меня алгоритм такой, что я всегда либо в продаже либо в покупке сижу, потому мне важнее не конкретная цена сделки, а сам факт войти в шорт либо лонг при определенных условиях рынка.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Владимир написал: BlaZed, Именно! А от "дрочилова" у меня такое средство: если заявка по данному тикеру подана, выставляется тайм-аут в 5 минут (или 4, не помню), и пока он не истечёт, никаких новых заявок. При этом гарантированно все прерывания по сделкам (они же приходят пачками) уже пройдут. А каждое такое прерывание (если заявка в несколько лотов, и не все они реализуются за одну сделку) продлевает этот тайм-аут: время начинает отсчитываться уже с неё. Правда, эта скотина оказалась изобретательная: она честно выдерживает эти 5 минут, после чего снимает несработавшую заявку (или её остаток), и в ту же секунду выставляет новую - эту подлянку я до конца ещё не поборол. ::
Предположу, когда таймаут заявки вышел, алгоритм должен снять заявку и обнулить сигнал, после чего заново оценить рынок, чтобы дать или не дать новый сигнал на покупку/продажу. Если сигнал по какой-либо причине не обнуляется, то как раз вышеописанное поведение и будет наблюдаться.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Владимир,Эх помню как тоже сначала пытался ловить тики, чтобы не прозевать самую лучшую цену, вместо одной заявки скрипт только и делал, что ставил, снимал заявки пока не поймает цену, дрочилово то еще было. Потом как вы начал выставлять заявки по ценам спроса/предложения, но после нескольких раз "гонок" с рынком, эту идею тоже отбросил. Сейчас при наличии сигнала просто бью по рынку, всего одна заявка которая тут же превращается в сделку, и наступило счастье..
Кстати, а в чем смысл для каждого инструмента искать class_code? По мне лучше указывать явно нужные sec_code и class_code, и понадежнее будет, да и код станет проще.
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
swerg написал: Считаю это ошибкой, которую разработчики QUIK должны исправить. Интерфейс у терминала русский, по умолчанию для русских букв штатные upper / lower должны корректно работать.
интерфейс у терминала не только русский, увы...
И все же это ошибка
Запускать на только что запущенном квике, пока никакой скрипт локаль не установил еще
function upper(s)
local str=""
for i=1,string.len(s) do
local byte=string.byte(s,i)
local char=string.char(byte)
if(byte>= 97)and(byte<=122)then char=string.char(byte-32) end -- Латинские буквы
if(byte>=224)and(byte<=255)then char=string.char(byte-32) end -- Русские буквы
if(byte==184) then char=string.char(byte-16) end -- Русская ё
str=str..char
end
return str
end
Евгений написал: Возможность запуска скриптов по заранее определенному списку. Например в скрипт добавляется список скриптов, и после запуска этого скрипта он запускает скрипты из списка
А зачем это может понадобиться? Если надо запустить несколько скриптов одновременно, то выделяем в доступных скриптах нужные скрипты (мышкой с зажатой клавишей Shift либо Ctrl, это стандатрные возможности винды) и запускаем.
Артем написал: BlaZed, при умном заказе без этой функции получение новых данных определенно не работает, только из открытого графика.
Проверил только что - работает даже при умном заказе при закрытом графике, потому и вопрос задал. Просто возникло ощущение, что SetEmptyCallback() стала не нужна.
Итак. Вводные данные. Выбираем инструмент который до этого не использовали, ну я выбрал "EuM1" График инструмента не открываем, в заказе котировок указано "по выбранным классам" и данный инструмент не выбран, в папке archive файла с таким инструментам тоже нет. Другими словами, QUIK пока еще никогда не получал данный инструмент.
Пишу простенький скриптик
Код
is_run=true
function main()
ds=CreateDataSource("SPBFUT","EuM1",INTERVAL_M5)
-- ds:SetEmptyCallback()
while(ds:Size()==0) do sleep(100) end
while is_run do
message("C="..ds:C(ds:Size()))
sleep(1000)
end
end
function OnStop()
is_run=false
return 100
end
...и он работает, данные обновляются. Но почему данные обновляются? Я же закомментил ds:SetEmptyCallback()
Всегда думал, что SetEmptyCallback() нужна для того чтобы поток данных обновлялся, но оказывается что нет.
Прошу знающих объяснить, зачем все таки нужна функция SetEmptyCallback()?
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
Тут дело в том, что ошибка плавающая, и будет появляться если удачно совпадет момент чтения данных из getSecurityInfo с моментом подключения к серверу, когда старые данные уже удалились, но еще не загрузились новые. При вашем sleep(3000) это может быть, ну скажем 1 раз из 10 раз, а поставьте sleep(100), так сразу увидите, что ошибка никуда не делась.
Такая проверка не поможет, ибо classcode у вас глобальная и после первой же итерации всегда будет не nil если инструмент существует, и по такому условию просто каждую итерацию скрипт будет пропускать
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(), и поместить в массив, а в цикле уже брать значения из массива. Нет никакого смысла каждый раз их заново находить, достаточно одного раза.
Скрипт не должен завершаться при разрыве соединения, если, конечно, это специально не реализовано.
Поэтому возникают следующие вопросы: 1) Скрипт молча останавливается или ошибку какую выдает? 2) Если вручную переподключиться, скрипт остановится? 3) Если ли в скрипте колбеки onConnected, onDisconnected, onCleanUp? Если есть, то что в них? 4) Используется ли проверка подключеия isConnected? Если используется, то как именно?
В идеале показали бы скрипт, предварительно удалив из него то, что считаете ком.тайной.
Идентификатор транзакции это параметр в диапазоне от 1 до 2147483647 Причем серверу QUIK даже не нужна уникализация данного параметра, сервер будет обрабатывать заявки даже если задать
Код
trans_id=1
хотя делать так, конечно же, не надо.
Уникализация trans_id нужна самому пользователю чтобы отслеживать через колбеки состояние своих заявок. Тут на форуме много споров было, как лучше это делать.
Kolossi написал: Я чего-то недопонимаю в логике настроек переноса заказа данных в настройки (?). Стоял фильтр заказа котировок. Снимаю галочку "фильтр инструмента" класса в /Программа/Получение данных/Котировки и уверен что все хорошо. Однако при следующем входе галка на месте. Ручное сохранение настроек эффекта не дает. Версия 8.11
Был косяк в версии 8.11.0.66, в 8.12 был исправлен Так что либо обновиться, либо (если не желаете обновляться) перед закрытием программы, отключитесь и подключитесь к серверу заново, тогда настройки котировок сохранятся.
Александр написал: Спасибо большое!! по правде хром и опера не разрешают больше работать с FTP буду искать как это устратить! Еще раз спасибо, не думал что они это отключили возможность.
В Chrome включается так Открывайте адрес chrome://flags/ Там включайте пункт "Enable support for FTP URLs"
Folsan написал: Здравствуйте! У меня не обновляется Quik. Пробовал запускать от имени администратора. Пробовал проверить наличие обновлений вручную. Ничего не помогает. Версия, стоящяя на компьютере: 8.11.0.66
Автоматически квик обновляется с серверов брокера, а брокер выкладывает обновление когда посчитает нужным. Скорее всего брокер еще не выложил новую версию для обновления.
Но всегда можно обновиться вручную. 1) Выходи из квика 2) Скопируй куда-нибудь ВСЮ папку с установлнным квиком (на случай если что-нибудь пойдет не так, вернешь ее на место и будет как раньше) 3) Качай архив с последней обновой с сервера квикаftp://ftp.quik.ru/public/updates/8.13/quik_8.13.1_upd.zip 4) Распакуй архив в папку с квиком с заменой файлов 5) Готово
Evgeniy написал: Хотелось бы узнать почему так? Может что-то не так делаю.Подскажите пожалуйста. Заранее благодарен :)
Ну разорвать соединение и снова подключиться вы же наверняка делали?
А так ошибка у вас только одна. Вопрос надо не на форуме квика задавать, а просто позвонить брокеру.
Пока брокер вам доступ к срочному рыноку не даст, в квике он не появится. Когда доступ будет, то в разделах котиировки (то что на скрине) вы увидите разделы FORTS
Владимир написал: Да не забивайте Вы Квик всяким дерьмом - и так уже не продохнуть от дурацких "сервисов"!
Храните У СЕБЯ данные и обращайтесь к ним сколько душе угодно! САМИ "дергайте данные из файлов в папке Arhive"! Храните там ЛЮБЫЕ исторические данные по любому инструменту за любой период (в Интете этих данных просто ДО МАМЫ!), тестируйте там свои стратегии хоть до посинения - какое дело до этого разработчикам (и пользователям) Квика? НА КОЙ нам "такой функционал: в панель выбора инструмента добавить еще один раздел "Архив", в котором и появлялись бы те инструменты, срок обращения которых истек, но данные по которым для терминала доступны ? Мало глюков в софте, добавить надобно? И РАЗДЕЛИТЕ, блин, процессы доступа к данным и всю остальную херню вроде "склейки графиков!"!
Если вам кроме ТТТ от квика ничего не надо, то не надо думать что остальным этого достаточно.
Данное пожелание было реализовано как функционал склейки графиков при замене инструмента.
Сделайте лучше, чтобы к данным которые имеются у пользователя в архиве можно было бы обратиться. Ну вот лежит у меня в папке archive файлик SPBFUT_SiH1_60.dat в нем как я понимаю часовые свечки по SiH1 Реализуйте возможность обратиться к ним из скрипта через CreateDataSource
Вероятно, что CreateDataSource и так дергает данные из файлов в папке Arhive. Вот сейчас если я пытаюсь обратиться ds,error_desc=CreateDataSource("SPBFUT","SiH1",INTERVAL_H1) мне возвращается в ds=nil, а в error_desc="SiH1 - unknown sec code."
Но данные то имеются, так дайте возможность к ним обратиться и использовать. Это очень бы помогло для тестирования стратегий на исторических данных.
Как вариант решения вижу добавление в функцию CreateDataSource параметра отменяющего проверку на актуальность инструмента.
Ну восьмерка, конечно, не без косяков, но то что вы говорите, это явно не в квике, а у вас проблемы с настройками. Все летает на железе достаточно среднего уровня, QUIK 8.13.0.106
Почитайте про настройку и оптимизацию рабочего места QUIK, тут на форуме есть темы про это.
Да с этим окном еще и не работают горячие клавиши Alt+L - "Закрепить окно" и Alt+B - "Убрать заголовок". Вот со всеми остальными окнами горячие клавиши работает, а с этим нет. Тоже бы исправить.
Добрый день, Заметил, что для всех индикаторов которые я пишу, при добавлении индикатора на график приходится снимать галочку "Поместить график в новую область", а в настройках индикатора выставлять галку "Показывать последнее значение"
Можно ли как-то из кода индикатора ставить и снимать эти галочки?
Какой язык подойдет для написания торгового алгоритма?, Только изучаю данную тему и хотелось бы получить совет куда двигаться, и что осваивать .Относительно описанной в теме стратегии.
Любой алгоритм, это все лишь математика, так что практически любой язык справится. В QUIK встроенный язык LUA, так что не нем и пишем.
Объемы дергать можно из стакана, из графика, из таблицы обезличенных сделок. Значения индикаторов, вроде как не вытащить, только рассчитывать в скрипте.
Как интегрировать с MT5 и главное зачем ума не приложу.
swerg написал: Ровно это и приходит. Или требуются новые значения параметров?
Так хотелось бы чтоб в колбеке не надо было дергать нужные параметры через GetParamEx и сравнивать с предыдущими чтобы понять изменилось ли значение. Гораздо удобнее чтоб было как в первом сообщении Артем описал
Только думаю лучше не OnParam переделывать, а добавить новый коллбек
Знаю, сталкивался с этим. В переменной PRCStr у тебя строка типа "12345.0" А в транзакцию цену надо передавать строку с учетом шага цены "12345"
Короче, точку с нулем из строки похерь и будет счастье
Код
function cut_zero(str)
local num=tonumber(str)
local zero=string.byte("0",1)
local point=string.byte(".",1)
if(string.find(num,'%.')) then -- Имеется точка в числе
for n=string.len(num),1,-1 do -- Перебор справа налево
if(string.byte(num,n)==point) then return string.sub(num,1,n-1) end
if(string.byte(num,n)~=zero) then return string.sub(num,1,n) end
end
end
return num
end
Roman Azarov написал: В коллбек OnParam приходит набор измененных параметров, а не какой-то один конкретный параметр.
Сейчас OnParam просто сообщает что изменились параметры по инструменту и не более того. А пожелание как раз в том и было, чтобы в коллбек приходили измененные параметры.