feat(frontend): 添加交易看板,统一时区为CST
refactor(db): 移除所有SQLite相关代码,迁移至MySQL
This commit is contained in:
1 parent
5e0d6b18ef
commit
55453d3739
12 files changed
+2116
-501
No files matched your search
+191
@@ -0,0 +1,191 @@
|
||||
"""
|
||||
FastAPI 主应用 - 交易看板 API
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from fastapi import FastAPI, Query, HTTPException
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
# 添加项目路径
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from api.models import TradeModel, PredictionModel
|
||||
from api.prediction_service import get_prediction_service
|
||||
|
||||
# 创建 FastAPI 应用
|
||||
app = FastAPI(
|
||||
title="Crypto Predictor Dashboard API",
|
||||
description="BTC 预测交易看板 API",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
# 启用 CORS
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# 静态文件目录
|
||||
STATIC_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static')
|
||||
|
||||
# 挂载静态文件
|
||||
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
|
||||
|
||||
|
||||
# ==================== 页面路由 ====================
|
||||
|
||||
@app.get("/")
|
||||
async def index():
|
||||
"""返回主页"""
|
||||
return FileResponse(os.path.join(STATIC_DIR, 'index.html'))
|
||||
|
||||
|
||||
# ==================== 交易 API ====================
|
||||
|
||||
@app.get("/api/trades/current")
|
||||
async def get_current_trade():
|
||||
"""获取当前/最新交易"""
|
||||
try:
|
||||
trade = TradeModel.get_current_trade()
|
||||
if trade:
|
||||
return {"success": True, "data": trade}
|
||||
return {"success": True, "data": None, "message": "暂无交易记录"}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@app.get("/api/trades/history")
|
||||
async def get_trade_history(
|
||||
page: int = Query(1, ge=1, description="页码"),
|
||||
limit: int = Query(10, ge=1, le=100, description="每页条数"),
|
||||
month: Optional[str] = Query(None, description="月份筛选 (YYYY-MM)"),
|
||||
day: Optional[str] = Query(None, description="日期筛选 (YYYY-MM-DD)")
|
||||
):
|
||||
"""获取历史交易记录"""
|
||||
try:
|
||||
result = TradeModel.get_history(page=page, limit=limit, month=month, day=day)
|
||||
return {"success": True, **result}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
# ==================== 准确率 API ====================
|
||||
|
||||
@app.get("/api/accuracy/current")
|
||||
async def get_current_prediction():
|
||||
"""获取当前小时的预测"""
|
||||
try:
|
||||
service = get_prediction_service()
|
||||
prediction = service.predict_current_hour()
|
||||
return {"success": True, "data": prediction}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@app.get("/api/accuracy/monthly")
|
||||
async def get_monthly_accuracy(
|
||||
month: Optional[str] = Query(None, description="月份 (YYYY-MM),默认当月")
|
||||
):
|
||||
"""获取月度准确率统计"""
|
||||
try:
|
||||
# 默认当月
|
||||
if not month:
|
||||
et_tz = ZoneInfo('America/New_York')
|
||||
month = datetime.now(et_tz).strftime('%Y-%m')
|
||||
|
||||
# 确保有数据
|
||||
service = get_prediction_service()
|
||||
service.ensure_predictions_for_month(month)
|
||||
|
||||
# 获取统计
|
||||
stats = PredictionModel.get_monthly_stats(month)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"month": month,
|
||||
"data": stats
|
||||
}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@app.get("/api/accuracy/daily")
|
||||
async def get_daily_accuracy(
|
||||
month: Optional[str] = Query(None, description="月份 (YYYY-MM),默认当月"),
|
||||
page: int = Query(1, ge=1, description="页码"),
|
||||
limit: int = Query(10, ge=1, le=100, description="每页条数")
|
||||
):
|
||||
"""获取每日准确率统计"""
|
||||
try:
|
||||
# 默认当月
|
||||
if not month:
|
||||
et_tz = ZoneInfo('America/New_York')
|
||||
month = datetime.now(et_tz).strftime('%Y-%m')
|
||||
|
||||
# 确保有数据
|
||||
service = get_prediction_service()
|
||||
service.ensure_predictions_for_month(month)
|
||||
|
||||
# 获取统计
|
||||
result = PredictionModel.get_daily_stats(month=month, page=page, limit=limit)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"month": month,
|
||||
**result
|
||||
}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@app.get("/api/accuracy/hourly/{date}")
|
||||
async def get_hourly_accuracy(date: str):
|
||||
"""获取指定日期的每小时准确率详情"""
|
||||
try:
|
||||
# 确保有数据
|
||||
service = get_prediction_service()
|
||||
service.ensure_predictions_for_date(date)
|
||||
|
||||
# 获取详情
|
||||
details = PredictionModel.get_hourly_details(date)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"date": date,
|
||||
"data": details
|
||||
}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
# ==================== 状态 API ====================
|
||||
|
||||
@app.get("/api/status")
|
||||
async def get_status():
|
||||
"""获取服务状态"""
|
||||
et_tz = ZoneInfo('America/New_York')
|
||||
now_et = datetime.now(et_tz)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"status": "running",
|
||||
"server_time": datetime.now().isoformat(),
|
||||
"server_time_et": now_et.isoformat(),
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
||||
|
||||
# ==================== 启动入口 ====================
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
Reference in new issue
Block a user