85 lines
2.7 KiB
Python
85 lines
2.7 KiB
Python
"""Portfolio API endpoints."""
|
|
|
|
from typing import Optional
|
|
from fastapi import APIRouter, HTTPException, Depends, Query
|
|
from datetime import datetime, timedelta
|
|
|
|
from ..core.dependencies import get_portfolio_tracker
|
|
from ..core.schemas import PortfolioResponse, PortfolioHistoryResponse
|
|
|
|
router = APIRouter()
|
|
|
|
# Import portfolio analytics
|
|
def get_portfolio_analytics():
|
|
"""Get portfolio analytics instance."""
|
|
from src.portfolio.analytics import get_portfolio_analytics as _get_analytics
|
|
return _get_analytics()
|
|
|
|
|
|
@router.get("/current", response_model=PortfolioResponse)
|
|
async def get_current_portfolio(
|
|
paper_trading: bool = True,
|
|
tracker=Depends(get_portfolio_tracker)
|
|
):
|
|
"""Get current portfolio state."""
|
|
try:
|
|
portfolio = await tracker.get_current_portfolio(paper_trading=paper_trading)
|
|
return PortfolioResponse(**portfolio)
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@router.get("/history", response_model=PortfolioHistoryResponse)
|
|
async def get_portfolio_history(
|
|
days: int = Query(30, ge=1, le=365),
|
|
paper_trading: bool = True,
|
|
tracker=Depends(get_portfolio_tracker)
|
|
):
|
|
"""Get portfolio history."""
|
|
try:
|
|
history = await tracker.get_portfolio_history(days=days, paper_trading=paper_trading)
|
|
|
|
dates = [h['timestamp'] if isinstance(h['timestamp'], str) else h['timestamp'].isoformat()
|
|
for h in history]
|
|
values = [float(h['total_value']) for h in history]
|
|
pnl = [float(h.get('total_pnl', 0)) for h in history]
|
|
|
|
return PortfolioHistoryResponse(
|
|
dates=dates,
|
|
values=values,
|
|
pnl=pnl
|
|
)
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@router.post("/positions/update-prices")
|
|
async def update_positions_prices(
|
|
prices: dict,
|
|
paper_trading: bool = True,
|
|
tracker=Depends(get_portfolio_tracker)
|
|
):
|
|
"""Update current prices for positions."""
|
|
try:
|
|
from decimal import Decimal
|
|
price_dict = {k: Decimal(str(v)) for k, v in prices.items()}
|
|
await tracker.update_positions_prices(price_dict, paper_trading=paper_trading)
|
|
return {"status": "updated"}
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@router.get("/risk-metrics")
|
|
async def get_risk_metrics(
|
|
days: int = Query(30, ge=1, le=365),
|
|
paper_trading: bool = True,
|
|
analytics=Depends(get_portfolio_analytics)
|
|
):
|
|
"""Get portfolio risk metrics."""
|
|
try:
|
|
metrics = await analytics.get_performance_metrics(days=days, paper_trading=paper_trading)
|
|
return metrics
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|