Implements FastAPI backend with ML model support for energy trading, including price prediction models and RL-based battery trading policy. Features dashboard, trading, backtest, and settings API routes with WebSocket support for real-time updates.
109 lines
3.3 KiB
Python
109 lines
3.3 KiB
Python
from typing import List, Optional
|
|
from fastapi import APIRouter, BackgroundTasks, HTTPException
|
|
from datetime import datetime
|
|
from app.models.schemas import (
|
|
BacktestConfig,
|
|
BacktestMetrics,
|
|
BacktestStatusEnum,
|
|
Trade,
|
|
)
|
|
from app.utils.logger import get_logger
|
|
import uuid
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
router = APIRouter()
|
|
|
|
_backtest_store: dict = {}
|
|
_backtest_results: dict = {}
|
|
|
|
|
|
@router.post("/start")
|
|
async def start_backtest(config: BacktestConfig, name: Optional[str] = None):
|
|
backtest_id = str(uuid.uuid4())
|
|
|
|
_backtest_store[backtest_id] = {
|
|
"backtest_id": backtest_id,
|
|
"name": name or f"Backtest {backtest_id[:8]}",
|
|
"status": BacktestStatusEnum.RUNNING,
|
|
"config": config.dict(),
|
|
"created_at": datetime.utcnow(),
|
|
"started_at": datetime.utcnow(),
|
|
"completed_at": None,
|
|
"error_message": None,
|
|
}
|
|
|
|
logger.info(f"Backtest started: {backtest_id}")
|
|
|
|
return {
|
|
"backtest_id": backtest_id,
|
|
"status": BacktestStatusEnum.RUNNING,
|
|
"name": _backtest_store[backtest_id]["name"],
|
|
}
|
|
|
|
|
|
@router.get("/{backtest_id}")
|
|
async def get_backtest_status(backtest_id: str):
|
|
if backtest_id not in _backtest_store:
|
|
raise HTTPException(status_code=404, detail=f"Backtest {backtest_id} not found")
|
|
|
|
backtest = _backtest_store[backtest_id]
|
|
result = _backtest_results.get(backtest_id)
|
|
|
|
return {
|
|
"status": backtest["status"],
|
|
"name": backtest["name"],
|
|
"created_at": backtest["created_at"],
|
|
"started_at": backtest["started_at"],
|
|
"completed_at": backtest["completed_at"],
|
|
"error_message": backtest["error_message"],
|
|
"results": result if backtest["status"] == BacktestStatusEnum.COMPLETED else None,
|
|
}
|
|
|
|
|
|
@router.get("/{backtest_id}/results")
|
|
async def get_backtest_results(backtest_id: str):
|
|
if backtest_id not in _backtest_results:
|
|
raise HTTPException(status_code=404, detail=f"Results for backtest {backtest_id} not found")
|
|
|
|
return _backtest_results[backtest_id]
|
|
|
|
|
|
@router.get("/{backtest_id}/trades")
|
|
async def get_backtest_trades(backtest_id: str, limit: int = 100):
|
|
if backtest_id not in _backtest_store:
|
|
raise HTTPException(status_code=404, detail=f"Backtest {backtest_id} not found")
|
|
|
|
trades = _backtest_results.get(backtest_id, {}).get("trades", [])
|
|
return {"backtest_id": backtest_id, "trades": trades[-limit:], "total": len(trades)}
|
|
|
|
|
|
@router.get("/history")
|
|
async def get_backtest_history():
|
|
backtests = []
|
|
for backtest_id, backtest in _backtest_store.items():
|
|
backtests.append(
|
|
{
|
|
"backtest_id": backtest_id,
|
|
"name": backtest["name"],
|
|
"status": backtest["status"],
|
|
"created_at": backtest["created_at"],
|
|
"completed_at": backtest["completed_at"],
|
|
}
|
|
)
|
|
|
|
return {"backtests": backtests, "total": len(backtests)}
|
|
|
|
|
|
@router.delete("/{backtest_id}")
|
|
async def delete_backtest(backtest_id: str):
|
|
if backtest_id not in _backtest_store:
|
|
raise HTTPException(status_code=404, detail=f"Backtest {backtest_id} not found")
|
|
|
|
del _backtest_store[backtest_id]
|
|
if backtest_id in _backtest_results:
|
|
del _backtest_results[backtest_id]
|
|
|
|
logger.info(f"Backtest deleted: {backtest_id}")
|
|
return {"message": f"Backtest {backtest_id} deleted"}
|