feat: add portfolio detail API with calculated values
This commit is contained in:
parent
5f3c6061c9
commit
7edc152491
@ -1,6 +1,7 @@
|
||||
"""
|
||||
Portfolio management API endpoints.
|
||||
"""
|
||||
from decimal import Decimal
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
@ -12,7 +13,7 @@ from app.models.portfolio import Portfolio, PortfolioType, Target, Holding, Tran
|
||||
from app.schemas.portfolio import (
|
||||
PortfolioCreate, PortfolioUpdate, PortfolioResponse, PortfolioDetail,
|
||||
TargetCreate, TargetResponse,
|
||||
HoldingCreate, HoldingResponse,
|
||||
HoldingCreate, HoldingResponse, HoldingWithValue,
|
||||
TransactionCreate, TransactionResponse,
|
||||
RebalanceResponse, RebalanceSimulationRequest, RebalanceSimulationResponse,
|
||||
)
|
||||
@ -316,3 +317,63 @@ async def simulate_rebalance(
|
||||
portfolio = _get_portfolio(db, portfolio_id, current_user.id)
|
||||
service = RebalanceService(db)
|
||||
return service.calculate_rebalance(portfolio, additional_amount=data.additional_amount)
|
||||
|
||||
|
||||
@router.get("/{portfolio_id}/detail", response_model=PortfolioDetail)
|
||||
async def get_portfolio_detail(
|
||||
portfolio_id: int,
|
||||
current_user: CurrentUser,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Get portfolio with calculated values."""
|
||||
portfolio = _get_portfolio(db, portfolio_id, current_user.id)
|
||||
|
||||
# Get current prices
|
||||
tickers = [h.ticker for h in portfolio.holdings]
|
||||
service = RebalanceService(db)
|
||||
prices = service.get_current_prices(tickers)
|
||||
|
||||
# Calculate holding values
|
||||
holdings_with_value = []
|
||||
total_value = Decimal("0")
|
||||
total_invested = Decimal("0")
|
||||
|
||||
for holding in portfolio.holdings:
|
||||
current_price = prices.get(holding.ticker, Decimal("0"))
|
||||
value = current_price * holding.quantity
|
||||
invested = Decimal(str(holding.avg_price)) * holding.quantity
|
||||
profit_loss = value - invested
|
||||
profit_loss_ratio = (profit_loss / invested * 100) if invested > 0 else Decimal("0")
|
||||
|
||||
total_value += value
|
||||
total_invested += invested
|
||||
|
||||
holdings_with_value.append(HoldingWithValue(
|
||||
ticker=holding.ticker,
|
||||
quantity=holding.quantity,
|
||||
avg_price=Decimal(str(holding.avg_price)),
|
||||
current_price=current_price,
|
||||
value=value,
|
||||
current_ratio=Decimal("0"), # Will be calculated after total
|
||||
profit_loss=profit_loss,
|
||||
profit_loss_ratio=profit_loss_ratio.quantize(Decimal("0.01")),
|
||||
))
|
||||
|
||||
# Calculate current ratios
|
||||
for h in holdings_with_value:
|
||||
if total_value > 0:
|
||||
h.current_ratio = (h.value / total_value * 100).quantize(Decimal("0.01"))
|
||||
|
||||
return PortfolioDetail(
|
||||
id=portfolio.id,
|
||||
user_id=portfolio.user_id,
|
||||
name=portfolio.name,
|
||||
portfolio_type=portfolio.portfolio_type.value,
|
||||
created_at=portfolio.created_at,
|
||||
updated_at=portfolio.updated_at,
|
||||
targets=portfolio.targets,
|
||||
holdings=holdings_with_value,
|
||||
total_value=total_value,
|
||||
total_invested=total_invested,
|
||||
total_profit_loss=total_value - total_invested,
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user