""" MEXC Funding Rate Report - Backend API FastAPI application for providing funding rate data and analysis. """ import os from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from apscheduler.schedulers.asyncio import AsyncIOScheduler from app.config import get_settings from app.database import Database from app.api import ( funding_rates_router, stats_router, alerts_router, watchlist_router, telegram_router, ) # Initialize settings settings = get_settings() # Scheduler instance scheduler = AsyncIOScheduler() async def scheduled_data_refresh(): """Refresh MEXC data every 5 minutes - ONLY source of MEXC API calls.""" from app.services import get_mexc_client client = get_mexc_client() await client.refresh_data() async def scheduled_fr_snapshot(): """Record FR snapshot for watched coins (hourly).""" from app.services import get_history_service service = get_history_service() count = await service.record_fr_snapshot() if count > 0: print(f"Recorded FR snapshot for {count} watched coins") async def scheduled_telegram_notify(): """Send hourly Telegram notifications.""" from app.services import get_telegram_service service = get_telegram_service() if service.is_configured(): await service.send_top_fr_notification() await service.send_watchlist_notification() @asynccontextmanager async def lifespan(app: FastAPI): """Application lifespan manager.""" # Startup await Database.connect() # Initial data fetch from app.services import get_mexc_client client = get_mexc_client() await client.refresh_data() # Setup Telegram bot with webhook from app.services.telegram_bot import TelegramBot webhook_url = os.environ.get("SPACE_HOST") if webhook_url: webhook_url = f"https://{webhook_url}" await TelegramBot.setup(webhook_base_url=webhook_url) # Setup scheduler scheduler.add_job( scheduled_data_refresh, 'interval', minutes=5, id='data_refresh', replace_existing=True, ) scheduler.add_job( scheduled_fr_snapshot, 'interval', minutes=settings.fr_history_interval, id='fr_snapshot', replace_existing=True, ) scheduler.add_job( scheduled_telegram_notify, 'interval', minutes=settings.telegram_notify_interval, id='telegram_notify', replace_existing=True, ) scheduler.start() print(f"Scheduler started: Data refresh every 5min, FR snapshot every {settings.fr_history_interval}min") yield # Shutdown scheduler.shutdown() await TelegramBot.shutdown() await Database.disconnect() # Create FastAPI app app = FastAPI( title="MEXC Funding Rate Report API", description="API for monitoring and analyzing MEXC Futures funding rates", version="2.0.0", docs_url="/docs", redoc_url="/redoc", lifespan=lifespan, ) # Configure CORS origins = settings.cors_origins.split(",") app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers app.include_router(funding_rates_router, prefix="/api/v1") app.include_router(stats_router, prefix="/api/v1") app.include_router(alerts_router, prefix="/api/v1") app.include_router(watchlist_router, prefix="/api/v1") app.include_router(telegram_router, prefix="/api/v1") @app.get("/") async def root(): """Health check endpoint.""" from app.services import get_mexc_client client = get_mexc_client() cache_age = client.get_cache_age_seconds() return { "status": "ok", "message": "MEXC FR Report API is running", "version": "2.0.0", "cache_age_seconds": cache_age, "data_refresh": "every 5 minutes", } @app.get("/health") async def health(): """Health check endpoint for monitoring.""" from app.database import get_database from app.services import get_mexc_client db = get_database() client = get_mexc_client() return { "status": "healthy", "database": "connected" if db is not None else "disconnected", "mexc_cache_age": client.get_cache_age_seconds(), "mexc_tickers_count": len(client.get_cached_tickers()), } if __name__ == "__main__": import uvicorn port = int(os.environ.get("PORT", 8000)) uvicorn.run("app.main:app", host="0.0.0.0", port=port, reload=True)