Skip to content

Add professional FastAPI crypto data service with OHLCV + indicators#5

Merged
Nfectious merged 4 commits intomainfrom
copilot/add-fastapi-live-data-again
Feb 21, 2026
Merged

Add professional FastAPI crypto data service with OHLCV + indicators#5
Nfectious merged 4 commits intomainfrom
copilot/add-fastapi-live-data-again

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 19, 2026

Implements a production-ready FastAPI service for fetching cryptocurrency OHLCV data with technical indicators (EMA 20/50/200, RSI 14, ATR 14) from multiple exchanges via ccxt.

Core Implementation

API Endpoints

  • REST: GET /api/v1/live_data - Fetch OHLCV with indicators, returns last 20 candles
  • WebSocket: WS /api/v1/live_data/ws - Stream updates at configurable intervals (5-300s)
  • Query params validated via Pydantic: symbol, timeframe, limit (20-2000), exchange

Data Pipeline

  • Exchange client wraps ccxt with rate limiting and market type configuration
  • Indicators calculated using ta library on pandas DataFrame
  • NaN/infinite values converted to None for JSON serialization
  • Metadata includes exchange defaultType when available

Error Handling

  • Network errors → 503
  • Exchange errors → 400
  • Generic errors → 500
  • WebSocket implements circuit breaker (max 5 consecutive errors)

Testing Strategy

Mocked tests use pytest monkeypatch to stub exchange.fetch_ohlcv, ensuring deterministic CI:

class MockExchange:
    def __init__(self, config: dict[str, bool] | None = None) -> None:
        self.options = {"defaultType": "spot"}
    
    def fetch_ohlcv(self, symbol: str, timeframe: str = "1h", limit: int = 250) -> list[list[float]]:
        return SAMPLE_OHLCV_DATA[:limit]

def test_live_data_endpoint_mocked(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr("ccxt.binance", lambda config: MockExchange(config))
    response = client.get("/api/v1/live_data")
    assert response.status_code == 200

Network smoke tests retained but not required for CI to pass.

Infrastructure

  • Docker: Multi-stage build with editable install
  • CI: GitHub Actions runs ruff, mypy (strict mode), pytest
  • Type safety: Full coverage with mypy, pandas-stubs included
  • Config: pydantic-settings with .env support

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/bin/python python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 (dns block)
    • Triggering command: /home/REDACTED/.local/bin/pytest pytest -v /home/REDACTED/work/crypto-trade-analysis/crypto-trade-analysis git conf�� --global credential.username /usr/sbin/git (dns block)

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

Original prompt

Create a new branch add/fastapi-live-data and open a pull request against main that adds a complete FastAPI service for fetching OHLCV candles and computing indicators (EMA/RSI/ATR) with Docker, CI, typing, and tests.

Files and structure to add (create under repo root):

Project files

  • pyproject.toml (dependencies: fastapi, uvicorn[standard], pydantic, pydantic-settings, ccxt, pandas, ta; dev: pytest, httpx, ruff, mypy, types-requests)
  • README.md (quickstart, Docker, notes)
  • .env.example
  • .gitignore
  • Dockerfile
  • docker-compose.yml
  • .github/workflows/ci.yml

Application package (src/app)

  • src/app/init.py
  • src/app/main.py (FastAPI app, health endpoint, include router)

Core

  • src/app/core/init.py
  • src/app/core/config.py (pydantic-settings Settings; load .env)
  • src/app/core/logging.py (basic logging config)

API routes

  • src/app/api/init.py
  • src/app/api/v1/init.py
  • src/app/api/v1/routes_live_data.py (GET /api/v1/live_data; Query validation; response_model)
  • src/app/api/v1/ws_live_data.py (WebSocket endpoint /api/v1/live_data/ws that streams recent candle payloads every N seconds; interval query param)

Integrations

  • src/app/integrations/init.py
  • src/app/integrations/exchanges.py (ExchangeClient wrapper; build_exchange to instantiate ccxt exchange with enableRateLimit and options.defaultType)

Schemas

  • src/app/schemas/init.py
  • src/app/schemas/live_data.py (Pydantic models: Candle, LatestIndicators, LiveDataResponse)

Services

  • src/app/services/init.py
  • src/app/services/indicators.py (add_indicators using ta: EMA20/50/200, RSI14, ATR14; helper to convert NaN->None)
  • src/app/services/market_data.py (get_live_data: fetch OHLCV via ccxt.fetch_ohlcv, build DataFrame, add indicators, prepare recent_candles (last 20), latest indicators, meta)

Tests

  • tests/init.py
  • tests/test_health.py (health endpoint)
  • tests/test_live_data.py (network smoke test)
  • tests/test_live_data_mocked.py (mocked ccxt tests using pytest + monkeypatch to stub exchange.fetch_ohlcv)

Behavior and implementation details

  • Default exchange: "binance" (configurable via .env)
  • Indicators: EMA 20/50/200, RSI 14, ATR 14 using ta and pandas
  • Convert NaN/infinite to None before JSON serialization
  • Validate query params: symbol (3-30 chars), timeframe (1-10), limit (20-2000), exchange (2-40)
  • Error mapping: ccxt.NetworkError -> HTTP 503, ccxt.ExchangeError -> HTTP 400, other exceptions -> HTTP 500
  • recent_candles: return last 20 candles
  • meta: include exchange.options.get("defaultType") when available
  • Logging via core.logging
  • Dockerfile installs package in editable mode with dev deps and runs uvicorn
  • GitHub Actions CI: checkout, setup python 3.11, install dev deps, run ruff, mypy, pytest

Testing/CI

  • Include mocked ccxt tests so CI is deterministic; keep the network smoke test but it won't be required for CI

PR details

  • Branch: add/fastapi-live-data
  • Base: main
  • PR title: "Add professional FastAPI crypto data service with OHLCV + indicators"
  • Include this problem statement text in the PR description
  • Preserve multiple logical commits (do not squash)
  • Do not add assignees, reviewers, or labels by default

Repository: Nfectious/crypto-trade-analysis

This pull request was created from Copilot chat.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits February 19, 2026 05:53
- Add WebSocket endpoint at /api/v1/live_data/ws for streaming data
- Add comprehensive mocked tests using pytest monkeypatch
- Add meta field with defaultType from exchange options
- Add pandas-stubs to fix mypy type checking
- Fix code style to pass ruff linting

Co-authored-by: Nfectious <19631929+Nfectious@users.noreply.github.com>
- Add WebSocket streaming endpoint documentation
- Add JavaScript example for WebSocket usage
- Update features list to highlight WebSocket support
- Update project structure to show new files

Co-authored-by: Nfectious <19631929+Nfectious@users.noreply.github.com>
- Add circuit breaker with max 5 consecutive errors
- Track consecutive errors and close connection after limit
- Reset error counter on successful data fetch
- Improve logging to show error count

Co-authored-by: Nfectious <19631929+Nfectious@users.noreply.github.com>
Copilot AI changed the title [WIP] Add complete FastAPI service for OHLCV candles and indicators Add professional FastAPI crypto data service with OHLCV + indicators Feb 19, 2026
Copilot AI requested a review from Nfectious February 19, 2026 06:01
@Nfectious Nfectious marked this pull request as ready for review February 21, 2026 10:10
@Nfectious Nfectious merged commit 2a2ae49 into main Feb 21, 2026
1 check passed
@Nfectious Nfectious deleted the copilot/add-fastapi-live-data-again branch February 21, 2026 10:11
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