feat: add recently_analyzed and trending_tickers GraphQL queries utilizing prediction logs
Browse files- backend/app/database/crud.py +32 -1
- backend/app/graphql/schema.py +19 -0
backend/app/database/crud.py
CHANGED
|
@@ -444,4 +444,35 @@ async def get_all_strategy_logs(db: AsyncSession, limit: int = 1000) -> List[mod
|
|
| 444 |
.order_by(models.StrategyLog.timestamp.desc())
|
| 445 |
.limit(limit)
|
| 446 |
)
|
| 447 |
-
return list(result.scalars().all())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
.order_by(models.StrategyLog.timestamp.desc())
|
| 445 |
.limit(limit)
|
| 446 |
)
|
| 447 |
+
return list(result.scalars().all())
|
| 448 |
+
|
| 449 |
+
|
| 450 |
+
async def get_recently_analyzed_tickers(db: AsyncSession, user_id: uuid.UUID, limit: int = 5) -> List[str]:
|
| 451 |
+
"""
|
| 452 |
+
Retrieves the unique tickers that the specified user has analyzed recently.
|
| 453 |
+
"""
|
| 454 |
+
from sqlalchemy import func
|
| 455 |
+
result = await db.execute(
|
| 456 |
+
select(models.PredictionLog.ticker, func.max(models.PredictionLog.timestamp).label("latest"))
|
| 457 |
+
.where(models.PredictionLog.user_id == user_id)
|
| 458 |
+
.group_by(models.PredictionLog.ticker)
|
| 459 |
+
.order_by(func.max(models.PredictionLog.timestamp).desc())
|
| 460 |
+
.limit(limit)
|
| 461 |
+
)
|
| 462 |
+
return [row.ticker for row in result]
|
| 463 |
+
|
| 464 |
+
|
| 465 |
+
async def get_trending_tickers(db: AsyncSession, limit: int = 5) -> List[dict]:
|
| 466 |
+
"""
|
| 467 |
+
Retrieves the globally trending tickers based on analysis query count in the last 7 days.
|
| 468 |
+
"""
|
| 469 |
+
from sqlalchemy import func
|
| 470 |
+
cutoff = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=7)
|
| 471 |
+
result = await db.execute(
|
| 472 |
+
select(models.PredictionLog.ticker, func.count(models.PredictionLog.id).label("count"))
|
| 473 |
+
.where(models.PredictionLog.timestamp >= cutoff)
|
| 474 |
+
.group_by(models.PredictionLog.ticker)
|
| 475 |
+
.order_by(func.count(models.PredictionLog.id).desc())
|
| 476 |
+
.limit(limit)
|
| 477 |
+
)
|
| 478 |
+
return [{"ticker": row.ticker, "count": row.count} for row in result]
|
backend/app/graphql/schema.py
CHANGED
|
@@ -98,6 +98,11 @@ class SavedStrategyType:
|
|
| 98 |
reason: str
|
| 99 |
created_at: datetime.datetime
|
| 100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
@strawberry.type
|
| 102 |
class AuthTokenType:
|
| 103 |
access_token: str
|
|
@@ -347,6 +352,20 @@ class Query:
|
|
| 347 |
) for h in local_data
|
| 348 |
]
|
| 349 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 350 |
|
| 351 |
|
| 352 |
# ==========================================
|
|
|
|
| 98 |
reason: str
|
| 99 |
created_at: datetime.datetime
|
| 100 |
|
| 101 |
+
@strawberry.type
|
| 102 |
+
class TrendingTickerType:
|
| 103 |
+
ticker: str
|
| 104 |
+
count: int
|
| 105 |
+
|
| 106 |
@strawberry.type
|
| 107 |
class AuthTokenType:
|
| 108 |
access_token: str
|
|
|
|
| 352 |
) for h in local_data
|
| 353 |
]
|
| 354 |
|
| 355 |
+
@strawberry.field
|
| 356 |
+
async def recently_analyzed(self, info: Info, limit: Optional[int] = 5) -> List[str]:
|
| 357 |
+
"""Fetch the unique tickers the authenticated user has recently analyzed."""
|
| 358 |
+
user = get_authenticated_user(info)
|
| 359 |
+
db = info.context["db"]
|
| 360 |
+
return await crud.get_recently_analyzed_tickers(db, user_id=user.id, limit=limit or 5)
|
| 361 |
+
|
| 362 |
+
@strawberry.field
|
| 363 |
+
async def trending_tickers(self, info: Info, limit: Optional[int] = 5) -> List[TrendingTickerType]:
|
| 364 |
+
"""Fetch the globally trending tickers based on analysis query count in the last 7 days."""
|
| 365 |
+
db = info.context["db"]
|
| 366 |
+
results = await crud.get_trending_tickers(db, limit=limit or 5)
|
| 367 |
+
return [TrendingTickerType(ticker=r["ticker"], count=r["count"]) for r in results]
|
| 368 |
+
|
| 369 |
|
| 370 |
|
| 371 |
# ==========================================
|