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.

169 lines
7.4 KiB

"""
股票数据路由
"""
from typing import List
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.schemas.base import ResponseModel
from app.schemas.kline import KlineRequest, BatchKlineRequest
from app.services.stock_service import StockService
from app.models.stock_basic import StockBasic
from app.core.security import get_current_user
from app.models.user import User
from app.utils.date_utils import parse_date
router = APIRouter()
@router.get("/kline", response_model=ResponseModel)
async def get_stock_kline(
codes: str = Query(..., description="股票代码,多个用逗号分隔"),
start_date: str = Query(..., description="开始日期(YYYYMMDD)"),
end_date: str = Query(..., description="结束日期(YYYYMMDD)"),
period: str = Query("daily", description="周期: daily, min1, min5, min15, min30, min60"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取股票K线数据含基础信息"""
service = StockService(db)
code_list = [c.strip() for c in codes.split(",")]
start = parse_date(start_date)
end = parse_date(end_date)
kline_data = service.get_kline(code_list, start, end, period)
result = {}
for code in code_list:
stock_basic = db.query(StockBasic).filter(StockBasic.code == code).first()
result[code] = {
"basic": {
"code": stock_basic.code if stock_basic else code,
"name": stock_basic.name if stock_basic else None,
"total_shares": stock_basic.total_shares if stock_basic else None,
"float_shares": stock_basic.float_shares if stock_basic else None,
"industry_index_name": stock_basic.industry_index_name if stock_basic else None,
"industry_index_code": stock_basic.industry_index_code if stock_basic else None,
"institution_hold_ratio": float(stock_basic.institution_hold_ratio) if stock_basic and stock_basic.institution_hold_ratio else None,
"industry_level3": stock_basic.industry_level3 if stock_basic else None,
"list_date": str(stock_basic.list_date) if stock_basic and stock_basic.list_date else None
},
"kline": kline_data.get(code, [])
}
return ResponseModel(data=result)
@router.post("/kline/batch", response_model=ResponseModel)
async def batch_get_stock_kline(
request: BatchKlineRequest,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""批量获取股票K线数据含基础信息"""
service = StockService(db)
start = parse_date(request.start_date)
end = parse_date(request.end_date)
kline_data = service.get_kline(request.codes, start, end, request.period)
result = {}
for code in request.codes:
stock_basic = db.query(StockBasic).filter(StockBasic.code == code).first()
result[code] = {
"basic": {
"code": stock_basic.code if stock_basic else code,
"name": stock_basic.name if stock_basic else None,
"total_shares": stock_basic.total_shares if stock_basic else None,
"float_shares": stock_basic.float_shares if stock_basic else None,
"industry_index_name": stock_basic.industry_index_name if stock_basic else None,
"industry_index_code": stock_basic.industry_index_code if stock_basic else None,
"institution_hold_ratio": float(stock_basic.institution_hold_ratio) if stock_basic and stock_basic.institution_hold_ratio else None,
"industry_level3": stock_basic.industry_level3 if stock_basic else None,
"list_date": str(stock_basic.list_date) if stock_basic and stock_basic.list_date else None
},
"kline": kline_data.get(code, [])
}
return ResponseModel(data=result)
@router.get("/kline/{code}/chart", response_model=ResponseModel)
async def get_stock_kline_chart(
code: str,
start_date: str = Query(..., description="开始日期(YYYYMMDD)"),
end_date: str = Query(..., description="结束日期(YYYYMMDD)"),
period: str = Query("daily", description="周期: daily, min1, min5, min15, min30, min60"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取股票K线图数据ECharts格式含基础信息"""
try:
service = StockService(db)
start = parse_date(start_date)
end = parse_date(end_date)
chart_data = service.get_kline_chart_data(code, start, end, period)
stock_basic = db.query(StockBasic).filter(StockBasic.code == code).first()
chart_data["basic"] = {
"code": stock_basic.code if stock_basic else code,
"name": stock_basic.name if stock_basic else None,
"total_shares": stock_basic.total_shares if stock_basic else None,
"float_shares": stock_basic.float_shares if stock_basic else None,
"industry_index_name": stock_basic.industry_index_name if stock_basic else None,
"industry_index_code": stock_basic.industry_index_code if stock_basic else None,
"institution_hold_ratio": float(stock_basic.institution_hold_ratio) if stock_basic and stock_basic.institution_hold_ratio else None,
"industry_level3": stock_basic.industry_level3 if stock_basic else None,
"list_date": str(stock_basic.list_date) if stock_basic and stock_basic.list_date else None
}
return ResponseModel(data=chart_data)
except ValueError as e:
return ResponseModel(code=400, message=f"参数错误: {str(e)}")
except RuntimeError as e:
return ResponseModel(code=500, message=f"服务错误: {str(e)}")
except Exception as e:
return ResponseModel(code=500, message=f"查询失败: {str(e)}")
@router.get("/basic/{code}", response_model=ResponseModel)
async def get_stock_basic(
code: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取股票基础信息"""
stock_basic = db.query(StockBasic).filter(StockBasic.code == code).first()
if not stock_basic:
return ResponseModel(code=404, message="股票不存在")
return ResponseModel(data={
"code": stock_basic.code,
"name": stock_basic.name,
"total_shares": stock_basic.total_shares,
"float_shares": stock_basic.float_shares,
"industry_index_name": stock_basic.industry_index_name,
"industry_index_code": stock_basic.industry_index_code,
"institution_hold_ratio": float(stock_basic.institution_hold_ratio) if stock_basic.institution_hold_ratio else None,
"industry_level3": stock_basic.industry_level3,
"list_date": str(stock_basic.list_date) if stock_basic.list_date else None
})
@router.get("/snapshot", response_model=ResponseModel)
async def get_stock_snapshot(
codes: str = Query(..., description="股票代码,多个用逗号分隔"),
start_date: str = Query(..., description="开始日期(YYYYMMDD)"),
end_date: str = Query(..., description="结束日期(YYYYMMDD)"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取股票历史快照数据"""
return ResponseModel(data={"message": "功能开发中"})