Add SIM/LIVE switch with API keys saved to .env and OKX live executor.
Enable settings UI for mode/keys, gate strategy start when LIVE is not ready, and stop PM2 from forcing MODE=SIM. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -11,7 +11,8 @@ from ..config import get_settings
|
||||
from .session import get_session
|
||||
from ..models.db import get_db
|
||||
from ..sim.ledger import Ledger
|
||||
from ..sim.matcher import Matcher
|
||||
from ..live import get_executor
|
||||
from ..env_store import live_ready
|
||||
from .clock import can_open_new, window_key
|
||||
from .exits import check_expiry_close, check_exits, resolve_exit_target
|
||||
from .group import next_group_id
|
||||
@@ -22,11 +23,15 @@ logger = logging.getLogger(__name__)
|
||||
class StrategyEngine:
|
||||
def __init__(self) -> None:
|
||||
self.db = get_db()
|
||||
self.matcher = Matcher(self.db)
|
||||
self.ledger = Ledger(self.db)
|
||||
self.matcher = get_executor(self.db)
|
||||
self._task: asyncio.Task[None] | None = None
|
||||
self._lock = asyncio.Lock()
|
||||
|
||||
def refresh_executor(self) -> None:
|
||||
"""MODE 变更后刷新执行器。"""
|
||||
self.matcher = get_executor(self.db)
|
||||
|
||||
def state(self) -> dict[str, Any]:
|
||||
row = self.db.fetchone("SELECT * FROM strategy_state WHERE id=1")
|
||||
assert row is not None
|
||||
@@ -90,6 +95,10 @@ class StrategyEngine:
|
||||
"position": upl,
|
||||
"residuals": self.matcher.list_residual_options(pending_only=True),
|
||||
"ledger": self.ledger.snapshot(),
|
||||
"mode": "SIM" if s.is_sim else "LIVE",
|
||||
"sim": s.is_sim,
|
||||
"live_ready": (live_ready()[0] if not s.is_sim else True),
|
||||
"live_ready_reason": (live_ready()[1] if not s.is_sim else "sim"),
|
||||
}
|
||||
|
||||
def _set_state(self, **kwargs: Any) -> None:
|
||||
@@ -108,6 +117,13 @@ class StrategyEngine:
|
||||
return self.state()
|
||||
|
||||
async def start(self) -> dict[str, Any]:
|
||||
self.refresh_executor()
|
||||
s = get_settings()
|
||||
if not s.is_sim:
|
||||
ok, reason = live_ready()
|
||||
if not ok:
|
||||
self._set_state(running=0, phase="paused", last_error=reason)
|
||||
return self.state()
|
||||
self._set_state(running=1, last_error=None, phase="idle")
|
||||
self.ensure_loop()
|
||||
return self.state()
|
||||
|
||||
Reference in New Issue
Block a user