galaxis-po/backend/app/api/correlation.py
머니페니 12d235a1f1 feat: add 9 new modules - notification alerts, trading journal, position sizing, pension allocation, drawdown monitoring, benchmark dashboard, tax simulation, correlation analysis, parameter optimizer
Phase 1:
- Real-time signal alerts (Discord/Telegram webhook)
- Trading journal with entry/exit tracking
- Position sizing calculator (Fixed/Kelly/ATR)

Phase 2:
- Pension asset allocation (DC/IRP 70% risk limit)
- Drawdown monitoring with SVG gauge
- Benchmark dashboard (portfolio vs KOSPI vs deposit)

Phase 3:
- Tax benefit simulation (Korean pension tax rules)
- Correlation matrix heatmap
- Parameter optimizer with grid search + overfit detection
2026-03-29 10:03:08 +09:00

87 lines
2.7 KiB
Python

"""
Correlation analysis API endpoints.
"""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.api.deps import CurrentUser
from app.schemas.correlation import (
CorrelationMatrixRequest,
CorrelationMatrixResponse,
DiversificationResponse,
HighCorrelationPair,
)
from app.services.correlation import CorrelationService
router = APIRouter(prefix="/api/correlation", tags=["correlation"])
@router.post("/matrix", response_model=CorrelationMatrixResponse)
async def calculate_correlation_matrix(
request: CorrelationMatrixRequest,
current_user: CurrentUser,
db: Session = Depends(get_db),
):
"""종목 간 수익률 상관 행렬 계산."""
service = CorrelationService(db)
result = service.get_correlation_data(request.stock_codes, request.period_days)
return CorrelationMatrixResponse(
stock_codes=result["stock_codes"],
matrix=result["matrix"],
high_correlation_pairs=[
HighCorrelationPair(**p) for p in result["high_correlation_pairs"]
],
)
@router.get("/portfolio/{portfolio_id}", response_model=DiversificationResponse)
async def get_portfolio_diversification(
portfolio_id: int,
current_user: CurrentUser,
db: Session = Depends(get_db),
):
"""포트폴리오 분산 효과 점수 조회."""
service = CorrelationService(db)
try:
score = service.calculate_portfolio_diversification(portfolio_id)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
# Get holdings for correlation data
from app.models.portfolio import Portfolio, PortfolioSnapshot
portfolio = db.query(Portfolio).filter(
Portfolio.id == portfolio_id,
Portfolio.user_id == current_user.id,
).first()
if not portfolio:
raise HTTPException(status_code=404, detail="Portfolio not found")
snapshot = (
db.query(PortfolioSnapshot)
.filter(PortfolioSnapshot.portfolio_id == portfolio_id)
.order_by(PortfolioSnapshot.snapshot_date.desc())
.first()
)
high_pairs = []
stock_count = 0
if snapshot and snapshot.holdings:
tickers = [h.ticker for h in snapshot.holdings]
stock_count = len(tickers)
if len(tickers) >= 2:
corr_data = service.get_correlation_data(tickers, period_days=60)
high_pairs = [
HighCorrelationPair(**p) for p in corr_data["high_correlation_pairs"]
]
return DiversificationResponse(
portfolio_id=portfolio_id,
diversification_score=score,
stock_count=stock_count,
high_correlation_pairs=high_pairs,
)