В Узбекистане доллар — это не просто иностранная валюта, а часть повседневной реальности.

Аренда квартиры всегда считается в долларах. На базаре цены на мясо и технику продавцы указывают в долларах, особенно в периоды нестабильности курса сума.

Базар Чорсу
Базар Чорсу

Для многих семей вопрос «по какому курсу сегодня менять» — это не абстрактная финансовая теория, а вполне бытовая необходимость: от оплаты жилья и машины до того, чтобы не потерять на обмене несколько сотен тысяч сумов.

И вот сидишь ты, молодая мама, с ребёнком на руках: одной рукой качаешь коляску, другой — листаешь сайты банков и Республиканскую валютную биржу, пытаясь поймать выгодный момент. Обновляешь страницы по десять раз в день, нервничаешь из-за разницы в 50–100 сумов на долларе — а это реальные деньги на памперсы или молочку.

В какой-то момент я просто устала от этого хаоса и подумала: так жить нельзя. Надо автоматизировать.

Как меняется курс доллара каждый рабочий день

Если сильно упростить, весь процесс выглядит примерно так (в рабочие дни, без праздников):

  1. Утро (~08:00–10:00) Начинаются торги на УзРВБ (Узбекская республиканская валютная биржа). Банки и крупные компании покупают/продают доллары в режиме реального времени. Курс формируется рыночно — по принципу спроса и предложения. Появляется «курс открытия» и дальше он колеблется в течение сессии.

  2. В течение дня (торги до ~15:00–16:00) Происходят все сделки. В конце дня биржа рассчитывает средневзвешенный курс по всем заключённым сделкам с долларом (USD/UZS).

  3. Вечер (обычно ~16:00–17:00)Центральный банк публикует официальный курс на следующий рабочий день. Он берётся именно как средневзвешенный курс предыдущих торгов на УзРВБ. Этот курс — официальный ориентир: для бухгалтерии, налогов, таможни, статистики и т.д. Сам ЦБ по нему не продаёт валюту населению.

  4. Коммерческие банки и обменники Смотрят на вчерашний официальный курс ЦБ (как минимальную базу) и на текущие рыночные реалии. Выставляют свои курсы покупки и продажи. Разница (спред) — их заработок. В течение дня банки могут менять курсы несколько раз: если на бирже доллар укрепился/ослаб, если конкуренты поменяли, если большой клиент пришёл — курс корректируется. Иногда изменения бывают по 3–5 раз за день, особенно в волатильные периоды.

Итог для обычного человека:

  • Хочешь поймать самый выгодный курс на сегодня — мониторь именно курсы банков в реальном времени, а не только официальный ЦБ.

  • Официальный курс ЦБ — это «вчерашний» средний по бирже, он обновляется раз в день.

  • Реальные деньги на обмене — в спреде банков и их оперативных изменениях.

Поэтому и нужен бот: чтобы не сидеть вручную и не пропустить момент, когда кто-то из банков вдруг поднял курс покупки на 50–100 сумов выше остальных.

Идея бота: уведомления, когда курс реально изменился

Всё это привело к простой, но очень нужной мне мысли: хочу получать уведомления в Telegram только тогда, когда курс в обменниках банков действительно поменялся — причём не официальный курс ЦБ (он обновляется раз в день в 16:00), а именно реальные курсы покупки/продажи в пунктах обмена конкретных банков.

Поэтому бот должен:

  1. Периодически (например, каждые 10–30 минут в рабочие часы) парсить страницы с курсами валют у популярных банков (NBU, Kapitalbank, Anorbank, Hamkorbank, Octobank, Ipak Yuli, Universal bank и ещё несколько, где курсы часто бывают самыми выгодными).

  2. Сравнивать новые значения с предыдущими (хранить в базе).

  3. Если курс покупки или продажи по доллару (а можно и по евро/рублю) изменился хотя бы на 10–20 сумов — присылать мне уведомление

Оповещение о смене курса валют

Техническая реализация: C# и микросервисы с самого начала

Когда пришло время переходить от идей к коду, выбор стека был очевиден и однозначен: C# на .NET 8. Других вариантов я даже не рассматривала — это мой основной рабочий инструмент, в нём я чувствую себя как рыба в воде. Опыт с .NET позволил сразу сосредоточиться на логике проекта, а не на изучении нового языка или фреймворка.

Микросервисная архитектура тоже была запланирована с первого дня — не как модный хайп, а потому что она идеально ложилась на задачи проекта:

  • чёткое разделение ответственности (парсинг, бизнес-логика уведомлений, доставка в Telegram),

  • независимая разработка и отладка каждого компонента,

  • удобство масштабирования в будущем (если вдруг добавятся новые банки, валюты или пользователи),

  • простота тестирования и мониторинга отдельных частей.

    В итоге получилось три микросервиса:

    1. Parser Service Работает по расписанию (BackgroundService + Timer), парсит сайты банков с помощью AngleSharp, сравнивает новые курсы с предыдущими (хранятся в PostgreSQL), и при любом изменении отправляет событие «CurrencyRateUpdated» в Kafka.

    2. Notification Logic Service Консьюмер Kafka-топика с обновлениями. Проверяет подписки пользователей (таблица subscriptions: user_id, bank_id, currency, min_change_threshold), формирует персонализированные сообщения и кидает их в следующий топик — «UserNotifications».

    3. Telegram Delivery Service Финальный консьюмер: берёт готовые сообщения, находит chat_id пользователя и отправляет их через Telegram.Bot библиотеку. Есть retry, rate-limiting и базовое форматирование (эмодзи, bold, inline-кнопки).

      Кода немного — весь проект уложился примерно в 1500–2000 строк (без ��онфигов и тестов). Любой разработчик на .NET мог бы собрать подобное за неделю плотной работы.

      Но я писала его по ночам, в декрете, выкраивая по 30–90 минут, когда ребёнок спал. Поэтому вместо недели проект растянулся на три месяца. Зато за это время я:

      пережила несколько «переездов» структуры страниц у банков,

      добавила надёжную обработку ошибок и логи,

      настроила Kafka + Victorya Logs для логов,

      протестировала всё на реальных скачках курсов.

В итоге получился крепкий, масштабируемый и очень удобный для меня инструмент — именно такой, каким я его и задумывала с самого начала.

Заключение

Телеграм бот уже спас мне кучу нервов и времени: теперь я не сижу сутками с обновлением страниц банков, а получаю точное уведомление именно тогда, когда курс в обменнике реально изменился и стоит бежать менять.

Если вы тоже в Узбекистане, тоже следите за курсами и тоже устали от ручного мониторинга — буду очень рада, если мой опыт и код кому-то пригодятся.

Огромное спасибо всем, кто дочитал до конца! ❤️ Особенно благодарна буду за ваши отзывы, предложения и критику — пишите в комментариях, что можно улучшить, какие банки добавить, какие фичи были бы полезны (например, алерты на определённый порог, топ-курсы в одном сообщении и т.д.).

Спасибо, что вы есть, хабровчане!💙