from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from pydantic import BaseModel import yfinance as yf from app.db.database import get_db from app.db.models import User, PortfolioItem from app.api.auth import get_current_user router = APIRouter() class BuyRequest(BaseModel): symbol: str quantity: int buy_price: float class SellRequest(BaseModel): portfolio_item_id: int @router.post("/buy") def buy_stock(req: BuyRequest, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)): final_buy_price = req.buy_price # If price wasn't provided (e.g. from watchlist), fetch it live if final_buy_price <= 0: try: ticker = yf.Ticker(req.symbol) final_buy_price = ticker.fast_info.last_price except Exception as e: print(f"Error fetching live price on buy for {req.symbol}: {e}") raise HTTPException(status_code=400, detail="Could not fetch live price, please try again.") new_item = PortfolioItem( user_id=current_user.id, symbol=req.symbol, quantity=req.quantity, buy_price=final_buy_price ) db.add(new_item) db.commit() db.refresh(new_item) return {"message": "Stock purchased successfully", "item": new_item} @router.get("/") def get_portfolio(db: Session = Depends(get_db), current_user: User = Depends(get_current_user)): items = db.query(PortfolioItem).filter(PortfolioItem.user_id == current_user.id).all() portfolio = [] total_invested = 0 total_current_value = 0 for item in items: # Fetch live price live_price = item.buy_price # Fallback try: ticker = yf.Ticker(item.symbol) live_price = ticker.fast_info.last_price except Exception as e: print(f"Error fetching price for {item.symbol}: {e}") invested = item.quantity * item.buy_price current_value = item.quantity * live_price pnl = current_value - invested pnl_percent = (pnl / invested) * 100 if invested > 0 else 0 total_invested += invested total_current_value += current_value portfolio.append({ "id": item.id, "symbol": item.symbol, "quantity": item.quantity, "buy_price": item.buy_price, "current_price": round(live_price, 2), "invested": round(invested, 2), "current_value": round(current_value, 2), "pnl": round(pnl, 2), "pnl_percent": round(pnl_percent, 2), "purchase_date": item.purchase_date }) total_pnl = total_current_value - total_invested total_pnl_percent = (total_pnl / total_invested) * 100 if total_invested > 0 else 0 return { "items": portfolio, "summary": { "total_invested": round(total_invested, 2), "total_current_value": round(total_current_value, 2), "total_pnl": round(total_pnl, 2), "total_pnl_percent": round(total_pnl_percent, 2) } } @router.delete("/{item_id}") def delete_portfolio_item(item_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)): item = db.query(PortfolioItem).filter(PortfolioItem.id == item_id, PortfolioItem.user_id == current_user.id).first() if not item: raise HTTPException(status_code=404, detail="Item not found") db.delete(item) db.commit() return {"message": "Stock sold/removed successfully"}