fix(oneshot): add global position limit — no new entry while any position is open
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user