A production-ready REST API for accessing OHLCV (Open, High, Low, Close, Volume) data from ClickHouse with ISO 8601 time format support
- π Secure: SQL injection protected with parameterized queries
- β‘ Fast: Optimized queries with async support and connection pooling
- π Paginated: Support for large datasets with built-in pagination
- β Validated: Automatic request validation using Pydantic
- π Documented: Auto-generated OpenAPI (Swagger) documentation
- π³ Docker Ready: Includes Docker and docker-compose setup
- π₯ Health Checks: Built-in health check endpoints for monitoring
- π ISO 8601: Modern time format with timezone support
- β±οΈ Backward Compatible: Legacy format still supported
The API now supports the international standard ISO 8601 time format with full timezone support:
- β
UTC Format:
2025-07-01T00:00:00Z - β
Timezone Offsets:
2025-07-01T00:00:00+03:00 - β
Milliseconds:
2025-07-01T00:00:00.000Z - β
Basic Format:
2025-07-01T00:00:00
Legacy format (YYYYMMDD-HHmm) is still supported for backward compatibility but deprecated.
# Clone the repository
git clone <your-repo-url>
cd clickhouse-ohlcv-api
# Start services
docker-compose up -d
# API will be available at http://localhost:8000
# ClickHouse will be available at http://localhost:8123Visit http://localhost:8000/docs for interactive API documentation.
# 1. Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# 2. Install dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt # For development
# 3. Install package in editable mode
pip install -e .
# 4. Configure environment
cp .env.example .env
# Edit .env with your ClickHouse connection details
# 5. Run the application
uvicorn app.main:app --reload
# 6. Visit http://localhost:8000/docsGET /health- Comprehensive health check with database statusGET /health/ready- Readiness check for orchestration systemsGET /health/live- Simple liveness probe
Health Check Response Example:
{
"success": true,
"status": "healthy",
"timestamp": "2025-11-29T09:38:47.442042",
"database": {
"connected": true,
"ping_ms": 1.45
},
"version": "1.0.0",
"query_time_ms": 1.47
}-
GET /api/v1/ohlcv- Get OHLCV data for a symbol- Query Parameters:
symbol(required): Trading symbol (e.g., BINANCE:BTCUSDT.P)start(required): Start time in ISO 8601 format (e.g.,2025-07-01T00:00:00Z)end(optional): End time in ISO 8601 format (defaults to now)limit(optional): Max records (default: 1000, max: 10000)offset(optional): Skip records (default: 0)
- Query Parameters:
-
GET /api/v1/ohlcv/latest- Get the latest candle for a symbol- Query Parameters:
symbol(required): Trading symbol
- Query Parameters:
# Get OHLCV data for Bitcoin (ISO 8601)
curl "http://localhost:8000/api/v1/ohlcv?symbol=BINANCE:BTCUSDT.P&start=2025-07-01T00:00:00Z&end=2025-08-01T00:00:00Z&limit=100"
# With timezone offset
curl "http://localhost:8000/api/v1/ohlcv?symbol=BINANCE:BTCUSDT.P&start=2025-07-01T00:00:00%2B03:00&end=2025-08-01T00:00:00%2B03:00"
# Get latest candle
curl "http://localhost:8000/api/v1/ohlcv/latest?symbol=BINANCE:BTCUSDT.P"
# Health check
curl "http://localhost:8000/health"# Legacy format still works for backward compatibility
curl "http://localhost:8000/api/v1/ohlcv?symbol=BINANCE:BTCUSDT.P&start=20250701-0000&end=20250801-0000"import requests
# Using ISO 8601 format
response = requests.get(
"http://localhost:8000/api/v1/ohlcv",
params={
"symbol": "BINANCE:BTCUSDT.P",
"start": "2025-07-01T00:00:00Z",
"end": "2025-08-01T00:00:00Z",
"limit": 1000
}
)
data = response.json()
print(f"Retrieved {data['metadata']['total_records']} records")
for candle in data['data']:
print(f"{candle['candle_time']}: ${candle['close']:,.2f}"){
"success": true,
"data": [
{
"candle_time": "2025-07-01T00:00:00",
"symbol": "BINANCE:BTCUSDT.P",
"open": 50000.0,
"high": 51000.0,
"low": 49500.0,
"close": 50500.0,
"volume": 1234567.89
}
],
"metadata": {
"total_records": 1,
"limit": 1000,
"offset": 0,
"has_more": false,
"query_time_ms": 45.2,
"timestamp": "2025-11-13T10:30:45.123Z"
}
}The API supports ISO 8601 format (recommended) with backward compatibility:
ISO 8601 Formats (Recommended):
2025-07-01T00:00:00- Basic format2025-07-01T00:00:00Z- UTC (recommended)2025-07-01T00:00:00+03:00- With timezone offset2025-07-01T00:00:00.000Z- With milliseconds
Legacy Format (Deprecated):
20250701-0000- Old format (still works but deprecated)
All timestamps in responses use ISO 8601 format:
{
"candle_time": "2025-07-01T15:30:00",
"timestamp": "2025-11-13T10:30:45.123Z"
}Configuration is managed through environment variables. See .env.example for all available options.
# ClickHouse Connection
CLICKHOUSE_HOST=localhost
CLICKHOUSE_PORT=9000
CLICKHOUSE_DATABASE=default
CLICKHOUSE_TABLE=ohlcv_data
# API Settings
MAX_LIMIT=10000
DEFAULT_LIMIT=1000clickhouse-ohlcv-api/
βββ app/
β βββ core/ # Core functionality
β β βββ database.py # ClickHouse connection
β β βββ exceptions.py # Custom exceptions
β β βββ logging_config.py # Logging setup
β βββ models/ # Pydantic models
β β βββ request.py # Request validation
β β βββ response.py # Response models
β βββ routers/ # API endpoints
β β βββ health.py # Health checks
β β βββ ohlcv.py # OHLCV endpoints
β βββ utils/ # Utility functions
β β βββ time_parser.py # Time parsing (ISO 8601)
β βββ config.py # Configuration
β βββ main.py # Application entry
βββ tests/ # Test suite
β βββ conftest.py # Pytest fixtures
β βββ test_time_parser.py # Time parser tests
β βββ test_models.py # Model tests
β βββ test_ohlcv_api.py # API tests
βββ docs/ # Documentation
β βββ API.md # API reference
β βββ EXAMPLES.md # Usage examples
βββ pyproject.toml # Project metadata (PEP 621)
βββ pytest.ini # Pytest configuration
βββ requirements.txt # Production dependencies
βββ requirements-dev.txt # Development dependencies
βββ README.md # This file
The project includes comprehensive test coverage:
# Run all tests
pytest
# Run with coverage
pytest --cov=app --cov-report=html
# Run specific test file
pytest tests/test_time_parser.py -v
# Run specific test
pytest tests/test_time_parser.py::TestParseTimeParam::test_iso8601_basic -v- β 50+ time parser tests (ISO 8601 + legacy)
- β 30+ model validation tests
- β 40+ API endpoint tests
- β 120+ total test cases
- β 95%+ code coverage
Important: This API is designed to work with an existing ClickHouse database. You need:
- ClickHouse server (installed locally, remote server, or cloud service)
- Database created
- OHLCV table with the schema below
The API expects a ClickHouse table with the following structure:
CREATE TABLE ohlcv_data (
candle_time DateTime64(3),
symbol String,
open Float64,
high Float64,
low Float64,
close Float64,
volume Float64
) ENGINE = MergeTree()
ORDER BY (symbol, candle_time);-
Install ClickHouse (if not already installed):
- Official Documentation
- Or use Docker:
docker run -d -p 8123:8123 clickhouse/clickhouse-server
-
Create Database and Table:
# Connect to ClickHouse clickhouse-client # Create database (if needed) CREATE DATABASE IF NOT EXISTS default; # Create table (run the SQL above)
-
Configure API: Update
.envwith your ClickHouse connection details
See scripts/init-db.sql for the complete schema and sample data.
# Clone repository
git clone <your-repo-url>
cd clickhouse-ohlcv-api
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt
# Install in editable mode
pip install -e .
# Run tests
pytestDevelopment tools for maintaining code quality (optional for contributors):
# Format code
black . # Auto-formats Python code
isort . # Sorts imports
# Lint
flake8 app tests # Checks code style
# Type checking
mypy app # Validates type hints
# Run all checks
black . && isort . && flake8 app tests && mypy app && pytestWhat these tools do:
- black: Automatically formats code to consistent style
- isort: Organizes import statements
- flake8: Finds code style issues and potential bugs
- mypy: Checks type annotations for correctness
Note: These are development tools for contributors. End users don't need them.
- API Reference: docs/API.md
- Usage Examples: docs/EXAMPLES.md
- Interactive Docs: http://localhost:8000/docs (Swagger UI)
- Alternative Docs: http://localhost:8000/redoc (ReDoc)
If you're currently using the legacy format, here's how to migrate:
Before (Legacy):
params = {
"start": "20250701-0000",
"end": "20250801-0000"
}After (ISO 8601):
params = {
"start": "2025-07-01T00:00:00Z",
"end": "2025-08-01T00:00:00Z"
}Benefits:
- β International standard
- β Timezone support
- β Better readability
- β Millisecond precision
See docs/EXAMPLES.md for detailed migration examples.
This API requires a ClickHouse database (local or remote) with the OHLCV table schema.
Note: ClickHouse can be:
- Running on the same server
- Running on a separate server
- A managed service (cloud provider)
Use docker-compose to start both API and ClickHouse:
# Start all services (API + ClickHouse)
docker-compose up -d
# API will be available at http://localhost:8000
# ClickHouse will be available at http://localhost:8123
# View logs
docker-compose logs -f api
# Stop services
docker-compose downIf you have ClickHouse running elsewhere, run only the API container:
# Build image
docker build -t clickhouse-ohlcv-api .
# Run API container connecting to external ClickHouse
docker run -d -p 8000:8000 \
-e CLICKHOUSE_HOST=your-clickhouse-server.com \
-e CLICKHOUSE_PORT=8123 \
-e CLICKHOUSE_USER=default \
-e CLICKHOUSE_PASSWORD=your-password \
-e CLICKHOUSE_DATABASE=default \
-e CLICKHOUSE_TABLE=ohlcv_data \
clickhouse-ohlcv-api
# Or using environment file
docker run -d -p 8000:8000 --env-file .env clickhouse-ohlcv-apiModify docker-compose.yml to remove the ClickHouse service and update environment variables:
services:
api:
build: .
ports:
- "8000:8000"
environment:
- CLICKHOUSE_HOST=external-clickhouse.example.com
- CLICKHOUSE_PORT=8123
# ... other variablesThen run:
docker-compose up -dContributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
pytest - Format code:
black . && isort . - Submit a pull request
MIT License - see LICENSE file for details.
- Built with FastAPI
- Database: ClickHouse
- Validation: Pydantic
- Testing: Pytest
Made with β€οΈ for the data community
For questions or issues, please open an issue on GitHub.