trading/services/api_gateway/routes/strategies.py

111 lines
3.3 KiB
Python

"""Strategy endpoints — list strategies, weight history, metrics."""
from __future__ import annotations
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Request, status
from services.api_gateway.auth.middleware import get_current_user
from sqlalchemy import select, desc
router = APIRouter(prefix="/api/strategies", tags=["strategies"])
@router.get("")
async def list_strategies(
request: Request,
_user: dict = Depends(get_current_user),
) -> list[dict]:
"""All strategies with current weights."""
from shared.models.trading import Strategy
db = request.app.state.db_session_factory
async with db() as session:
result = await session.execute(select(Strategy))
strategies = result.scalars().all()
return [
{
"id": str(s.id),
"name": s.name,
"description": s.description,
"current_weight": s.current_weight,
"active": s.active,
"created_at": s.created_at.isoformat() if s.created_at else None,
}
for s in strategies
]
@router.get("/{strategy_id}/history")
async def get_strategy_weight_history(
strategy_id: UUID,
request: Request,
_user: dict = Depends(get_current_user),
) -> list[dict]:
"""Weight history for a specific strategy."""
from shared.models.trading import StrategyWeightHistory, Strategy
db = request.app.state.db_session_factory
async with db() as session:
# Verify strategy exists
strategy = (
await session.execute(
select(Strategy).where(Strategy.id == strategy_id)
)
).scalar_one_or_none()
if strategy is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Strategy not found",
)
result = await session.execute(
select(StrategyWeightHistory)
.where(StrategyWeightHistory.strategy_id == strategy_id)
.order_by(desc(StrategyWeightHistory.created_at))
)
history = result.scalars().all()
return [
{
"id": str(h.id),
"old_weight": h.old_weight,
"new_weight": h.new_weight,
"reason": h.reason,
"created_at": h.created_at.isoformat() if h.created_at else None,
}
for h in history
]
@router.get("/{strategy_id}/metrics")
async def get_strategy_metrics(
strategy_id: UUID,
request: Request,
_user: dict = Depends(get_current_user),
) -> list[dict]:
"""Performance metrics over time for a specific strategy."""
from shared.models.timeseries import StrategyMetric
db = request.app.state.db_session_factory
async with db() as session:
result = await session.execute(
select(StrategyMetric)
.where(StrategyMetric.strategy_id == strategy_id)
.order_by(desc(StrategyMetric.timestamp))
.limit(100)
)
metrics = result.scalars().all()
return [
{
"timestamp": m.timestamp.isoformat(),
"win_rate": m.win_rate,
"total_pnl": m.total_pnl,
"trade_count": m.trade_count,
"sharpe_ratio": m.sharpe_ratio,
}
for m in metrics
]