|
|
|
|
|
from fastapi import FastAPI |
|
|
from fastapi.responses import JSONResponse |
|
|
import yfinance as yf |
|
|
from datetime import datetime, timedelta |
|
|
import pytz |
|
|
|
|
|
app = FastAPI() |
|
|
|
|
|
@app.get("/stock/{name}") |
|
|
async def get_stock_history(name: str): |
|
|
tz = pytz.timezone('Asia/Kolkata') |
|
|
today = datetime.now(tz) |
|
|
|
|
|
dates = { |
|
|
"Current": today, |
|
|
"1 Month Ago": today - timedelta(days=30), |
|
|
"6 Months Ago": today - timedelta(days=182), |
|
|
"1 Year Ago": today - timedelta(days=365), |
|
|
"3 Years Ago": today - timedelta(days=3*365), |
|
|
} |
|
|
|
|
|
try: |
|
|
ticker = yf.Ticker(name) |
|
|
start_date = (today - timedelta(days=4*365)).strftime('%Y-%m-%d') |
|
|
end_date = (today + timedelta(days=1)).strftime('%Y-%m-%d') |
|
|
|
|
|
hist = ticker.history(start=start_date, end=end_date) |
|
|
|
|
|
if hist.empty: |
|
|
return JSONResponse(content={"error": f"No data found for {name}"}, status_code=404) |
|
|
|
|
|
if hist.index.tz is None: |
|
|
hist.index = hist.index.tz_localize(tz) |
|
|
else: |
|
|
hist.index = hist.index.tz_convert(tz) |
|
|
|
|
|
def get_closest_price(date): |
|
|
available_dates = hist.index[hist.index <= date] |
|
|
if not available_dates.empty: |
|
|
closest_date = available_dates[-1] |
|
|
return float(hist.loc[closest_date]['Close']), closest_date.date() |
|
|
else: |
|
|
return None, None |
|
|
|
|
|
result = {} |
|
|
for label, date in dates.items(): |
|
|
price, actual_date = get_closest_price(date) |
|
|
result[label] = { |
|
|
"price": f"{price:.2f}" if price is not None else "No data", |
|
|
"date": str(actual_date) if actual_date else None |
|
|
} |
|
|
|
|
|
latest_date = hist.index[-1].date() |
|
|
if latest_date < today.date(): |
|
|
result["Warning"] = f"Data for {today.date()} not available. Latest is from {latest_date}." |
|
|
|
|
|
return result |
|
|
|
|
|
except Exception as e: |
|
|
return JSONResponse(content={"error": str(e)}, status_code=500) |
|
|
|