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.
285 lines
11 KiB
Python
285 lines
11 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, 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 # Import to register 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)
|
|
yield
|
|
# Shutdown
|
|
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"""
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Stock Oracle API Documentation</title>
|
|
<style>
|
|
body {{
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
line-height: 1.6;
|
|
max-width: 1000px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
color: #333;
|
|
}}
|
|
h1 {{ color: #007acc; border-bottom: 2px solid #007acc; padding-bottom: 10px; }}
|
|
h2 {{ color: #2c3e50; margin-top: 2em; }}
|
|
.nav-links {{ margin: 20px 0; }}
|
|
.nav-links a {{
|
|
display: inline-block;
|
|
margin-right: 15px;
|
|
padding: 10px 20px;
|
|
background: #007acc;
|
|
color: white;
|
|
text-decoration: none;
|
|
border-radius: 5px;
|
|
}}
|
|
.nav-links a:hover {{ background: #0066aa; }}
|
|
code {{ background: #f4f4f4; padding: 2px 4px; border-radius: 3px; }}
|
|
pre {{ background: #f4f4f4; padding: 15px; border-radius: 5px; overflow-x: auto; }}
|
|
.new-badge {{ background: #e74c3c; color: white; padding: 2px 6px; border-radius: 3px; font-size: 0.8em; }}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>🔮 Stock Oracle API Documentation</h1>
|
|
<p><strong>Comprehensive Investment Data Analysis API</strong></p>
|
|
|
|
<div class="nav-links">
|
|
<a href="{settings.API_PREFIX}/docs">📋 Interactive API Docs</a>
|
|
<a href="{settings.API_PREFIX}/redoc">📖 ReDoc</a>
|
|
<a href="{settings.API_PREFIX}/health">💚 Health Check</a>
|
|
<a href="{settings.API_PREFIX}/openapi.json">⚙️ OpenAPI Schema</a>
|
|
</div>
|
|
|
|
<h2>🚀 Quick Start</h2>
|
|
<p><strong>Base URL:</strong> <code>http://localhost:18001/api/v1</code></p>
|
|
|
|
<h2>🎯 Main Endpoints</h2>
|
|
|
|
<h3>Health & System</h3>
|
|
<ul>
|
|
<li><code>GET /health</code> - API health status</li>
|
|
<li><code>GET /health/detailed</code> - Detailed system health</li>
|
|
</ul>
|
|
|
|
<h3>Financial Data</h3>
|
|
<ul>
|
|
<li><code>POST /financial/data</code> - Get comprehensive financial data</li>
|
|
<li><code>GET /financial/data/{{ticker}}</code> - Simple financial data</li>
|
|
<li><code>POST /financial/data/bulk</code> - Bulk financial data</li>
|
|
</ul>
|
|
|
|
<h3>Price Data</h3>
|
|
<ul>
|
|
<li><code>POST /price/data</code> - Get historical price data (OHLCV)</li>
|
|
<li><code>GET /price/data/{{ticker}}</code> - Simple price data</li>
|
|
<li><code>POST /price/data/bulk</code> - Bulk price data</li>
|
|
<li><code>GET /price/quote/{{ticker}}</code> - Latest quote (regular/pre/post market)</li>
|
|
<li><code>GET /price/intraday/{{ticker}}</code> - Intraday candles (interval, period)</li>
|
|
<li><code>GET /price/today/{{ticker}}</code> - Today's OHLC (daily or 1m aggregate)</li>
|
|
</ul>
|
|
|
|
<h3>Stock Market Data <span class="new-badge">NEW</span></h3>
|
|
<ul>
|
|
<li><code>GET /stocks/trending</code> - Trending stocks with intelligent parameter coordination (n=500 default)</li>
|
|
<li><code>GET /stocks/most-active</code> - Most actively traded stocks</li>
|
|
<li><code>GET /stocks/52-week-gainers</code> - Top 52-week gaining stocks</li>
|
|
</ul>
|
|
|
|
<h3>FRED Economic Data <span class="new-badge">NEW</span></h3>
|
|
<ul>
|
|
<li><code>GET /fred/proxy/{{endpoint}}</code> - Universal FRED API proxy with caching</li>
|
|
<li><code>GET /fred/endpoints</code> - List all supported FRED API endpoints</li>
|
|
<li><code>GET /fred/stats/usage</code> - API usage statistics and monitoring</li>
|
|
</ul>
|
|
|
|
<h3>News & Social Media <span class="new-badge">NEW</span></h3>
|
|
<ul>
|
|
<li><code>GET /news/{{ticker}}</code> - Complete news and social media data</li>
|
|
<li><code>GET /news/{{ticker}}/news-only</code> - News articles only (faster)</li>
|
|
<li><code>GET /news/{{ticker}}/social-only</code> - Social media posts only</li>
|
|
</ul>
|
|
|
|
<h3>ETF Holdings</h3>
|
|
<ul>
|
|
<li><code>GET /etf/holdings/{{ticker}}</code> - ETF holdings at date or most recent</li>
|
|
<li><code>POST /etf/admin/refresh-maps</code> - Refresh CUSIP/CIK maps</li>
|
|
</ul>
|
|
|
|
<h2>📊 Example Requests</h2>
|
|
|
|
<h3>Financial Data</h3>
|
|
<pre><code>curl -X POST "http://localhost:18001/api/v1/financial/data" \\
|
|
-H "Content-Type: application/json" \\
|
|
-d '{{"ticker": "AAPL", "period": "1y", "include_metrics": true}}'</code></pre>
|
|
|
|
<h3>Trending Stocks <span class="new-badge">NEW</span></h3>
|
|
<pre><code># 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"</code></pre>
|
|
|
|
<h3>FRED Economic Data <span class="new-badge">NEW</span></h3>
|
|
<pre><code># 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"</code></pre>
|
|
|
|
<h3>News & Social Data <span class="new-badge">NEW</span></h3>
|
|
<pre><code>curl "http://localhost:18001/api/v1/news/AAPL?days_back=7&max_articles=20"</code></pre>
|
|
|
|
<h3>Price - Quote/Intraday/Today <span class="new-badge">NEW</span></h3>
|
|
<pre><code># 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"</code></pre>
|
|
|
|
<h3>ETF Holdings</h3>
|
|
<pre><code>curl "http://localhost:18001/api/v1/etf/holdings/QQQ"</code></pre>
|
|
|
|
<h2>🐍 Python Client</h2>
|
|
<pre><code>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)</code></pre>
|
|
|
|
<h2>📈 Key Features</h2>
|
|
<ul>
|
|
<li><strong>SEC EDGAR Data</strong> - Official company filings (10-K, 10-Q)</li>
|
|
<li><strong>Real-time News</strong> - Yahoo Finance + NewsAPI integration</li>
|
|
<li><strong>Social Sentiment</strong> - Reddit discussions and sentiment analysis</li>
|
|
<li><strong>ETF Holdings</strong> - Complete ETF portfolio analysis via N-PORT</li>
|
|
<li><strong>Price Data</strong> - Historical OHLCV data from Yahoo Finance</li>
|
|
<li><strong>Investment Metrics</strong> - P/E, ROE, debt ratios, growth metrics</li>
|
|
</ul>
|
|
|
|
<h2>🔧 Data Sources</h2>
|
|
<ul>
|
|
<li><strong>SEC EDGAR</strong> - Official company filings and ETF holdings</li>
|
|
<li><strong>Yahoo Finance</strong> - Price data and financial news (via yfinance_plus)</li>
|
|
<li><strong>NewsAPI</strong> - Professional news aggregation</li>
|
|
<li><strong>Reddit API</strong> - Social media sentiment from investing subreddits</li>
|
|
</ul>
|
|
|
|
<footer style="margin-top: 3em; padding-top: 2em; border-top: 1px solid #eee; text-align: center; color: #666;">
|
|
<p><strong>Stock Oracle API</strong> - Built with FastAPI, powered by SEC EDGAR data</p>
|
|
<p>For complete interactive documentation, visit <a href="{settings.API_PREFIX}/docs">Swagger UI</a></p>
|
|
<p><small>Version {settings.APP_VERSION}</small></p>
|
|
</footer>
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
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": "etf",
|
|
"description": "ETF holdings endpoints"
|
|
},
|
|
{
|
|
"name": "admin",
|
|
"description": "Administrative endpoints (migration, etc.)"
|
|
}
|
|
]
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
uvicorn.run(
|
|
"app.main:app",
|
|
host="0.0.0.0",
|
|
port=settings.API_PORT,
|
|
reload=settings.DEBUG
|
|
) |