You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
4.9 KiB
Python
161 lines
4.9 KiB
Python
"""
|
|
Main FastAPI application
|
|
"""
|
|
|
|
import os
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI, HTTPException
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import RedirectResponse
|
|
|
|
from app.core.config import settings
|
|
from app.api.v1.api import api_router
|
|
from app.core.database import engine, Base
|
|
from app.middleware.error_logger import ErrorLoggingMiddleware
|
|
from app.models import error_log, request_log, fred_data, filing, finra_short_volume, alpaca_price # Import to register models
|
|
from app.models import overlay_registry, overlay_raw_event, overlay_feature # Overlay models
|
|
|
|
# Create database tables
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
# Startup - ensure tables exist
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.create_all)
|
|
# Start overlay batch scheduler (graceful no-op if apscheduler not installed)
|
|
try:
|
|
from app.services.overlay.scheduler import start_scheduler
|
|
start_scheduler()
|
|
except Exception:
|
|
pass
|
|
yield
|
|
# Shutdown
|
|
try:
|
|
from app.services.overlay.scheduler import stop_scheduler
|
|
stop_scheduler()
|
|
except Exception:
|
|
pass
|
|
await engine.dispose()
|
|
|
|
# Create FastAPI app
|
|
app = FastAPI(
|
|
title=settings.APP_NAME,
|
|
version=settings.APP_VERSION,
|
|
openapi_url=f"{settings.API_PREFIX}/openapi.json",
|
|
docs_url=f"{settings.API_PREFIX}/docs",
|
|
redoc_url=f"{settings.API_PREFIX}/redoc",
|
|
lifespan=lifespan
|
|
)
|
|
|
|
# Add error logging middleware
|
|
app.add_middleware(ErrorLoggingMiddleware)
|
|
|
|
# Set up CORS - use configured origins if available, otherwise allow all
|
|
cors_origins = [str(o) for o in settings.BACKEND_CORS_ORIGINS] if settings.BACKEND_CORS_ORIGINS else ["*"]
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=cors_origins,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Include API router
|
|
app.include_router(api_router, prefix=settings.API_PREFIX)
|
|
|
|
# Root — redirect to Swagger UI
|
|
@app.get("/", include_in_schema=False)
|
|
async def root_redirect():
|
|
return RedirectResponse(url=f"{settings.API_PREFIX}/docs")
|
|
|
|
# Additional metadata for OpenAPI
|
|
app.openapi_tags = [
|
|
{
|
|
"name": "health",
|
|
"description": "Health check endpoints"
|
|
},
|
|
{
|
|
"name": "financial",
|
|
"description": "Financial data retrieval endpoints"
|
|
},
|
|
{
|
|
"name": "price",
|
|
"description": "Price data endpoints (OHLCV)"
|
|
},
|
|
{
|
|
"name": "news",
|
|
"description": "News and social media endpoints"
|
|
},
|
|
{
|
|
"name": "metadata",
|
|
"description": "Data catalog and metadata endpoints"
|
|
},
|
|
{
|
|
"name": "filings",
|
|
"description": "SEC filings search, document listing, and exhibit extraction (8-K, 6-K, 20-F, 40-F)"
|
|
},
|
|
{
|
|
"name": "etf",
|
|
"description": "ETF holdings endpoints"
|
|
},
|
|
{
|
|
"name": "alpaca",
|
|
"description": "Alpaca Market Data endpoints (OHLCV bars, connection status)"
|
|
},
|
|
{
|
|
"name": "finra",
|
|
"description": "FINRA RegSHO short sale volume data (ingest, query, ratio history)"
|
|
},
|
|
{
|
|
"name": "admin",
|
|
"description": "Administrative endpoints (migration, etc.)"
|
|
},
|
|
{
|
|
"name": "overlay",
|
|
"description": "Attention Overlay - retail investor interest, media diffusion, crowding signals"
|
|
},
|
|
{
|
|
"name": "overlay-admin",
|
|
"description": "Overlay administrative endpoints (pipeline trigger, health, job log)"
|
|
},
|
|
{
|
|
"name": "screener",
|
|
"description": "Stock screener — condition-based filtering by market cap, volume, price, P/E, sector, exchange"
|
|
},
|
|
{
|
|
"name": "stocks",
|
|
"description": "Stock market data — most active, 52-week gainers, trending, and index constituents (S&P 500 / Nasdaq 100)"
|
|
},
|
|
{
|
|
"name": "attention",
|
|
"description": "Attention signals — Wikipedia pageview spikes and GDELT news article counts for event-centric backtesting"
|
|
},
|
|
{
|
|
"name": "attention-admin",
|
|
"description": "Attention administrative endpoints — entity resolution, Wikipedia and GDELT data collection"
|
|
},
|
|
{
|
|
"name": "database",
|
|
"description": "Database inspection — record counts, date ranges, raw data browsing, and ETF snapshot history"
|
|
},
|
|
{
|
|
"name": "fred",
|
|
"description": "FRED (Federal Reserve Economic Data) — macroeconomic series via FRED API proxy"
|
|
},
|
|
{
|
|
"name": "error-logs",
|
|
"description": "Error log management — browse and clear server-side error records"
|
|
},
|
|
{
|
|
"name": "request-logs",
|
|
"description": "Request log management — browse API request history and latency records"
|
|
}
|
|
]
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
uvicorn.run(
|
|
"app.main:app",
|
|
host="0.0.0.0",
|
|
port=settings.API_PORT,
|
|
reload=settings.DEBUG
|
|
) |