Spaces:
Running
on
Zero
Running
on
Zero
from fastapi import FastAPI, HTTPException | |
from fastapi.middleware.cors import CORSMiddleware | |
import yfinance as yf | |
import pandas as pd | |
from datetime import datetime, timedelta | |
import logging | |
from typing import Optional | |
# Configure logging | |
logging.basicConfig(level=logging.INFO) | |
logger = logging.getLogger(__name__) | |
app = FastAPI() | |
# Configure CORS | |
app.add_middleware( | |
CORSMiddleware, | |
allow_origins=["*"], # Allows all origins | |
allow_credentials=True, | |
allow_methods=["*"], # Allows all methods | |
allow_headers=["*"], # Allows all headers | |
) | |
def fetch_stock_data(symbol: str, period: str = "1y") -> pd.DataFrame: | |
""" | |
Fetch historical stock data for a given symbol using yfinance with authentication. | |
Args: | |
symbol (str): Stock symbol (e.g., 'AAPL') | |
period (str): Time period to fetch (default: '1y') | |
Returns: | |
pd.DataFrame: DataFrame containing historical stock data | |
""" | |
try: | |
# Create a Ticker object with authentication | |
ticker = yf.Ticker(symbol) | |
# Set authentication credentials | |
ticker._session.headers.update({ | |
'User-Agent': 'Mozilla/5.0', | |
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', | |
'Accept-Language': 'en-US,en;q=0.5', | |
'Connection': 'keep-alive', | |
'Upgrade-Insecure-Requests': '1', | |
}) | |
# Fetch historical data | |
df = ticker.history(period=period) | |
if df.empty: | |
logger.warning(f"No data found for symbol {symbol}") | |
return pd.DataFrame() | |
# Reset index to make Date a column | |
df = df.reset_index() | |
# Rename columns to match expected format | |
df = df.rename(columns={ | |
'Date': 'date', | |
'Open': 'open', | |
'High': 'high', | |
'Low': 'low', | |
'Close': 'close', | |
'Volume': 'volume' | |
}) | |
# Convert date to string format | |
df['date'] = df['date'].dt.strftime('%Y-%m-%d') | |
logger.info(f"Successfully fetched data for {symbol}") | |
return df | |
except Exception as e: | |
logger.error(f"Error fetching data for {symbol}: {str(e)}") | |
return pd.DataFrame() | |
async def root(): | |
return {"message": "Stock Prediction API"} | |
async def get_stock_data(symbol: str, period: Optional[str] = "1y"): | |
""" | |
Get historical stock data for a given symbol. | |
Args: | |
symbol (str): Stock symbol (e.g., 'AAPL') | |
period (str, optional): Time period to fetch. Defaults to "1y". | |
Valid periods: 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max | |
Returns: | |
dict: Dictionary containing stock data and metadata | |
""" | |
try: | |
df = fetch_stock_data(symbol, period) | |
if df.empty: | |
raise HTTPException(status_code=404, detail=f"No data found for symbol {symbol}") | |
# Convert DataFrame to dictionary format | |
data = df.to_dict(orient='records') | |
return { | |
"symbol": symbol, | |
"period": period, | |
"data": data, | |
"count": len(data) | |
} | |
except Exception as e: | |
logger.error(f"Error processing request for {symbol}: {str(e)}") | |
raise HTTPException(status_code=500, detail=str(e)) | |
if __name__ == "__main__": | |
import uvicorn | |
uvicorn.run(app, host="0.0.0.0", port=8000) |