Система ежедневного инкрементального обновления предназначена для поддержания актуальности сырых данных валютных пар, необходимых для расчёта абсолютных курсов в проекте AbsCur3. Система работает полностью автоматически, выполняясь каждый день в заданное время.
Ключевой принцип: AbsCur3 — проект об абсолютных валютных курсах, а не публичный архив сырых парных котировок. Сырые данные являются промежуточным продуктом для внутренних расчётов.
Режим: Продакшен (все 287 пар)
Расписание: Ежедневно в 05:00 UTC (08:00 МСК)
Статус: ✅ Рабочий (с 02.02.2026)
Последний запуск: [см. статус-бейдж выше]
graph TD
A[GitHub Actions Scheduler<br/>05:00 UTC] --> B[Запуск daily_update.yml]
B --> C[Выполнение incremental_updater.py]
C --> D{Для каждой из 287 пар}
D --> E[Определение горизонта обновления<br/>last_date - 5 дней]
E --> F[Формирование батчей по 7 пар]
F --> G[Запрос к Twelve Data API]
G --> H[Объединение данных с дедупликацией]
H --> I[Сохранение в CSV]
I --> J[Пауза до следующей минуты]
J --> K{Обработаны все пары?}
K -->|Нет| F
K -->|Да| L[Формирование отчёта]
L --> M[Автоматический коммит изменений]
M --> N[Завершение workflow]
style A fill:#e1f5fe
style C fill:#f3e5f5
style G fill:#e8f5e8
style M fill:#e1f7d5
incremental_updater.pyОсновной скрипт, выполняющий инкрементальное обновление данных. Наследует код из historical_loader.py и добавляет логику ежедневного обновления.
Текущий режим: Продакшен (все 287 пар).
Автоматизированный пайплайн, расположен в .github/workflows/daily_update.yml.
Конфигурация:
cron: '0 5 * * *' (ежедневно в 05:00 UTC)workflow_dispatch)contents: write для автоматического коммитаupdate_state.jsonJSON-файл в data/metadata/, отслеживающий статус последнего запуска. Содержит:
Для каждой валютной пары система определяет период для загрузки:
# Псевдокод логики определения дат
last_local_date = читаем_последнюю_дату_из_CSV()
start_date = last_local_date - timedelta(days=5) # Перекрытие 5 дней
end_date = min(вчерашний_день, последняя_доступная_дата_API)
if start_date >= end_date:
пропускаем_пару() # Нет новых данных
else:
загружаем_данные(start_date, end_date)
Для соблюдения лимита API (8 запросов в минуту) используется стратегия батчей:
gantt
title Распределение запросов для 287 пар (41 батч)
dateFormat HH:mm
axisFormat %H:%M
section Батч 1-40
Запросы к API (7 пар) : 00:00, 40m
Пауза до след. минуты : после каждого батча
section Батч 41
Запросы к API (7 пар) : 00:40, 1m
section Итоги
Обработка данных : 00:41, 6m
Коммит и завершение : 00:47, 5m
Расчёт времени: 287 пар ÷ 7 пар/мин = 41 батч
Итоговое время: 41 минута + 6 минут на обработку = 47 минут (реально 41 минута)
Новые данные объединяются с существующими по следующим правилам:
config/currencies.py (список 287 валютных пар)data/raw/twelve_data/pairs/data/metadata/data/raw/twelve_data/pairs/scripts/daily_update/logs/update_state.json в data/metadata/# Активируйте виртуальное окружение
# (предполагается, что вы находитесь в корне проекта)
source .venv/bin/activate # Linux/Mac
# или
.venv\Scripts\activate # Windows
# Установите зависимости
pip install -r requirements.txt
Убедитесь, что файл .env в корне проекта содержит ключ API:
TWELVE_DATA_API_KEY=your_api_key_here
Для локального тестирования можно ограничить количество пар:
# Временное изменение в incremental_updater.py
# В функции load_currency_config() заменить:
# return all_symbols # На продакшене
# на:
return all_symbols[:10] # Для теста только 10 пар
Запуск скрипта:
# Из корня проекта (обязательно!)
python scripts/daily_update/incremental_updater.py
Продакшен workflow находится в .github/workflows/daily_update.yml:
name: Daily Data Update
on:
schedule:
- cron: '0 5 * * *' # Ежедневно в 05:00 UTC (08:00 МСК)
workflow_dispatch: # Оставляем ручной запуск
jobs:
update-raw-pairs:
runs-on: ubuntu-latest
timeout-minutes: 55 # Для 287 пар
permissions:
contents: write # Для автоматического коммита
steps:
# ... стандартные шаги
В настройках GitHub репозитория должен быть установлен секрет:
TWELVE_DATA_API_KEY - ключ API от Twelve Datadata/metadata/update_state.jsonupdate_state.json (пример после автоматического запуска):{
"timestamp": "2026-02-02T06:48:06.817000",
"total_pairs": 287,
"total_api_requests": 287,
"yesterday_date": "2026-02-01",
"statistics": {
"updated": 287,
"already_current": 0,
"no_new_data": 0,
"failed": 0,
"total_new_rows": 287
}
}
| Проблема | Симптомы | Решение |
|---|---|---|
| Превышение времени | Workflow прерывается через 55 минут | Убедитесь, что батчи обрабатываются за 1 минуту каждый |
| Ошибки API ключа | API ключ не найден в логах |
Проверьте секрет TWELVE_DATA_API_KEY в настройках репозитория |
| Ошибки доступа | Permission denied при коммите |
Проверьте permissions: contents: write в workflow |
| Пустые данные | Для некоторых пар нет новых данных | Проверьте доступность пар в API Twelve Data |
| Дубликаты данных | Повторяющиеся даты в CSV | Функция save_to_csv автоматически удаляет дубликаты |
last_date - 5 дней → yesterdayupdate_state.jsonСистема разработана с учётом устойчивости к ошибкам:
| Тип ошибки | Действие системы | Логирование |
|---|---|---|
| Сетевая ошибка | 3 попытки повтора с экспоненциальной задержкой | ERROR с деталями ошибки |
| Ошибка API (429) | Пауза 60 секунд, повтор попытки | WARNING с информацией о лимите |
| Ошибка отдельной пары | Пропуск пары, продолжение обработки остальных | ERROR для конкретной пары |
| Превышение времени | GitHub Actions прерывает выполнение через 55 минут | Workflow помечается как failed |
| Отсутствие локальных данных | Пара пропускается (требуется первоначальная загрузка) | WARNING с указанием пары |
Продакшен режим (287 пар):
Мониторинг времени:
update_state.json после активацииfailed и no_new_data парcurrencies.pydata/raw/twelve_data/pairs/Текущий статус: ✅ Продакшен (287 пар, ежедневное расписание)
Дата последнего обновления: 2026-02-02
Версия: 1.0.0