from contextlib import asynccontextmanager from datetime import datetime from typing import AsyncGenerator from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.database import init_db from app.scheduler import start_scheduler, stop_scheduler, scheduler from app.routers import devices, portfolio, recommendations, positions, signals, alerts from app.models.schemas import HealthResponse @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator: # Startup init_db() start_scheduler() yield # Shutdown stop_scheduler() app = FastAPI( title="Options Sidekick", description="Covered call and cash-secured put recommendation engine", version="1.0.0", lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # Routers app.include_router(devices.router, prefix="/api/v1") app.include_router(portfolio.router, prefix="/api/v1") app.include_router(recommendations.router, prefix="/api/v1") app.include_router(positions.router, prefix="/api/v1") app.include_router(signals.router, prefix="/api/v1") app.include_router(alerts.router, prefix="/api/v1") @app.get("/api/v1/health", response_model=HealthResponse, tags=["health"]) def health(): from app.services.position_monitor import last_run return HealthResponse( status="ok", scheduler_running=scheduler.running, last_run=last_run, )