Go-live gate: refuse unsafe live trading

Setting MODE=live alone no longer starts trading. check_live_ready requires an
active risk limit, MAX_POSITION_PCT < 1.0, LIVE_CONFIRMATION exactly
"I UNDERSTAND THE RISK", a minimum balance, and exchange credentials. Enforced
in Runtime.start_many (both start paths) and surfaced at GET /api/live-check;
the dashboard shows a banner and blocks the start buttons. Adds tests.
This commit is contained in:
matitos committed 2026-09-22 12:55:12 +00:00
1 parent b60cddf13d
commit 0173e46cfb
10 files changed
+241 -1

No files matched your search

+10
View File
@@ -11,6 +11,7 @@ from app.broker import build_broker
from app.broker.base import Broker
from app.config import Settings
from app.engine.engine import TradingEngine
from app.engine.live_guard import check_live_ready
from app.engine.manager import MultiStrategyManager
from app.engine.strategies import get_strategy
from app.market import build_market_data
@@ -129,8 +130,17 @@ class Runtime:
return engine.status() if engine is not None else self._idle_status()
async def start_many(self, request: StartManyRequest) -> MultiStatusOut:
check = check_live_ready(
self.settings,
request.starting_balance or self.settings.starting_balance,
)
if not check.ok:
raise ValueError("live trading blocked: " + "; ".join(check.blockers))
return await self.manager.start(request)
def live_check(self) -> dict:
return check_live_ready(self.settings).as_dict()
async def stop(self) -> StatusOut:
await self.manager.stop()
engine = self.engine