Изучение изменения стоимости валют по данным ЦБ

Материал из Поле цифровой дидактики
Версия от 01:59, 14 апреля 2026; Vladislav Leontev (обсуждение | вклад) (Дополнено)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
library(httr)
library(jsonlite)
library(ggplot2)
library(patchwork)

options(encoding = "UTF-8")

url <- "https://www.cbr-xml-daily.ru/daily_json.js"
data <- fromJSON(content(GET(url), "text"))

valutes <- data$Valute  # Извлекаем список валют из полученного объекта

df <- data.frame(  # Создаём таблицу
  CharCode = sapply(valutes, function(x) x$CharCode),  # Код валюты (USD, EUR и т.д.)
  Value    = as.numeric(sapply(valutes, function(x) x$Value)),  # Текущий курс валюты
  Previous = as.numeric(sapply(valutes, function(x) x$Previous))  # Предыдущий курс валюты
)

df <- df[complete.cases(df), ]  # Удаляем строки с пропущенными значениями

df$change_pct <- (df$Value - df$Previous) / df$Previous * 100  # Считаем процентное изменение курса валют
df <- df[is.finite(df$change_pct), ]  # Удаляем бесконечные значения

popular <- c("USD","EUR","GBP","JPY","CNY", # Список основных валют для отдельного анализа
             "CHF","CAD","AUD","NZD","SEK")

df_world <- df[df$CharCode %in% popular, ]  # Фильтруем только мировые валюты
df_world$group <- "Мировые"  # Добавляем метку группы

df_top <- df[!df$CharCode %in% popular, ] # Оставляем все валюты не из списка

df_up <- df_top[df_top$change_pct > 0, ]  # Фильтруем валюты, которые выросли
df_up <- df_up[order(df_up$change_pct, decreasing = TRUE), ] # Сортируем по убыванию роста
df_up <- head(df_up, 10) # Берём топ-10 валют роста
df_up$group <- "Рост"

df_down <- df_top[df_top$change_pct < 0, ]  # Фильтруем валюты, которые упали
df_down <- df_down[order(df_down$change_pct), ]  # Сортируем по сильнейшему падению
df_down <- head(df_down, 10)  # Берём топ-10 падений
df_down$group <- "Падение"

df_final <- rbind(df_world, df_up, df_down)  # Объединяем мировые + рост + падение в одну таблицу

# График за день
plot_main <- ggplot(df_final, aes(
  x = reorder(CharCode, change_pct),  # Сортируем валюты по изменению
  y = change_pct,  # Значение по оси Y (% изменения)
  fill = group  # Цвет по группе
)) +

  geom_col() +  # Столбчатый график

  geom_text(  # Подписи значений на столбцах
    aes(label = paste0(round(change_pct, 2), "%")),
    vjust = -0.5,
    size = 3
  ) +

  scale_fill_manual(values = c(  # Цвета для групп
    "Мировые" = "gray60",
    "Рост" = "green3",
    "Падение" = "red3"
  )) +

  theme_minimal() +

  labs(    # Подписи графика
    title = "Валютный рынок ЦБ РФ",
    x = "Валюта",
    y = "Изменение (%)",
    fill = "Группа"
  ) +

  expand_limits(y = max(df_final$change_pct) * 1.2)  # Запас по оси Y, чтобы подписи не обрезались


currencies <- c("USD", "EUR", "CNY", "JPY", "GBP")  # Список валют для анализа месяца
dates <- seq(Sys.Date() - 30, Sys.Date(), by = "day")  # Создаём список дат за последние 30 дней

get_day_data <- function(date) {  # Функция загрузки данных за конкретный день
  url <- paste0(
    "https://www.cbr-xml-daily.ru/archive/",
    format(date, "%Y/%m/%d"),
    "/daily_json.js"
  )

  tryCatch({
    data <- fromJSON(content(GET(url), "text")) # Загружаем данные дня

    data.frame(  # Создаём таблицу по выбранным валютам
      date = as.Date(date),
      CharCode = currencies,
      Value = sapply(currencies, function(x) data$Valute[[x]]$Value)  # Берём значение каждой валюты
    )
  }, error = function(e) NULL)  # Если ошибка
}

list_data <- lapply(dates, get_day_data)  # Получаем данные за все дни
list_data <- Filter(Negate(is.null), list_data)  # Удаляем пустые результаты

df_month <- do.call(rbind, list_data)  # объединяем в один график
df_month <- df_month[complete.cases(df_month), ]  # удаляем ненайденное

# График за месяц
plot_month <- ggplot(df_month, aes(
  x = date,  # Ось X — дата
  y = Value,    # Ось Y — курс валюты
  color = CharCode,  # Цвет линий по валюте
  group = CharCode  # Группировка линий
)) +

  geom_line(linewidth = 1) + # Линия графика
  geom_point(size = 1.5) + # Точки на линии

  theme_minimal() +

  labs(  # Подписи
    title = "Динамика валют за 30 дней",
    x = "Дата",
    y = "Курс к RUB",
    color = "Валюта"
  )

# Объединение графиков
final_plot <- plot_main / plot_month

print(final_plot)  # Вывод на экран

ggsave("currency_dashboard_full.png",  # Сохранение в PNG файл
       final_plot,
       width = 14,
       height = 10)