""" 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, HTMLResponse 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 documentation endpoint @app.get("/", response_class=HTMLResponse, include_in_schema=False) async def root_documentation(): """ Display comprehensive API documentation at root path """ try: # Simple working version simple_html = f""" Stock Oracle API Documentation

🔮 Stock Oracle API Documentation

Comprehensive Investment Data Analysis API

🚀 Quick Start

Base URL: http://localhost:18001/api/v1

🎯 Main Endpoints

Health & System

Financial Data

Price Data

Stock Market Data NEW

FRED Economic Data NEW

News & Social Media NEW

SEC Filings NEW

Alpaca Market Data NEW

FINRA Short Volume NEW

ETF Holdings

Stock Screener NEW

Attention Overlay NEW

📊 Example Requests

Financial Data

curl -X POST "http://localhost:18001/api/v1/financial/data" \\
  -H "Content-Type: application/json" \\
  -d '{{"ticker": "AAPL", "period": "1y", "include_metrics": true}}'

Trending Stocks NEW

# Get trending stocks (default: 500 total stocks with intelligent coordination)
curl "http://localhost:18001/api/v1/stocks/trending"

# Custom total count
curl "http://localhost:18001/api/v1/stocks/trending?n=200"

FRED Economic Data NEW

# Get GDP series information
curl "http://localhost:18001/api/v1/fred/proxy/series?series_id=GDP"

# Get unemployment rate observations
curl "http://localhost:18001/api/v1/fred/proxy/series/observations?series_id=UNRATE&limit=12"

News & Social Data NEW

curl "http://localhost:18001/api/v1/news/AAPL?days_back=7&max_articles=20"

Price - Quote/Intraday/Today NEW

# Quote (latest regular/pre/post)
curl "http://localhost:18001/api/v1/price/quote/AAPL?use_prepost=true"

# Intraday 1m candles for 1 day
curl "http://localhost:18001/api/v1/price/intraday/AAPL?interval=1m&period=1d"

# Today's OHLC (daily if available; otherwise 1m aggregate)
curl "http://localhost:18001/api/v1/price/today/AAPL"

SEC Filings NEW

# Search AAPL 8-K filings (earnings announcements, material events)
curl "http://localhost:18001/api/v1/filings/search/AAPL?form_type=8-K&limit=5"

# Search foreign issuer filings
curl "http://localhost:18001/api/v1/filings/search/TSM?form_type=20-F"
curl "http://localhost:18001/api/v1/filings/search/SAP?form_type=6-K"

# List all documents in a filing
curl "http://localhost:18001/api/v1/filings/documents/0000320193-26-000005"

# Extract press release (Exhibit 99.1) from an 8-K
curl "http://localhost:18001/api/v1/filings/exhibit/0000320193-26-000005?exhibit_type=EX-99.1"

ETF Holdings

curl "http://localhost:18001/api/v1/etf/holdings/QQQ"

🐍 Python Client

from stock_oracle_client import StockOracleClient

client = StockOracleClient("http://localhost:18001")

# Check health
health = client.get_health()
print("API Status:", health["status"])

# Get financial data
data = client.get_financial_data("AAPL", period="1y")

# Get news data (NEW!)
news = client.get_news_social_data("AAPL", days_back=7)

📈 Key Features

Attention Overlay Response Example NEW

GET /api/v1/overlay/AAPL
{{
  "symbol": "AAPL",
  "as_of_ts": "2026-03-13T20:30:00Z",
  "overlay_score": 0.72,          // 0~1 (higher = more retail attention)
  "overlay_confidence": 0.80,     // fraction of sources with data
  "overlay_band": "supportive",   // silent / tepid / supportive / loud / frenzied
  "hold_extension_hint": "neutral", // extend / neutral / trim
  "add_on_eligibility": false,
  "features": {{
    "headline_burst_z": 1.2,      // z-score vs 30-day window
    "youtube_influence_z": 0.8,
    "wiki_attention_z": null,
    "theme_heat_z": null,
    "crowding_stress_z": -0.3
  }},
  "source_presence": {{
    "yahoo": true, "youtube": true,
    "wikimedia": false, "google_trends": false, "finra": true
  }},
  "source_details": {{
    "yahoo": {{"headline_count_6h": 5, "headline_count_24h": 12, "publisher_breadth_24h": 4}},
    "finra": {{"short_volume_ratio": 0.42, "short_volume_spike_zscore": -0.3}}
  }}
}}

Alpaca Market Data NEW

# Check Alpaca connection status
curl "http://localhost:18001/api/v1/alpaca/status"

# Get daily bars from Alpaca
curl "http://localhost:18001/api/v1/alpaca/bars/AAPL?interval=1d&start_date=2025-01-01&end_date=2025-01-31"

FINRA Short Volume NEW

# Ingest FINRA data for a specific date
curl -X POST "http://localhost:18001/api/v1/finra/admin/ingest?date=2025-03-10"

# Get short volume for AAPL (last 30 days)
curl "http://localhost:18001/api/v1/finra/short-volume/AAPL?days=30"

# Get short ratio history
curl "http://localhost:18001/api/v1/finra/short-ratio/AAPL?days=60"

Stock Screener NEW

# Small/mid-cap stocks on NYSE+NASDAQ with avg volume > 500K, sorted by market cap
curl "http://localhost:18001/api/v1/screener/stocks?market_cap_min=500000000&market_cap_max=10000000000&exchange=NYSE,NASDAQ&min_avg_volume=500000&exclude_types=ETF,FUND"

# Technology sector only
curl "http://localhost:18001/api/v1/screener/stocks?market_cap_min=500000000&exchange=NASDAQ§or=Technology&page=1&page_size=50"

# Available filter metadata
curl "http://localhost:18001/api/v1/screener/fields"

Attention Overlay NEW

# Overlay score for a single symbol
curl "http://localhost:18001/api/v1/overlay/AAPL"

# Bulk scores (comma-separated, max 50)
curl "http://localhost:18001/api/v1/overlay/bulk?symbols=AAPL,TSLA,NVDA,AMD,META"

# Top movers by overlay score (last 24h)
curl "http://localhost:18001/api/v1/overlay/top-movers?limit=10"

# Recent headlines matched to AAPL
curl "http://localhost:18001/api/v1/overlay/AAPL/headlines?hours=24"

# Wikipedia pageview trend (last 30 days)
curl "http://localhost:18001/api/v1/overlay/AAPL/wiki?days=30"

# FINRA crowding metrics
curl "http://localhost:18001/api/v1/overlay/AAPL/crowding"

# Historical overlay scores (backtesting)
curl "http://localhost:18001/api/v1/overlay/AAPL/history?days=90"

# Manually trigger full pipeline
curl -X POST "http://localhost:18001/api/v1/overlay/admin/trigger-pipeline"

🔧 Data Sources

""" return HTMLResponse(content=simple_html) except Exception as e: # Fallback to Swagger UI if anything goes wrong 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" } ] if __name__ == "__main__": import uvicorn uvicorn.run( "app.main:app", host="0.0.0.0", port=settings.API_PORT, reload=settings.DEBUG )