fix: redesign relative rotation for multi-symbol comparison

- Accept comma-separated symbols query param instead of single path param
- Move endpoint from /stock/{symbol}/technical/relative-rotation to
  /technical/relative-rotation?symbols=AAPL,MSFT,GOOGL&benchmark=SPY
- Fetch all symbols + benchmark in single obb.equity.price.historical call
- Add RRG quadrant classification (Leading/Weakening/Lagging/Improving)
- Support study parameter (price/volume/volatility)
This commit is contained in:
Yaojia Wang
2026-03-19 17:34:18 +01:00
parent 615f17a3bb
commit e2cf6e2488
2 changed files with 66 additions and 14 deletions

View File

@@ -164,14 +164,23 @@ async def stock_vwap(symbol: str = Path(..., min_length=1, max_length=20)):
return ApiResponse(data=data)
@router.get("/stock/{symbol}/technical/relative-rotation", response_model=ApiResponse)
@router.get("/technical/relative-rotation", response_model=ApiResponse)
@safe
async def stock_relative_rotation(
symbol: str = Path(..., min_length=1, max_length=20),
async def relative_rotation(
symbols: str = Query(..., min_length=1, max_length=200, description="Comma-separated symbols, e.g. AAPL,MSFT,GOOGL"),
benchmark: str = Query(default="SPY", min_length=1, max_length=20),
study: str = Query(default="price", pattern="^(price|volume|volatility)$"),
):
"""Relative Rotation -- strength vs benchmark (sector rotation analysis)."""
symbol = validate_symbol(symbol)
"""Relative Rotation Graph -- compare multiple symbols vs benchmark.
Returns RS-Ratio and RS-Momentum for each symbol, indicating
RRG quadrant: Leading, Weakening, Lagging, or Improving.
"""
symbol_list = [validate_symbol(s.strip()) for s in symbols.split(",") if s.strip()]
if not symbol_list:
return ApiResponse(data=[], error="No valid symbols provided")
benchmark = validate_symbol(benchmark)
data = await technical_service.get_relative_rotation(symbol, benchmark=benchmark)
data = await technical_service.get_relative_rotation(
symbol_list, benchmark=benchmark, study=study,
)
return ApiResponse(data=data)