Files
sanguo_vnpy_v2/sanguo_web/api/routes/market.py
T
claude_dev 918bbed0fc fix: 修复登录500错误和移除明文密码提示
- 修复 deps.py 中 get_vn_service 的引用错误 (vn_service.vn_service -> vn_service)
- 移除登录页面上的明文密码提示
- 改进前端错误处理,避免数据加载失败导致登录显示错误
2026-07-02 12:23:55 +08:00

177 lines
4.5 KiB
Python

"""
行情数据路由
处理行情数据查询和订阅
"""
from fastapi import APIRouter, Depends, Query, HTTPException, status
from typing import List, Optional
import logging
from ..models import (
TickData, KlineRequest, KlineData, SubscribeRequest, UnsubscribeRequest, ApiResponse
)
from ..deps import get_current_user, get_vn_service
logger = logging.getLogger(__name__)
router = APIRouter()
@router.get("/contracts")
async def get_contracts(
current_user: dict = Depends(get_current_user),
vn_service=Depends(get_vn_service)
):
"""
获取所有合约列表
返回系统中所有已知的合约信息
"""
contracts = await vn_service.get_contracts()
return {
"contracts": contracts,
"total": len(contracts)
}
@router.get("/contracts/{vt_symbol}")
async def get_contract(
vt_symbol: str,
current_user: dict = Depends(get_current_user),
vn_service=Depends(get_vn_service)
):
"""
获取单个合约详情
- **vt_symbol**: 合约代码 (格式: symbol.exchange)
"""
contract = await vn_service.get_contract(vt_symbol)
if not contract:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Contract {vt_symbol} not found"
)
return contract
@router.post("/subscribe")
async def subscribe_market(
request: SubscribeRequest,
current_user: dict = Depends(get_current_user),
vn_service=Depends(get_vn_service)
):
"""
订阅行情
- **symbol**: 品种代码
- **exchange**: 交易所
- **gateway_name**: 网关名称(可选)
"""
success = await vn_service.subscribe(
symbol=request.symbol,
exchange=request.exchange,
gateway_name=request.gateway_name
)
if success:
return ApiResponse(
success=True,
message=f"Subscribed to {request.symbol}.{request.exchange}"
)
else:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to subscribe to {request.symbol}.{request.exchange}"
)
@router.post("/unsubscribe")
async def unsubscribe_market(
request: UnsubscribeRequest,
current_user: dict = Depends(get_current_user),
vn_service=Depends(get_vn_service)
):
"""
取消订阅行情
- **symbol**: 品种代码
- **exchange**: 交易所
- **gateway_name**: 网关名称(可选)
"""
success = await vn_service.unsubscribe(
symbol=request.symbol,
exchange=request.exchange,
gateway_name=request.gateway_name
)
if success:
return ApiResponse(
success=True,
message=f"Unsubscribed from {request.symbol}.{request.exchange}"
)
else:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to unsubscribe from {request.symbol}.{request.exchange}"
)
@router.get("/ticks")
async def get_all_ticks(
symbols: Optional[str] = Query(None, description="品种代码,逗号分隔"),
current_user: dict = Depends(get_current_user),
vn_service=Depends(get_vn_service)
):
"""
获取当前行情缓存
- **symbols**: 可选,过滤特定品种
"""
symbol_list = symbols.split(",") if symbols else None
ticks = await vn_service.get_ticks(symbol_list)
return {
"ticks": ticks,
"total": len(ticks)
}
@router.get("/ticks/{vt_symbol}")
async def get_tick(
vt_symbol: str,
current_user: dict = Depends(get_current_user),
vn_service=Depends(get_vn_service)
):
"""
获取指定合约行情
- **vt_symbol**: 合约代码 (格式: symbol.exchange)
"""
ticks = await vn_service.get_ticks([vt_symbol])
if not ticks:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No tick data for {vt_symbol}"
)
return ticks[0]
@router.post("/kline", response_model=List[KlineData])
async def get_kline_data(
request: KlineRequest,
current_user: dict = Depends(get_current_user),
vn_service=Depends(get_vn_service)
):
"""
获取 K线数据
- **symbol**: 品种代码
- **exchange**: 交易所
- **interval**: 周期 (1m, 5m, 15m, 1h, 4h, 1d)
- **start**: 开始时间(可选)
- **end**: 结束时间(可选)
- **limit**: 数据条数限制
"""
# 占位实现,实际应从数据库获取
logger.info(f"Kline request: {request.symbol}.{request.exchange} {request.interval}")
return []