You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
5.9 KiB
218 lines
5.9 KiB
# -*- coding: utf-8 -*-
|
|
"""
|
|
===================================
|
|
Market data endpoints
|
|
===================================
|
|
|
|
Responsibilities:
|
|
1. Provide market indices data
|
|
2. Provide sector momentum data
|
|
3. Provide stock momentum recommendations
|
|
4. Provide new high/low stocks
|
|
5. Provide price distribution
|
|
"""
|
|
|
|
import logging
|
|
from datetime import datetime
|
|
from typing import Optional, List
|
|
|
|
from fastapi import APIRouter, Query, Depends
|
|
|
|
from api.v1.schemas.market import (
|
|
MarketIndex,
|
|
UpDownStats,
|
|
SectorMomentum,
|
|
StockMomentum,
|
|
NewHighLowStock,
|
|
PriceDistribution,
|
|
SentimentIndicator,
|
|
MarketOverview,
|
|
SectorListResponse,
|
|
StockMomentumResponse,
|
|
NewHighLowResponse,
|
|
PriceDistributionResponse,
|
|
KLineChartResponse,
|
|
)
|
|
from api.v1.schemas.common import ErrorResponse
|
|
from src.services.market_service import MarketService
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
def get_market_service() -> MarketService:
|
|
"""Dependency injection for MarketService"""
|
|
return MarketService()
|
|
|
|
|
|
@router.get(
|
|
"/indices",
|
|
response_model=List[MarketIndex],
|
|
responses={
|
|
200: {"description": "Market indices data"},
|
|
500: {"description": "Server error", "model": ErrorResponse},
|
|
},
|
|
summary="Get market indices",
|
|
description="Get major market indices (Shanghai, Shenzhen, ChiNext, STAR50)"
|
|
)
|
|
def get_indices(
|
|
service: MarketService = Depends(get_market_service)
|
|
) -> List[MarketIndex]:
|
|
"""
|
|
Get market indices data
|
|
|
|
Returns major market indices including:
|
|
- Shanghai Composite Index (000001.SH)
|
|
- Shenzhen Component Index (399001.SZ)
|
|
- ChiNext Index (399006.SZ)
|
|
- STAR50 Index (000698.SH)
|
|
"""
|
|
try:
|
|
indices = service.get_indices()
|
|
return indices
|
|
except Exception as e:
|
|
logger.error(f"Failed to get market indices: {e}", exc_info=True)
|
|
return []
|
|
|
|
|
|
@router.get(
|
|
"/updown-stats",
|
|
response_model=UpDownStats,
|
|
responses={
|
|
200: {"description": "Up/down statistics"},
|
|
500: {"description": "Server error", "model": ErrorResponse},
|
|
},
|
|
summary="Get up/down statistics",
|
|
description="Get market up/down statistics including limit up/down counts"
|
|
)
|
|
def get_updown_stats(
|
|
service: MarketService = Depends(get_market_service)
|
|
) -> UpDownStats:
|
|
"""
|
|
Get up/down statistics
|
|
|
|
Returns statistics about:
|
|
- Number of rising stocks
|
|
- Number of falling stocks
|
|
- Number of flat stocks
|
|
- Limit up/down counts
|
|
"""
|
|
try:
|
|
stats = service.get_updown_stats()
|
|
return stats
|
|
except Exception as e:
|
|
logger.error(f"Failed to get updown stats: {e}", exc_info=True)
|
|
return UpDownStats(
|
|
up_count=0,
|
|
down_count=0,
|
|
flat_count=0,
|
|
limit_up_count=0,
|
|
limit_down_count=0,
|
|
total_count=0
|
|
)
|
|
|
|
|
|
@router.get(
|
|
"/price-distribution",
|
|
response_model=PriceDistributionResponse,
|
|
responses={
|
|
200: {"description": "Price distribution"},
|
|
500: {"description": "Server error", "model": ErrorResponse},
|
|
},
|
|
summary="Get price distribution",
|
|
description="Get stock price distribution across different price ranges"
|
|
)
|
|
def get_price_distribution(
|
|
service: MarketService = Depends(get_market_service)
|
|
) -> PriceDistributionResponse:
|
|
"""
|
|
Get price distribution
|
|
|
|
Returns distribution of stocks across price ranges:
|
|
- Under 10 yuan
|
|
- 10-20 yuan
|
|
- 20-50 yuan
|
|
- 50-100 yuan
|
|
- Over 100 yuan
|
|
"""
|
|
try:
|
|
distribution = service.get_price_distribution()
|
|
return distribution
|
|
except Exception as e:
|
|
logger.error(f"Failed to get price distribution: {e}", exc_info=True)
|
|
return PriceDistributionResponse(items=[], total_count=0)
|
|
|
|
|
|
@router.get(
|
|
"/overview",
|
|
response_model=MarketOverview,
|
|
responses={
|
|
200: {"description": "Market overview"},
|
|
500: {"description": "Server error", "model": ErrorResponse},
|
|
},
|
|
summary="Get market overview",
|
|
description="Get comprehensive market overview including indices, stats, and sentiment"
|
|
)
|
|
def get_market_overview(
|
|
service: MarketService = Depends(get_market_service)
|
|
) -> MarketOverview:
|
|
"""
|
|
Get market overview
|
|
|
|
Returns comprehensive market data including:
|
|
- Major indices
|
|
- Up/down statistics
|
|
- Sentiment indicators
|
|
"""
|
|
try:
|
|
indices = service.get_indices()
|
|
stats = service.get_updown_stats()
|
|
sentiment = service.get_sentiment_indicators()
|
|
|
|
return MarketOverview(
|
|
indices=indices,
|
|
updown_stats=stats,
|
|
sentiment=sentiment,
|
|
update_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Failed to get market overview: {e}", exc_info=True)
|
|
return MarketOverview(
|
|
indices=[],
|
|
updown_stats=UpDownStats(
|
|
up_count=0, down_count=0, flat_count=0,
|
|
limit_up_count=0, limit_down_count=0, total_count=0
|
|
),
|
|
sentiment=[],
|
|
update_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
)
|
|
|
|
|
|
@router.get(
|
|
"/sentiment",
|
|
response_model=List[SentimentIndicator],
|
|
responses={
|
|
200: {"description": "Sentiment indicators"},
|
|
500: {"description": "Server error", "model": ErrorResponse},
|
|
},
|
|
summary="Get sentiment indicators",
|
|
description="Get market sentiment indicators"
|
|
)
|
|
def get_sentiment(
|
|
service: MarketService = Depends(get_market_service)
|
|
) -> List[SentimentIndicator]:
|
|
"""
|
|
Get sentiment indicators
|
|
|
|
Returns various sentiment data including:
|
|
- Fear & Greed Index
|
|
- Market breadth
|
|
- Volatility index
|
|
"""
|
|
try:
|
|
sentiment = service.get_sentiment_indicators()
|
|
return sentiment
|
|
except Exception as e:
|
|
logger.error(f"Failed to get sentiment: {e}", exc_info=True)
|
|
return [] |