feat: add backtest progress tracking and fix stop functionality
This commit is contained in:
@@ -169,6 +169,11 @@ def get_backtest(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Backtest not found"
|
||||
)
|
||||
|
||||
# Add progress from running engine if available
|
||||
if backtest.status == "running" and run_id in running_backtests:
|
||||
engine = running_backtests[run_id]
|
||||
backtest.progress = engine.progress
|
||||
|
||||
return backtest
|
||||
|
||||
|
||||
@@ -226,7 +231,12 @@ def stop_backtest(
|
||||
|
||||
if run_id in running_backtests:
|
||||
engine = running_backtests[run_id]
|
||||
asyncio.create_task(engine.stop())
|
||||
engine.running = False # Direct sync access to running flag
|
||||
backtest.status = "stopped"
|
||||
backtest.ended_at = datetime.utcnow()
|
||||
db.commit()
|
||||
elif backtest.status == "running":
|
||||
# Engine already finished but status not updated
|
||||
backtest.status = "stopped"
|
||||
backtest.ended_at = datetime.utcnow()
|
||||
db.commit()
|
||||
|
||||
@@ -90,6 +90,7 @@ class BacktestResponse(BaseModel):
|
||||
status: str
|
||||
config: dict
|
||||
result: Optional[dict]
|
||||
progress: Optional[int] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
@@ -31,6 +31,8 @@ class BacktestEngine:
|
||||
self.entry_time: Optional[int] = None
|
||||
self.trades: List[Dict[str, Any]] = []
|
||||
self.running = False
|
||||
self.progress = 0
|
||||
self.total_klines = 0
|
||||
|
||||
async def run(self) -> Dict[str, Any]:
|
||||
self.running = True
|
||||
@@ -98,10 +100,13 @@ class BacktestEngine:
|
||||
return self.results
|
||||
|
||||
async def _process_klines(self, klines: List[Dict[str, Any]]):
|
||||
self.total_klines = len(klines)
|
||||
for i, kline in enumerate(klines):
|
||||
if not self.running:
|
||||
break
|
||||
|
||||
self.progress = int((i / self.total_klines) * 100) if self.total_klines > 0 else 0
|
||||
|
||||
price = float(kline.get("close", 0))
|
||||
if price <= 0:
|
||||
continue
|
||||
@@ -384,6 +389,8 @@ class BacktestEngine:
|
||||
|
||||
async def stop(self):
|
||||
self.running = False
|
||||
self.progress = 0
|
||||
self.total_klines = 0
|
||||
self.status = "stopped"
|
||||
self._calculate_metrics()
|
||||
|
||||
@@ -393,4 +400,13 @@ class BacktestEngine:
|
||||
"status": self.status,
|
||||
"results": self.results,
|
||||
"signals": self.signals,
|
||||
"progress": self.progress,
|
||||
"total_klines": self.total_klines,
|
||||
}
|
||||
|
||||
def get_status(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"status": self.status,
|
||||
"progress": self.progress,
|
||||
"total_klines": self.total_klines,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user