Hidden liquidity¶
Size a venue will trade that the visible book does not show. An L3 stream records two footprints of it: the refills of an iceberg order, and trades that print inside the visible spread.
See Find hidden liquidity for a worked example and the measured recall and precision, and Glossary: hidden liquidity for the terms.
Iceberg orders¶
detect_icebergs ¶
detect_icebergs(
events: DataFrame,
trades: DataFrame,
*,
max_delay: str | Timedelta = ICEBERG_MAX_DELAY,
) -> IcebergDetection
Find suspected iceberg orders from the refills they leave behind.
A slice is filled out when its last fill as a maker leaves it with nothing outstanding. A refill is the first new order placed at the same side and price at or after that fill, within max_delay, and, at the same instant, after it in event order. When several slices at one price level are filled out together, a new order is matched to the one whose displayed size it equals, and otherwise to the one filled out first. Each order joins at most one refill as the new slice and at most one as the old.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
events
|
DataFrame
|
L3 events with |
required |
trades
|
DataFrame
|
Trades with |
required |
max_delay
|
str or Timedelta
|
Longest wait from a peak being filled to its refill. See
:data: |
ICEBERG_MAX_DELAY
|
Returns:
| Type | Description |
|---|---|
IcebergDetection
|
The suspected icebergs and the slices each one is made of. Both frames are empty, with their columns, when none is found. |
Raises:
| Type | Description |
|---|---|
ConfigError
|
If a required column is missing, or max_delay is negative. |
Trades against hidden orders¶
hidden_trades ¶
Return the trades that printed strictly inside the visible spread.
Each trade is compared with the spread its maker's fill arrived into: the
last quote strictly before the maker event, in the canonical event order
(:func:~ob_analytics.trade_sign.quote_before). The maker event is used
rather than the trade's own timestamp because some feeds report the fill
on the order stream before the trade print arrives, and by the print the
maker has already left the book. The quote written by the fill itself, or
by a later event at the same instant, does not count, so a sweep that
empties a price level does not make its own later prints look inside the
spread. A trade with no maker event is read against the last quote
strictly before its own timestamp.
A trade is kept when that spread can be read
(:func:~ob_analytics.depth.readable_quotes: both sides present and not
crossed) and best_bid_price < price < best_ask_price. An older spread
is not used in place of an unreadable one, because it no longer stood.
The depth summary holds visible orders only, so such a trade executed
against an order the book did not show. A hidden order resting at or
behind the touch is missed: its trades print at a visible price.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
events
|
DataFrame
|
L3 events with |
required |
trades
|
DataFrame
|
Trades with |
required |
depth_summary
|
DataFrame
|
The run's depth summary, with |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
The matching rows of trades, index kept, with the standing
|
Raises:
| Type | Description |
|---|---|
ConfigError
|
If a required column is missing. |
Models¶
IcebergDetection
dataclass
¶
Result of :func:detect_icebergs.
Attributes:
| Name | Type | Description |
|---|---|---|
icebergs |
DataFrame
|
One row per suspected iceberg, in order of
|
slices |
DataFrame
|
One row per visible order in a chain: |