"""Signal endpoints — recent signals with filtering.""" from __future__ import annotations from fastapi import APIRouter, Depends, Query, Request from services.api_gateway.auth.middleware import get_current_user from sqlalchemy import select, desc, func router = APIRouter(prefix="/api/signals", tags=["signals"]) @router.get("") async def list_signals( request: Request, _user: dict = Depends(get_current_user), ticker: str | None = Query(default=None), page: int = Query(default=1, ge=1), per_page: int = Query(default=20, ge=1, le=100), ) -> dict: """Recent signals with optional ticker filter and pagination.""" from shared.models.trading import Signal db = request.app.state.db_session_factory async with db() as session: query = select(Signal).order_by(desc(Signal.created_at)) count_query = select(func.count()).select_from(Signal) if ticker: query = query.where(Signal.ticker == ticker.upper()) count_query = count_query.where(Signal.ticker == ticker.upper()) total = (await session.execute(count_query)).scalar() or 0 offset = (page - 1) * per_page query = query.offset(offset).limit(per_page) result = await session.execute(query) signals = result.scalars().all() return { "signals": [ { "id": str(s.id), "ticker": s.ticker, "direction": s.direction.value, "strength": s.strength, "strategy_sources": s.strategy_sources, "sentiment_score": s.sentiment_score, "acted_on": s.acted_on, "created_at": s.created_at.isoformat() if s.created_at else None, } for s in signals ], "total": total, "page": page, "per_page": per_page, "pages": (total + per_page - 1) // per_page if per_page else 0, }