Архитектура бэкенда
Поток данных
Dukascopy CDN (.bi5, LZMA, один файл = 1 час тиков)
↓ prefetch.py
data/dukascopy/{symbol}/{year}/{mm}/{dd_hh}.bi5 ← локальный кэш raw-файлов
↓ lzma.decompress + struct.unpack → DataFrame тиков
↓ resample("1min").agg(ohlcv)
data/M1/{symbol}.parquet
↓ _load_m1() → in-memory cache (mtime-aware)
↓ df.loc[from:to] + resample(TF)
GET /api/candles → JSON
Почему только M1 хранится на диске
Хранить заранее нарезанные H1, H4 и т.д. не нужно: ресэмплинг из M1 дешевле, чем управлять несколькими файлами. Запрос 1 дня H1 из M1-кэша занимает ~2–5 мс.
Валидация параметров
Instrument и Timeframe — Python StrEnum. FastAPI автоматически отклоняет невалидные значения с 422, без ручных проверок в роутерах.