Files
stock/backend/app/main.py
T
2026-09-09 11:35:02 +08:00

59 lines
1.5 KiB
Python

"""FastAPI 入口。数据库结构统一由 Alembic 管理。"""
import asyncio
from contextlib import asynccontextmanager, suppress
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import text
from . import cache, scheduler
from .api import router
from .auth_api import router as auth_router
from .config import settings
from .db import engine
@asynccontextmanager
async def lifespan(app: FastAPI):
async with engine.connect() as conn:
await conn.execute(text("SELECT 1"))
nightly = asyncio.create_task(scheduler.run_nightly_loop())
yield
nightly.cancel()
with suppress(asyncio.CancelledError):
await nightly
await engine.dispose()
await cache.aclose() # 释放 Redis 连接池(未启用时是 no-op)
app = FastAPI(
title="Stock Backtest",
description="股票研究平台:全市场数据 + 智能选股 + 事件回测(A 股为主,不做实盘)",
version="0.1.0",
lifespan=lifespan,
docs_url="/docs" if settings.expose_api_docs else None,
redoc_url=None,
openapi_url="/openapi.json" if settings.expose_api_docs else None,
)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(auth_router)
app.include_router(router)
@app.get("/api/health")
async def health() -> dict:
return {"status": "ok"}
@app.get("/")
async def root() -> dict:
return {"name": "Stock Backtest API", "docs": "/docs"}