bf57aed17a
- git mv sanguo_web → _retired/sanguo_web/(git 历史保全+墓碑 README:
归档原因/拍板记录/现役=sanguo_api)
- 退出启动面三处: promote.sh ALL_MODS 白名单(15→14 模块)+docker/Dockerfile:63
COPY+docker/Dockerfile.nas:16 COPY——不可再被部署或启动为服务
- 背景(架构审计 P0-3): 硬编码 SECRET_KEY/admin123 默认口令/CORS 全开/可下
真实订单/零测试/与 sanguo_api 路由冲突; 生产从未部署为服务, 纯误启动风险
(README 旧「生产模式 uvicorn sanguo_web」指引已于 f6ca85e 勘误)
- three-env §3.1 模块清单+§12 矩阵行同步; session-guide §5 角色表前端行
勘误(旧表把 sanguo_web 当前端模块推——实为 legacy 后端, 前端=frontend/)
- 零外部 import(runuweb/tests/packages 全 grep 实证), pytest testpaths=tests
不受影响
Co-Authored-By: Claude Code <notify@anthropic.com>
163 lines
4.5 KiB
Python
163 lines
4.5 KiB
Python
"""
|
||
成交监控路由
|
||
处理成交记录查询
|
||
"""
|
||
from fastapi import APIRouter, Depends, HTTPException, status
|
||
from typing import List, Optional
|
||
from datetime import datetime
|
||
import logging
|
||
|
||
from ..deps import get_current_user, get_vn_service
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
router = APIRouter()
|
||
|
||
|
||
@router.get("/", response_model=List[dict])
|
||
async def get_all_trades(
|
||
current_user: dict = Depends(get_current_user),
|
||
vn_service=Depends(get_vn_service)
|
||
):
|
||
"""
|
||
获取所有成交记录
|
||
|
||
返回所有成交记录,包括成交号、委托号、合约代码、方向、开平、价格、数量、时间等信息
|
||
"""
|
||
trades = await vn_service.get_trades()
|
||
|
||
return [
|
||
{
|
||
"tradeid": t.get("trade_id", ""),
|
||
"orderid": t.get("order_id", ""),
|
||
"symbol": t.get("symbol", ""),
|
||
"exchange": t.get("exchange", ""),
|
||
"direction": t.get("direction", ""),
|
||
"offset": t.get("offset", ""),
|
||
"price": t.get("price", 0.0),
|
||
"volume": t.get("volume", 0),
|
||
"datetime": _format_datetime(t.get("time")),
|
||
"gateway_name": t.get("gateway_name", ""),
|
||
}
|
||
for t in trades
|
||
]
|
||
|
||
|
||
@router.get("/latest", response_model=List[dict])
|
||
async def get_latest_trades(
|
||
limit: int = 50,
|
||
current_user: dict = Depends(get_current_user),
|
||
vn_service=Depends(get_vn_service)
|
||
):
|
||
"""
|
||
获取最新的成交记录
|
||
|
||
- **limit**: 返回记录数量,默认 50 条
|
||
"""
|
||
trades = await vn_service.get_trades()
|
||
|
||
# 按时间降序排序,取最新的 limit 条
|
||
sorted_trades = sorted(
|
||
trades,
|
||
key=lambda x: x.get("time", datetime.min),
|
||
reverse=True
|
||
)[:limit]
|
||
|
||
return [
|
||
{
|
||
"tradeid": t.get("trade_id", ""),
|
||
"orderid": t.get("order_id", ""),
|
||
"symbol": t.get("symbol", ""),
|
||
"exchange": t.get("exchange", ""),
|
||
"direction": t.get("direction", ""),
|
||
"offset": t.get("offset", ""),
|
||
"price": t.get("price", 0.0),
|
||
"volume": t.get("volume", 0),
|
||
"datetime": _format_datetime(t.get("time")),
|
||
"gateway_name": t.get("gateway_name", ""),
|
||
}
|
||
for t in sorted_trades
|
||
]
|
||
|
||
|
||
@router.get("/order/{vt_orderid}", response_model=List[dict])
|
||
async def get_trades_by_order(
|
||
vt_orderid: str,
|
||
current_user: dict = Depends(get_current_user),
|
||
vn_service=Depends(get_vn_service)
|
||
):
|
||
"""
|
||
获取指定委托的所有成交记录
|
||
|
||
- **vt_orderid**: 委托号(格式:gateway_name.orderid)
|
||
"""
|
||
all_trades = await vn_service.get_trades()
|
||
|
||
filtered_trades = [
|
||
t for t in all_trades
|
||
if t.get("order_id", "") == vt_orderid
|
||
]
|
||
|
||
return [
|
||
{
|
||
"tradeid": t.get("trade_id", ""),
|
||
"orderid": t.get("order_id", ""),
|
||
"symbol": t.get("symbol", ""),
|
||
"exchange": t.get("exchange", ""),
|
||
"direction": t.get("direction", ""),
|
||
"offset": t.get("offset", ""),
|
||
"price": t.get("price", 0.0),
|
||
"volume": t.get("volume", 0),
|
||
"datetime": _format_datetime(t.get("time")),
|
||
"gateway_name": t.get("gateway_name", ""),
|
||
}
|
||
for t in filtered_trades
|
||
]
|
||
|
||
|
||
@router.get("/symbol/{symbol}", response_model=List[dict])
|
||
async def get_trades_by_symbol(
|
||
symbol: str,
|
||
current_user: dict = Depends(get_current_user),
|
||
vn_service=Depends(get_vn_service)
|
||
):
|
||
"""
|
||
获取指定合约的所有成交记录
|
||
|
||
- **symbol**: 合约代码
|
||
"""
|
||
all_trades = await vn_service.get_trades()
|
||
|
||
filtered_trades = [
|
||
t for t in all_trades
|
||
if t.get("symbol", "") == symbol
|
||
]
|
||
|
||
return [
|
||
{
|
||
"tradeid": t.get("trade_id", ""),
|
||
"orderid": t.get("order_id", ""),
|
||
"symbol": t.get("symbol", ""),
|
||
"exchange": t.get("exchange", ""),
|
||
"direction": t.get("direction", ""),
|
||
"offset": t.get("offset", ""),
|
||
"price": t.get("price", 0.0),
|
||
"volume": t.get("volume", 0),
|
||
"datetime": _format_datetime(t.get("time")),
|
||
"gateway_name": t.get("gateway_name", ""),
|
||
}
|
||
for t in filtered_trades
|
||
]
|
||
|
||
|
||
def _format_datetime(dt: Optional[datetime]) -> str:
|
||
"""格式化 datetime 对象为字符串"""
|
||
if dt is None:
|
||
return ""
|
||
if isinstance(dt, datetime):
|
||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||
return str(dt)
|
||
|
||
|
||
__all__ = ["router"]
|