DRRK/app/jobs/update_market.py

100 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Обновление котировок MOEX и курса CNY за дату — для запуска по расписанию.
python -m app.jobs.update_market # предыдущий рабочий день
python -m app.jobs.update_market --date 2026-10-08
Работает от пользователя `system`. Код выхода: 0 — без ошибок (отсутствие
торгов ошибкой не считается), 1 — были ошибки по бумагам/курсу или сбой,
2 — неверные аргументы.
"""
from __future__ import annotations
import argparse
import logging
from collections.abc import Sequence
from datetime import date
from app.core.logging import setup_logging
from app.db.base import run_db
from app.db.types import SYSTEM_USER
from app.services import fx_rates, market_data
from app.services.dates import previous_business_day
logger = logging.getLogger("app.jobs.update_market")
def _parse_date(value: str) -> date:
try:
return date.fromisoformat(value)
except ValueError as exc:
raise argparse.ArgumentTypeError(
f"дата должна быть в формате ГГГГ-ММ-ДД, получено «{value}»"
) from exc
def _update_quotes(on_date: date) -> bool:
try:
result = run_db(market_data.update(on_date, SYSTEM_USER))
except Exception: # noqa: BLE001
logger.exception("Котировки: сбой обновления")
return False
for message in result.messages:
logger.info("Котировки: %s", message)
logger.log(
logging.INFO if result.ok else logging.ERROR,
"Котировки на %s: обновлено %d, без торгов %d, ошибок %d",
on_date.isoformat(),
result.updated,
result.no_trades,
result.errors,
)
return result.ok
def _update_fx(on_date: date) -> bool:
try:
result = run_db(fx_rates.update(on_date, SYSTEM_USER))
except Exception: # noqa: BLE001
logger.exception("Курс CNY: сбой обновления")
return False
for message in result.messages:
logger.log(
logging.INFO if result.ok else logging.ERROR, "Курс CNY: %s", message
)
return result.ok
def main(argv: Sequence[str] | None = None) -> int:
parser = argparse.ArgumentParser(
prog="python -m app.jobs.update_market",
description="Обновить котировки MOEX и курс CNY за дату.",
)
parser.add_argument(
"--date",
type=_parse_date,
default=None,
help="Дата ГГГГ-ММ-ДД (по умолчанию — предыдущий рабочий день)",
)
args = parser.parse_args(argv)
setup_logging()
on_date = args.date or previous_business_day()
logger.info("Старт обновления рыночных данных на %s", on_date.isoformat())
# Курс обновляем, даже если котировки упали, — источники независимы.
quotes_ok = _update_quotes(on_date)
fx_ok = _update_fx(on_date)
ok = quotes_ok and fx_ok
logger.log(
logging.INFO if ok else logging.ERROR,
"Готово: %s",
"без ошибок" if ok else "есть ошибки",
)
return 0 if ok else 1
if __name__ == "__main__":
raise SystemExit(main())