Skip to content

Add FastAPI service for cryptocurrency market data with technical indicators#1

Merged
Nfectious merged 4 commits intomainfrom
copilot/create-fastapi-crypto-service
Feb 7, 2026
Merged

Add FastAPI service for cryptocurrency market data with technical indicators#1
Nfectious merged 4 commits intomainfrom
copilot/create-fastapi-crypto-service

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 7, 2026

Production-ready FastAPI service that fetches OHLCV data from cryptocurrency exchanges (via ccxt) and calculates technical indicators (EMA 20/50/200, RSI-14, ATR-14). Proper handling of NaN/infinity values in pandas calculations ensures valid JSON serialization.

Architecture

Layered design with clean separation:

  • api/v1/routes_live_data.py - FastAPI endpoints with validation
  • services/ - Business logic (market data processing, indicator calculation)
  • integrations/exchanges.py - ccxt wrapper for testability
  • schemas/live_data.py - Pydantic models for request/response

Key implementation detail:

def clean_value(value: Any) -> Any:
    """Convert NaN and infinity to None for JSON serialization."""
    if pd.isna(value) or (isinstance(value, float) and not math.isfinite(value)):
        return None
    return value

API

GET /api/v1/live_data - Query parameters: symbol, timeframe, limit, exchange

Returns last 20 candles with indicators + latest indicator values. Response includes null for indicators where insufficient historical data exists (e.g., EMA-200 requires 200 candles).

Error handling maps ccxt exceptions:

  • NetworkError → 503
  • ExchangeError → 400
  • Generic exceptions → 500

Configuration

Environment-based via pydantic-settings. Default exchange: Binance spot market.

Development

  • Type safety: mypy strict mode with overrides for untyped third-party libs (ccxt, ta)
  • Linting: ruff with line-length=100, Python 3.11+
  • CI: GitHub Actions runs ruff, mypy, pytest
  • Docker: Multi-stage build with slim base image

Project Structure

src/app/
├── api/v1/routes_live_data.py
├── core/{config,logging}.py
├── integrations/exchanges.py
├── schemas/live_data.py
├── services/{market_data,indicators}.py
└── main.py

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.binance.com
    • Triggering command: /home/REDACTED/.local/bin/pytest pytest -v (dns block)
    • Triggering command: /usr/local/bin/uvicorn uvicorn app.main:app --host 0.0.0.0 --port 8000 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Objective

Create a professional, production-ready FastAPI service for fetching cryptocurrency OHLCV data and technical indicators using ccxt.

Requirements

Repository Structure

Create a src/-based package layout with the following structure:

src/
└─ app/
   ├─ __init__.py
   ├─ main.py
   ├─ api/
   │  ├─ __init__.py
   │  └─ v1/
   │     ├─ __init__.py
   │     └─ routes_live_data.py
   ├─ core/
   │  ├─ __init__.py
   │  ├─ config.py
   │  └─ logging.py
   ├─ integrations/
   │  ├─ __init__.py
   │  └─ exchanges.py
   ├─ schemas/
   │  ├─ __init__.py
   │  └─ live_data.py
   └─ services/
      ├─ __init__.py
      ├─ indicators.py
      └─ market_data.py

tests/
├─ __init__.py
├─ test_health.py
└─ test_live_data.py

API Implementation

Main Endpoint: GET /api/v1/live_data

Query parameters:

  • symbol (string, default: "BTC/USDT", min: 3, max: 30 chars)
  • timeframe (string, default: "1h", min: 1, max: 10 chars)
  • limit (integer, default: 250, range: 20-2000)
  • exchange (string, default from config, min: 2, max: 40 chars)

Response Model (LiveDataResponse):

{
  "symbol": str,
  "timeframe": str,
  "exchange": str,
  "last_price": float,
  "last_timestamp": datetime,
  "candles_count": int,
  "recent_candles": List[Candle],  # last 20 candles
  "latest_indicators": LatestIndicators,
  "meta": dict
}

Candle Model:

{
  "timestamp": datetime,
  "open": float,
  "high": float,
  "low": float,
  "close": float,
  "volume": float,
  "ema_20": Optional[float],
  "ema_50": Optional[float],
  "ema_200": Optional[float],
  "rsi_14": Optional[float],
  "atr_14": Optional[float]
}

LatestIndicators Model:

{
  "ema_20": Optional[float],
  "ema_50": Optional[float],
  "ema_200": Optional[float],
  "rsi_14": Optional[float],
  "atr_14": Optional[float]
}

Technical Indicators

Implement using the ta library:

  • EMA (Exponential Moving Average): 20, 50, 200 periods
  • RSI (Relative Strength Index): 14 period
  • ATR (Average True Range): 14 period

Important: Handle NaN values properly by converting them to None (null in JSON) instead of returning invalid JSON.

Configuration

Use pydantic-settings for environment-based configuration:

class Settings(BaseSettings):
    app_name: str = "Simple Crypto Data API"
    api_prefix: str = "/api/v1"
    default_exchange: str = "binance"
    default_market_type: str = "spot"
    enable_rate_limit: bool = True

Load from .env file (provide .env.example template).

Exchange Integration

  • Use ccxt library for exchange connectivity
  • Create an ExchangeClient wrapper class for testability
  • Support configurable exchange selection via query parameter
  • Handle exchange errors gracefully:
    • ccxt.NetworkError → 503 HTTP error
    • ccxt.ExchangeError → 400 HTTP error
    • General exceptions → 500 HTTP error

Error Handling

  • Validate all inputs using FastAPI Query validators
  • Raise HTTPException with appropriate status codes
  • Return user-friendly error messages

Development Tools

pyproject.toml should include:

Dependencies:

  • fastapi>=0.110
  • uvicorn[standard]>=0.27
  • pydantic>=2.6
  • pydantic-settings>=2.2
  • ccxt>=4.2
  • pandas>=2.1
  • ta>=0.11.0

Dev dependencies:

  • pytest>=8.0
  • httpx>=0.26
  • ruff>=0.3
  • mypy>=1.8
  • types-requests

Tool configuration:

  • Ruff: line-length=100, Python 3.11+, select E/F/I/B/UP/N/S rules, ignore S101
  • Mypy: strict mode, Python 3.11
  • Pytest: testpaths=["tests"]

Docker Support

Dockerfile:

  • Base: python:3.11-slim
  • Set PYTHONDONTWRITEBYTECODE=1 and PYTHONUNBUFFERED=1
  • Install package in editable mode with dev dependencies
  • Expose port 8000
  • CMD: uvicorn app.main:app --host 0.0.0.0 --port 8000

docker-compose.yml:

  • Single service "api"
  • Map port 8000:8000
  • Pass environment variables for configuration

CI/CD

GitHub Actions workflow (.github/workflows/ci.yml):

  • Trigger on push and pull_request
  • Python 3.11
  • Steps:
    1. Install dependencies
    2. Run ruff linting
    3. Run mypy type checking
    4. Run pytest tests

Tests

test_health.py:

  • Test GET / health endpoint
  • Verify 200 status and "running" in message

test_live_data.py:

  • Smoke test for GET /api/v1/live_data
  • Validate response structure when network call succeeds
  • Note: This is a network test; recommend adding mocked tests for CI reliability

Documentation

README.md should include:

  • Project description
  • Quickstart instructions (local + Docker)
  • API endpoint examples
  • Notes about indicator null values

Additional Files

  • .gitignore: Ignore .venv/, pycache, .pytest_cache, .mypy_cache, .ruff_cache, dist/, build/, .env
  • .env.example: Template with all configuration variables

Implementation Notes

  1. Layered architecture: routes → services → integrations → schemas
  2. Type safety: Use type hints throughout, enforce with mypy strict mode
  3. **NaN handling:...

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits February 7, 2026 15:02
Co-authored-by: Nfectious <19631929+Nfectious@users.noreply.github.com>
Co-authored-by: Nfectious <19631929+Nfectious@users.noreply.github.com>
Co-authored-by: Nfectious <19631929+Nfectious@users.noreply.github.com>
Copilot AI changed the title [WIP] Create FastAPI service for cryptocurrency OHLCV data Add FastAPI service for cryptocurrency market data with technical indicators Feb 7, 2026
Copilot AI requested a review from Nfectious February 7, 2026 15:11
@Nfectious
Copy link
Copy Markdown
Owner

Initial Upload

@Nfectious Nfectious marked this pull request as ready for review February 7, 2026 17:12
@Nfectious Nfectious merged commit 1ceaea5 into main Feb 7, 2026
1 check failed
@Nfectious Nfectious deleted the copilot/create-fastapi-crypto-service branch February 7, 2026 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants