Luno Exchange `watch_order_book` not handling trade updates
Author: badokunCreated Nov 5, 2025Updated Sep 15, 2026
Labelsbugenhancementsuggestion
Operating System
MacOs
Programming Language
Python
CCXT Version
4.5.14
Description
When streaming market data for Luno Exchange, the documentation states that:
"Reduce the outstanding volume of an Order in the Order Book (maker_order_id) and append a Trade to the Trades List."
However the current implementation does not reduce the outstanding volume.
Below is the fix to address this.
def handle_trades(self, client: Client, message, subscription):
#
# {
# "sequence": "110980825",
# "trade_updates": [],
# "create_update": {
# "order_id": "BXHSYXAUMH8C2RW",
# "type": "ASK",
# "price": "24081.09000000",
# "volume": "0.07780000"
# },
# "delete_update": null,
# "status_update": null,
# "timestamp": 1660598775360
# }
#
rawTrades = self.safe_value(message, 'trade_updates', [])
length = len(rawTrades)
if length == 0:
return
symbol = subscription['symbol']
market = self.market(symbol)
messageHash = 'trades:' + symbol
stored = self.safe_value(self.trades, symbol)
if stored is None:
limit = self.safe_integer(self.options, 'tradesLimit', 10000)
stored = ArrayCache(limit)
self.trades[symbol] = stored
for i in range(0, len(rawTrades)):
rawTrade = rawTrades[i]
trade = self.parse_trade(rawTrade, market)
stored.append(trade)
self.trades[symbol] = stored
client.resolve(self.trades[symbol], messageHash)
# FIX: Update orderbook volumes based on trades
if length > 0 and symbol in self.orderbooks:
orderbook = self.orderbooks[symbol]
for trade in rawTrades:
maker_order_id = self.safe_string(trade, 'maker_order_id')
base_volume = self.safe_string(trade, 'base') # Amount traded
if maker_order_id and base_volume:
# Reduce volume in both bids and asks (we don't know which side)
# The storeArray method with volume=0 will delete if volume becomes 0
self._reduce_order_volume(orderbook['bids'], maker_order_id, base_volume)
self._reduce_order_volume(orderbook['asks'], maker_order_id, base_volume)
def _reduce_order_volume(self, order_side, order_id: str, traded_volume: str):
"""
Reduce the volume of an order in the orderbook after a trade.
Args:
order_side: The bids or asks side of the orderbook
order_id: The maker order ID that was traded
traded_volume: The volume that was traded (as string)
"""
# Find the order by ID
for i in range(len(order_side)):
order = order_side[i]
if len(order) >= 3 and order[2] == order_id:
# Found the order: [price, volume, id]
current_volume = decimal.Decimal(str(order[1]))
trade_volume = decimal.Decimal(traded_volume)
new_volume = current_volume - trade_volume
if new_volume <= 0:
# Order fully filled - delete it
order_side.storeArray([order[0], 0, order_id])
else:
# Order partially filled - update volume
order_side.storeArray([order[0], float(new_volume), order_id])
break # Found and updated, exit loopSource: ccxt/ccxt