Handling Partial Broker Fills with an Idempotent Callback
Summary
This document explains a strategy lifecycle callback invoked when a broker reports a partial order fill. The callback receives the updated position, order, fill price, newly observed fill quantity, and options multiplier. It can support quantity-sensitive tasks such as incremental hedging.
The example tracks processed quantity by order identifier, adds each new fill delta, and derives the quantity still outstanding from the order size. The later full-fill callback receives the remaining delta, so both callbacks should share the same idempotency state to avoid double processing. The guidance also notes that live callbacks may arrive late or be reconstructed after reconciliation; handlers should be brief and act on the supplied order and quantity rather than depending on a fresh broker query. The document describes API usage, not a trading strategy or performance evidence, and does not specify persistence or recovery details for the tracking state.
Key ideas
- The callback reports the newly observed fill quantity rather than cumulative filled quantity.
- Track processed fill deltas by order identifier to support idempotent handling.
- Use shared state across partial-fill and full-fill callbacks to account for remaining quantity.
- Keep live callback work short and rely on the supplied order and fill data.
Tags
Full text
# lifecycle methods.on partially filled order
def on_partially_filled_order
===================================
.. meta::
:description: The lifecycle callback method called after LumiBot observes a partial broker fill. Use it for quantity-sensitive work such as incremental hedging.
The lifecycle callback method called after LumiBot observes a partial broker
fill. Use it for quantity-sensitive work such as incremental hedging.
Parameters:
position (Position): The updated position after applying this fill
order (Order): The order object that is being processed by the broker
price (float): The filled price
quantity (int): The newly observed fill quantity for this callback, not the cumulative filled quantity
multiplier (int): Options multiplier
.. code-block:: python
class MyStrategy(Strategy):
def on_partially_filled_order(self, position, order, price, quantity, multiplier):
order_id = order.identifier
previously_processed = self.processed_fill_quantity.get(order_id, 0)
self.processed_fill_quantity[order_id] = previously_processed + quantity
missing = order.quantity - self.processed_fill_quantity[order_id]
self.log_message(f"{quantity} has been filled")
self.log_message(f"{quantity} waiting for the remaining {missing}")
The later ``on_filled_order`` callback receives the remaining delta and should
reuse the same idempotency state. Live callbacks may be delayed or reconstructed
after reconciliation; keep the callback short and do not require a fresh broker
read before acting on the supplied order and quantity.
Reference
----------
.. autofunction:: lumibot.strategies.strategy.Strategy.on_partially_filled_orderShown in full with attribution under the source's licence. Licence: GPL-3.0
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.