Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/najmulhossainnj/Hedge-fund-backend/llms.txt

Use this file to discover all available pages before exploring further.

The Hedge Fund Backend ships as two separate Docker images — one for the FastAPI application server and one for the Celery background-worker pool. Both images are built from python:3.12-slim and install all Python dependencies from requirements.txt. The API server listens on port 8000 and communicates with the worker over Redis. No application code changes are required to switch between development and production; all runtime behaviour is driven entirely by environment variables.

Infrastructure Requirements

Before starting either container you need four external services running and reachable:
ServiceMinimum versionPurpose
PostgreSQL15+Primary relational store for all domain models (strategies, features, ML models, backtests)
Redis7+Session cache (REDIS_URL), Celery broker (CELERY_BROKER_URL), and result backend (CELERY_RESULT_BACKEND) — three separate logical databases
MinIO (S3-compatible)Any recentObject storage for feature datasets and MLflow model artifacts
MLflow tracking server2.xExperiment and model-artifact tracking via MLFLOW_TRACKING_URI
All four services can be co-located on a single host for development. For production, place PostgreSQL, Redis, and MinIO behind private networking so only the application containers can reach them.

Building Docker Images

The repository contains two Dockerfiles. Build them from the project root:
# API server — exposes port 8000, runs uvicorn
docker build -f Dockerfile -t hedge-fund-backend:latest .

# Celery worker — no exposed port, connects outbound to broker
docker build -f Dockerfile.worker -t hedge-fund-worker:latest .
Both images run the same pip install -r requirements.txt step, so the build cache is shared when layers are identical. Expect the first build to take several minutes due to compiled dependencies (psycopg2, xgboost, lightgbm).
Tag images with a Git SHA for immutable deployments:
docker build -f Dockerfile -t hedge-fund-backend:$(git rev-parse --short HEAD) .

Running the API Server

1
Start the API container
2
Pass all required environment variables with -e flags or mount a .env file. The container exposes port 8000 which you map to the host.
3
docker run -d \
  --name hedge-fund-api \
  -p 8000:8000 \
  -e APP_ENV=production \
  -e DATABASE_URL=postgresql+asyncpg://postgres:secret@db:5432/research_layer \
  -e REDIS_URL=redis://redis:6379/0 \
  -e CELERY_BROKER_URL=redis://redis:6379/1 \
  -e CELERY_RESULT_BACKEND=redis://redis:6379/2 \
  -e S3_ENDPOINT_URL=http://minio:9000 \
  -e S3_ACCESS_KEY=minioadmin \
  -e S3_SECRET_KEY=minioadmin \
  -e S3_BUCKET_ARTIFACTS=research-artifacts \
  -e S3_BUCKET_FEATURES=feature-store \
  -e MLFLOW_TRACKING_URI=http://mlflow:5000 \
  -e MLFLOW_EXPERIMENT_NAME=research-layer \
  -e MLFLOW_ARTIFACT_ROOT=s3://research-artifacts/mlflow \
  -e MARKET_DATA_URL=http://market-data:8001 \
  -e KAFKA_BOOTSTRAP_SERVERS=kafka:9092 \
  -e EVENT_BACKEND=kafka \
  -e SECRET_KEY=<your-secret-key> \
  -e CORS_ORIGINS='["https://app.yourdomain.com"]' \
  hedge-fund-backend:latest
4
Verify the container is running
5
docker ps --filter name=hedge-fund-api

Running the Celery Worker

The worker container uses the same image tag as a base but invokes celery instead of uvicorn. It shares identical database and broker credentials with the API container.
docker run -d \
  --name hedge-fund-worker \
  -e DATABASE_URL=postgresql+asyncpg://postgres:secret@db:5432/research_layer \
  -e REDIS_URL=redis://redis:6379/0 \
  -e CELERY_BROKER_URL=redis://redis:6379/1 \
  -e CELERY_RESULT_BACKEND=redis://redis:6379/2 \
  -e S3_ENDPOINT_URL=http://minio:9000 \
  -e S3_ACCESS_KEY=minioadmin \
  -e S3_SECRET_KEY=minioadmin \
  -e S3_BUCKET_ARTIFACTS=research-artifacts \
  -e S3_BUCKET_FEATURES=feature-store \
  -e MLFLOW_TRACKING_URI=http://mlflow:5000 \
  -e MLFLOW_EXPERIMENT_NAME=research-layer \
  -e MLFLOW_ARTIFACT_ROOT=s3://research-artifacts/mlflow \
  -e MARKET_DATA_URL=http://market-data:8001 \
  -e SECRET_KEY=<your-secret-key> \
  hedge-fund-worker:latest
The Dockerfile.worker default command starts the worker with --concurrency=2. Override concurrency at runtime:
docker run -d ... hedge-fund-worker:latest \
  celery -A app.workers.celery_app worker --loglevel=info --concurrency=4

Health Check

Once the API container is running, verify it is healthy with:
curl http://localhost:8000/health
A successful response:
{
  "status": "ok",
  "service": "Research Layer",
  "env": "production"
}
The service field reflects the APP_NAME setting and env reflects APP_ENV. If the response is anything other than 200 OK, inspect the container logs:
docker logs hedge-fund-api --tail 100

Database Migrations

Schema migrations are managed by Alembic. Run them inside the running API container before the service accepts traffic:
1
Apply all pending migrations
2
docker exec hedge-fund-api alembic upgrade head
3
Check current revision
4
docker exec hedge-fund-api alembic current
5
Generate a new migration (development)
6
docker exec hedge-fund-api alembic revision --autogenerate -m "describe your change"
The Alembic environment (alembic/env.py) reads DATABASE_URL from app.core.config.get_settings() automatically, so no separate alembic.ini edits are needed when environment variables are already set on the container.

Port Mapping

ContainerInternal portSuggested host mapping
hedge-fund-api80008000:8000 (dev) or reverse-proxy only (prod)
hedge-fund-workerNone (outbound only)

CORS

The default CORS_ORIGINS value is ["http://localhost:5173"] (the Vite dev-server origin). In development you may wish to widen this to ["*"], but you must set CORS_ORIGINS to the exact origin(s) of your production frontend when deploying publicly. Wildcard origins disable cookie-based authentication and expose the API to cross-site requests.

Secret Key

The default SECRET_KEY value is literally "change-me-in-production". This key is used to sign session tokens and other security-sensitive material. You must replace it with a cryptographically random value before any production deployment. Generate one with:
python -c "import secrets; print(secrets.token_hex(32))"
Never commit the real key to source control.

Build docs developers (and LLMs) love