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

Материал из Поле цифровой дидактики
м Patarakin переименовал страницу Проект Леонтьев R в Изучение изменения стоимости валют по данным ЦБ без оставления перенаправления: Название с ошибкой
мНет описания правки
 
(не показана 1 промежуточная версия этого же участника)
Строка 1: Строка 1:
== Описание проекта ==
== Описание проекта ==
'''Анализ валютного рынка ЦБ РФ на основе R. Построение дашборда: дневные изменения, 30-дневная динамика и волатильность валют.'''
== Назначение ==
Проект позволяет оценить характер изменения стоимости валют по данным ЦБ.
Проект позволяет оценить характер изменения стоимости валют по данным ЦБ.
__NOTOC__
== Общая концепция ==
<uml>
@startuml
title Уровни анализа валютного дашборда
rectangle "Источник данных (CBR API)" as data
rectangle "Сбор данных (httr + JSON)" as collect
rectangle "Обработка (R data.frame)" as process
rectangle "Метрики (изменения, волатильность)" as metrics
rectangle "Визуализация (ggplot2 + patchwork)" as viz
rectangle "Интерпретация (аналитика)" as interp
data --> collect
collect --> process
process --> metrics
metrics --> viz
viz --> interp
@enduml
</uml>
= Валютный дашборд ЦБ РФ (R + анализ) =
== Цель исследования ==
Проект направлен на анализ валютного рынка:
* дневные изменения валют
* динамика за 30 дней
* волатильность валют
* сравнение мировых и остальных валют
== Источник данных ==
Данные берутся из API ЦБ РФ:
<code>https://www.cbr-xml-daily.ru/daily_json.js</code>
Исторические данные:
<code>https://www.cbr-xml-daily.ru/archive/YYYY/MM/DD/daily_json.js</code>
== Архитектура обработки данных ==
<uml>
@startuml
title Поток обработки данных
rectangle "CBR API" as api
rectangle "HTTP GET" as http
rectangle "JSON parsing" as json
rectangle "data.frame" as df
rectangle "Feature engineering" as feat
rectangle "Visualization" as plot
api --> http
http --> json
json --> df
df --> feat
feat --> plot
@enduml
</uml>
== 📊 Структура данных ==
<uml>
@startuml
title Структура валютных данных
rectangle "Date" as date
rectangle "Currency Code" as code
rectangle "Value" as value
rectangle "Previous Value" as prev
rectangle "Change %" as change
date --> value
code --> value
prev --> change
value --> change
@enduml
</uml>
== Загрузка и подготовка данных ==
<syntaxhighlight lang="r">
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),
  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), ]
</syntaxhighlight>
== Сегментация валют ==
Мировые валюты:
<syntaxhighlight lang="r">
popular <- c("USD","EUR","GBP","JPY","CNY",
            "CHF","CAD","AUD","NZD","SEK")
</syntaxhighlight>
== Логика анализа ==
<uml>
@startuml
title Логика обработки валют
rectangle "Все валюты" as all
rectangle "Мировые валюты" as world
rectangle "Рост" as up
rectangle "Падение" as down
all --> world
all --> up
all --> down
@enduml
</uml>
== Дневной анализ ==
<syntaxhighlight lang="r">
title Группы валют
rectangle "Мировые" as world
rectangle "Рост" as up
rectangle "Падение" as down
world --> "Сравнительный анализ"
up --> "Топ роста"
down --> "Топ падения"
</syntaxhighlight>
== 30-дневная динамика ==
Алгоритм:
# загрузка архивных данных ЦБ
# формирование временного ряда
# расчёт накопленного изменения
<syntaxhighlight lang="r">
change_30d_pct = (Value / first(Value) - 1) * 100
</syntaxhighlight>
== Волатильность ==
Формула:
<math>
Volatility = sd(\log(Value)) \times 100
</math>
== Визуализация системы ==
<uml>
@startuml
title Схема дашборда
rectangle "Дневной график" as main
rectangle "30-дневная динамика" as growth
rectangle "Волатильность" as vol
rectangle "Итоговый дашборд" as dashboard
main --> dashboard
growth --> dashboard
vol --> dashboard
@enduml
</uml>
=== Основной график ===
* дневные изменения валют
* цветовая группировка: рост / падение / мировые
=== Волатильность ===
* TOP-10 наиболее нестабильных валют
== Итоговый дашборд ==
<syntaxhighlight lang="r">
final_plot <- (plot_main | plot_vol) /
              (plot_growth | plot_month)
ggsave("currency_dashboard_full.png",
      final_plot,
      width = 14,
      height = 10)
</syntaxhighlight>
== Вывод ==
Проект демонстрирует:
* работу с внешними API
* обработку временных рядов
* построение аналитических дашбордов в R
* визуальную аналитику финансовых данных




== Код на R ==
<syntaxhighlight lang="r">
<syntaxhighlight lang="r">
library(httr)
library(httr)
Строка 231: Строка 449:


[[Категория:BigDataWorks]]
[[Категория:BigDataWorks]]
[[Категория: RRecipe]]

Текущая версия от 11:24, 14 апреля 2026

Описание проекта

Анализ валютного рынка ЦБ РФ на основе R. Построение дашборда: дневные изменения, 30-дневная динамика и волатильность валют.

Назначение

Проект позволяет оценить характер изменения стоимости валют по данным ЦБ.


Общая концепция

Валютный дашборд ЦБ РФ (R + анализ)

Цель исследования

Проект направлен на анализ валютного рынка:

  • дневные изменения валют
  • динамика за 30 дней
  • волатильность валют
  • сравнение мировых и остальных валют

Источник данных

Данные берутся из API ЦБ РФ:

https://www.cbr-xml-daily.ru/daily_json.js

Исторические данные:

https://www.cbr-xml-daily.ru/archive/YYYY/MM/DD/daily_json.js

Архитектура обработки данных

📊 Структура данных

Загрузка и подготовка данных

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),
  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")

Логика анализа

Дневной анализ

title Группы валют

rectangle "Мировые" as world
rectangle "Рост" as up
rectangle "Падение" as down

world --> "Сравнительный анализ"
up --> "Топ роста"
down --> "Топ падения"

30-дневная динамика

Алгоритм:

  1. загрузка архивных данных ЦБ
  2. формирование временного ряда
  3. расчёт накопленного изменения
change_30d_pct = (Value / first(Value) - 1) * 100

Волатильность

Формула:

[math]\displaystyle{ Volatility = sd(\log(Value)) \times 100 }[/math]

Визуализация системы

Основной график

  • дневные изменения валют
  • цветовая группировка: рост / падение / мировые

Волатильность

  • TOP-10 наиболее нестабильных валют

Итоговый дашборд

final_plot <- (plot_main | plot_vol) /
              (plot_growth | plot_month)

ggsave("currency_dashboard_full.png",
       final_plot,
       width = 14,
       height = 10)

Вывод

Проект демонстрирует:

  • работу с внешними API
  • обработку временных рядов
  • построение аналитических дашбордов в R
  • визуальную аналитику финансовых данных


Код на R

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), ]  # удаляем ненайденное

df_month <- df_month %>%
  group_by(CharCode) %>%
  arrange(date) %>%
  mutate(
    change_30d_pct = (Value / first(Value) - 1) * 100
  ) %>%
  ungroup()

plot_growth <- ggplot(df_month, aes(
  x = date,
  y = change_30d_pct,
  color = CharCode
)) +
  geom_line(linewidth = 1) +
  theme_minimal() +
  labs(
    title = "Накопленное изменение валют за 30 дней (%)",
    x = "Дата",
    y = "% изменения",
    color = "Валюта"
  )

get_all_currencies <- 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"))
    val <- data$Valute

    data.frame(
      date = as.Date(date),
      CharCode = names(val),
      Value = sapply(val, function(x) x$Value)
    )
  }, error = function(e) NULL)
}

list_all <- lapply(dates, get_all_currencies)
list_all <- Filter(Negate(is.null), list_all)

df_all <- do.call(rbind, list_all)
df_all <- df_all[complete.cases(df_all), ]

volatility <- df_all %>%
  group_by(CharCode) %>%
  summarise(
    mean_value = mean(Value, na.rm = TRUE),
    sd_value = sd(Value, na.rm = TRUE),
    volatility = sd(log(Value), na.rm = TRUE) * 100
  ) %>%
  arrange(desc(volatility)) %>%
  slice_head(n = 10)

plot_vol <- ggplot(volatility, aes(
  x = reorder(CharCode, volatility),
  y = volatility,
  fill = CharCode
)) +
  geom_col(width = 0.7) +
  
  geom_text(
    aes(label = round(volatility, 2)),
    hjust = -0.2,
    size = 3.5
  ) +
  
  coord_flip() +

scale_y_continuous(expand = expansion(mult = c(0, 0.25))) +
  
  theme_minimal() +
  theme(
    legend.position = "none"
  ) +
  
  labs(
    title = "ТОП-10 самых волатильных валют (30 дней)",
    x = "Валюта",
    y = "Волатильность (%)"
  )


# График за месяц
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_vol) /
              (plot_growth| plot_month)

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

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

Результаты