From 26926943094cb2d5aa99ff7d02fd17b71fb14dfb Mon Sep 17 00:00:00 2001 From: direkturcrypto Date: Tue, 24 Feb 2026 14:07:13 +0700 Subject: [PATCH] =?UTF-8?q?fix(oneshot):=20add=20global=20position=20limit?= =?UTF-8?q?=20=E2=80=94=20no=20new=20entry=20while=20any=20position=20is?= =?UTF-8?q?=20open?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the per-market state machine check (sm.is(IDLE)) only blocked re-entry on the same slug. A fresh market slot (different slug) would get its own IDLE state machine and could trigger another entry while the previous market's position was still being held. Added posEngine.hasAnyPosition() global guard in onSignal so the engine holds exactly one position at a time across all tracked markets. Co-Authored-By: Claude Sonnet 4.6 --- src/oneshot.js | 7 +++++++ src/oneshot/PositionEngine.js | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/src/oneshot.js b/src/oneshot.js index 652a387..d9189f9 100644 --- a/src/oneshot.js +++ b/src/oneshot.js @@ -175,6 +175,13 @@ async function onSignal(evt) { // Only enter from IDLE — one position per market slot if (!sm.is(State.IDLE)) return; + // Global position limit: never open a new position while any other market + // is still being held. The engine is designed to focus on one bet at a time. + if (posEngine.hasAnyPosition()) { + dbg('SIGNAL', `${marketSlug} | blocked — position already open in another market`); + return; + } + // ── Risk gate ───────────────────────────────────────────────────────── const riskCheck = riskEngine.canTrade(); diff --git a/src/oneshot/PositionEngine.js b/src/oneshot/PositionEngine.js index bbad5a3..912f23a 100644 --- a/src/oneshot/PositionEngine.js +++ b/src/oneshot/PositionEngine.js @@ -68,6 +68,11 @@ export class PositionEngine { return this._positions.has(marketSlug); } + /** True if ANY position is open across all tracked markets */ + hasAnyPosition() { + return this._positions.size > 0; + } + /** * Close the position actively (adverse-move emergency exit) and return exit data. *