Skip to main content
Position handover is what happens when an executor ends without closing its position. The executor terminates with close type POSITION_HOLD, and the Hummingbot API adds its fills to the Position Hold for the executor’s account, connector, trading pair and controller_id. The tokens stay in the account, and an agent can manage the position later with a new executor.

When an executor hands over

A handover happens only when an executor ends with POSITION_HOLD. keep_position is a config field on two executors only, the grid and the LP executor. For every type it is also a parameter of the stop call. When you stop an executor, the keep_position you pass with the stop decides. A grid’s or LP executor’s config value applies only when the executor closes itself. If there turns out to be nothing to hold (the entry never filled), the executor ends as EARLY_STOP instead.

Executors whose holds are not recorded

The DCA, TWAP, XEMM and arbitrage executors don’t hand over to the Position Hold:
  • DCA, XEMM and arbitrage: a stop with keep_position=true ends them as POSITION_HOLD and leaves the fills in the account, but the current Hummingbot API doesn’t record those fills in the Position Hold.
  • TWAP: a stopped TWAP always ends as COMPLETED, so nothing is handed over.
Anything they leave in the account is invisible to list_positions_held and to an agent’s held positions. Track it yourself.

What gets recorded

For each handover, the API adds the executor’s filled orders to the Position Hold keyed by:
Buys and sells are added separately. When a hold has both, the matched amount becomes realized P&L and only the unmatched amount stays open. See Inventory for the fields and the P&L arithmetic. For an LP executor the connector is the network, such as solana-mainnet-beta, and the executor records one net trade for the whole position. See LP Executor.

Held positions belong to one session

The controller_id in the key is the agent session’s ID, such as my_agent.my_loop_3. So:
  • On each tick, the agent sees the held positions for its own session ID only.
  • A new session of the same loop has a new ID, and can’t see what an earlier session held.
Before you stop a loop that holds positions, close them or decide to manage them by hand. Held positions are not adopted by the next session; see Executors left by a stopped session.

Example: a grid that crosses its limit price

An agent runs a long grid that holds what it bought if SOL falls through 138:
  1. SOL falls to 138. The grid cancels its open orders and ends as POSITION_HOLD.
  2. The SOL it bought and hadn’t sold yet is added to the Position Hold for (master_account, binance, SOL-USDT, my_agent.my_loop_3).
  3. On the next tick, the agent sees the held SOL with its breakeven price.
  4. When it decides to exit, it sells with an order executor under the same controller_id:
When the sell fills, the order executor hands it over too. It nets against the held buys in the same Position Hold, and the matched amount becomes realized P&L.

Positions add up

Every handover under the same key adds to one position:

Clearing a held position

If a held position was closed somewhere else, such as on the exchange’s own site, clear the record with clear_position_held or DELETE /executors/positions/{connector_name}/{trading_pair}. Pass the position’s controller_id and account_name: they default to main and master_account. This changes only the record; it moves no funds. To close a position that is still open, trade it with an executor.