fix(executors): clear phantom spot hold left by a fully-unwound LP position - #197
fix(executors): clear phantom spot hold left by a fully-unwound LP position#197fengtality wants to merge 1 commit into
Conversation
…P position An LP slot's base is bought by an entry order_executor (stopped with keep_position=True, which records a PositionHold) and then deposited into the pool. Neither the add-liquidity deposit nor the mostly-quote withdrawal is a swap fill, so that hold's net_amount_base never comes back down: it lingers as a phantom long after the position is closed on-chain. positions/summary then reports a closed LP position as open indefinitely, which drives false "stranded position" shutdown alarms and an over-stated restart guard. Regular buy/sell executors (spot/perp/grid/dca) are unaffected — their every disposal is a recorded sell fill, so the ledger nets correctly. The gap is specific to LP liquidity add/remove being invisible to a fill-based ledger. Fix: when an lp_executor completes a clean keep_position=False close (the base is gone, returned as quote), clear its position hold by (account, connector, pair, controller) key in _handle_executor_completion. Restrict to a clean close: a FAILED open never deposited into the pool and leaves the swapped base in the wallet as a real spot position (must NOT be cleared); POSITION_HOLD (keep_position=True) still aggregates as before. Verified live: three LP slots opened and shut down; all three holds went to CLEARED, positions/summary returned empty, and the shutdown reconciler reported verify=flat instead of the prior false "left 3 positions OPEN" alarm. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9Vygff6wPFpmZb5gahuW4
|
PR update:
|
|
Closing — this was fixing the wrong layer. @Reviewer's finding is correct and the cause is more fundamental than the scoping bug: But scoping the clear per-executor would still have been wrong, because the phantom it was clearing shouldn't exist in the first place. Root cause, in hummingbot, not here. hummingbot commit The LP round trip is the executor's to undo; the base it was handed is not. Restoring the net-based close-out makes the LP executor position-neutral, keeps the entry executor's hold accurate, and needs no LP-specific hold logic in hummingbot-api at all. Fixed in hummingbot instead ( Thanks for catching it. |
Problem
An LP slot's base is bought by an entry
order_executor(stopped withkeep_position=True, which records aPositionHold) and then deposited into the pool. Neither the add-liquidity deposit nor the mostly-quote withdrawal is a swap fill, so that hold'snet_amount_basenever comes back down — it lingers as a phantom long after the position is closed on-chain.GET /executors/positions/summarythen reports a closed LP position as open indefinitely. Observed downstream effects:flatten_all, treats every phantom as stranded). In one run a position closed an hour earlier still showed up./stop.Regular buy/sell executors (spot/perp/grid/dca) are unaffected: every disposal is a recorded sell fill, so the ledger nets correctly. The gap is specific to LP liquidity add/remove being invisible to a fill-based ledger.
Fix
When an
lp_executorcompletes a cleankeep_position=Falseclose (the base is gone, returned as quote), clear its position hold by(account, connector, pair, controller)key in_handle_executor_completion.Guards:
FAILEDopen never deposited into the pool and leaves the swapped base in the wallet as a real spot position → not cleared.POSITION_HOLD(keep_position=True) still aggregates as before.Tests
test/test_position_hold_lp_clear.py(4 cases): clean unwind clears, FAILED keeps, POSITION_HOLD aggregates (not clears), non-LP executor untouched.Verified live
Three LP slots opened and shut down: all three holds went to
CLEARED,positions/summaryreturned empty, and the shutdown reconciler reportedverify=flatinstead of the prior false "left 3 positions OPEN" alarm. The same scenario on the unpatched build produced the false alarm.🤖 Generated with Claude Code