70 lines
1.8 KiB
Python
70 lines
1.8 KiB
Python
|
|
"""Rebalancing API endpoints."""
|
||
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||
|
|
from sqlalchemy.orm import Session
|
||
|
|
|
||
|
|
from app.database import get_db
|
||
|
|
from app.schemas.portfolio import (
|
||
|
|
RebalancingRequest,
|
||
|
|
RebalancingResponse
|
||
|
|
)
|
||
|
|
from app.services.rebalancing_service import RebalancingService, PortfolioService
|
||
|
|
|
||
|
|
router = APIRouter()
|
||
|
|
|
||
|
|
|
||
|
|
@router.post("/calculate", response_model=RebalancingResponse)
|
||
|
|
async def calculate_rebalancing(
|
||
|
|
request: RebalancingRequest,
|
||
|
|
db: Session = Depends(get_db)
|
||
|
|
):
|
||
|
|
"""
|
||
|
|
리밸런싱 계산.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
request: 리밸런싱 요청
|
||
|
|
db: 데이터베이스 세션
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
리밸런싱 추천
|
||
|
|
"""
|
||
|
|
try:
|
||
|
|
# 포트폴리오 조회
|
||
|
|
portfolio = PortfolioService.get_portfolio(request.portfolio_id, db)
|
||
|
|
|
||
|
|
if not portfolio:
|
||
|
|
raise HTTPException(
|
||
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
||
|
|
detail="포트폴리오를 찾을 수 없습니다"
|
||
|
|
)
|
||
|
|
|
||
|
|
# 현재 보유량을 딕셔너리로 변환
|
||
|
|
current_holdings = {
|
||
|
|
holding.ticker: holding.quantity
|
||
|
|
for holding in request.current_holdings
|
||
|
|
}
|
||
|
|
|
||
|
|
# 리밸런싱 계산
|
||
|
|
result = RebalancingService.calculate_rebalancing(
|
||
|
|
portfolio_id=request.portfolio_id,
|
||
|
|
current_holdings=current_holdings,
|
||
|
|
cash=request.cash,
|
||
|
|
db_session=db
|
||
|
|
)
|
||
|
|
|
||
|
|
# 응답 구성
|
||
|
|
return {
|
||
|
|
'portfolio': portfolio,
|
||
|
|
**result
|
||
|
|
}
|
||
|
|
|
||
|
|
except ValueError as e:
|
||
|
|
raise HTTPException(
|
||
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
||
|
|
detail=str(e)
|
||
|
|
)
|
||
|
|
except Exception as e:
|
||
|
|
raise HTTPException(
|
||
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||
|
|
detail=f"리밸런싱 계산 오류: {str(e)}"
|
||
|
|
)
|