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:
1 parent
b60cddf13d
commit
0173e46cfb
10 files changed
+241
-1
No files matched your search
@@ -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
|
||||
|
||||
Reference in new issue
Block a user