Розробка REST API для історичних ринкових даних
REST API для історичних даних — це інтерфейс між сховищем часових рядів та споживачами: торговельними ботами, аналітичними системами, платформами бектестингу. Якість API визначається швидкістю відповіді, гнучкістю фільтрування та надійністю під навантаженням.
Дизайн ендпоїнтів
Базовий набір ендпоїнтів для маркет-даних:
GET /v1/ohlcv/{exchange}/{symbol}
?from=2024-01-01T00:00:00Z
&to=2024-01-31T23:59:59Z
&interval=1h
&limit=1000
GET /v1/trades/{exchange}/{symbol}
?from=1704067200000
&to=1704153600000
&limit=10000
GET /v1/orderbook/{exchange}/{symbol}/snapshot
?timestamp=1704067200000
&depth=20
GET /v1/tickers/{exchange}/{symbol}/history
?from=2024-01-01
&to=2024-01-02
&fields=close,volume
Використовуйте ISO 8601 для користувацького інтерфейсу та Unix timestamp (мілісекунди) для програмного доступу. Підтримка обох форматів через автоматичне виявлення.
Параметри та валідація
from fastapi import FastAPI, Query
from datetime import datetime
from typing import Optional
@app.get("/v1/ohlcv/{exchange}/{symbol}")
async def get_ohlcv(
exchange: str,
symbol: str,
interval: str = Query("1h", regex="^(1m|5m|15m|1h|4h|1d|1w)$"),
from_time: datetime = Query(..., alias="from"),
to_time: datetime = Query(..., alias="to"),
limit: int = Query(1000, ge=1, le=50000),
):
if (to_time - from_time).days > 365:
raise HTTPException(400, "Date range cannot exceed 365 days")
data = await candle_service.get_candles(
exchange, symbol, interval, from_time, to_time, limit
)
return {"data": data, "count": len(data)}
Пагінація для великих датасетів
Cursor-based пагінація ефективніша за offset для часових рядів:
{
"data": [...],
"cursor": {
"next": "eyJ0aW1lc3RhbXAiOiAxNzA0MDY3MjAwMDAwfQ==",
"has_more": true
}
}
Cursor — base64-encoded JSON з останнім timestamp на поточній сторінці. При наступному запиті клієнт надсилає ?cursor=... замість ?from=....
Кешування
Історичні дані незмінні — ідеальний кандидат для агресивного кешування:
-
HTTP Cache-Control:
public, max-age=3600для даних старше одного дня - Redis Cache: для часто запитуваних діапазонів (популярні символи, останні 30 днів)
- Query Cache у TimescaleDB / ClickHouse для важких агрегацій
Стратегія: якщо запитаний діапазон повністю в минулому (закритий) — кешуємо на 24 години. Якщо включає поточний момент — кешуємо на 60 секунд.
Rate Limiting та аутентифікація
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
@app.get("/v1/ohlcv/{exchange}/{symbol}")
@limiter.limit("100/minute")
async def get_ohlcv(...):
...
Для комерційного API — тарифні плани через API-ключі з різними лімітами: free (10 req/min, 30 днів історії), paid (1000 req/min, повна історія).
Документація через OpenAPI
FastAPI автоматично генерує OpenAPI схему. Крім того — приклади запитів/відповідей у документації, опис форматів, коди помилок. Swagger UI та ReDoc з коробки — клієнти можуть тестувати API безпосередньо в браузері без додаткових інструментів.







