Builtins: level 3 individual orders

Market by order: every resting order whose life overlapped the bar, each one seen exactly as it stood at the end of that bar. Nothing the order did later leaks into an earlier bar, so a bar at 09:31 never knows what the order became at 15:59.

SignatureReturns
mbo.supported() -> boolWhether order level data is wired on this chart
mbo.available() -> boolWhether this bar carries orders
mbo.count() -> intHow many orders overlapped the bar, 0 without data
mbo.order_id(index: int) -> stringThe exchange order id, empty when out of range
mbo.side(index: int) -> sideBUY for a resting bid, SELL for a resting offer
mbo.price(index: int) -> floatIts resting price at the end of the bar
mbo.size(index: int) -> floatIts displayed size at the end of the bar
mbo.peak_size(index: int) -> floatThe largest size it had shown so far
mbo.filled(index: int) -> floatHow much of it had traded so far
mbo.refills(index: int) -> floatHow many times its size grew back at the same price so far
mbo.first_time(index: int) -> floatWhen it was first seen, epoch milliseconds
mbo.last_time(index: int) -> floatIts last change seen so far
mbo.status(index: int) -> string"active" while it rests, "executed" or "cancelled" once it ended inside the bar
mbo.largest_index() -> intIndex of the largest displayed order on the bar, or -1
mbo.largest_size() -> floatIts size
mbo.bid_size_total() -> floatTotal displayed size of the resting bids
mbo.ask_size_total() -> floatTotal displayed size of the resting offers
mbo.iceberg_count(min_refills: float) -> intHow many orders on the bar were refilled at least min_refills times

Order events

Every change to an order stamped inside the bar, oldest first: when it was placed, when its price or size changed, each fill and its cancel. This is the stream to read when the question is what happened during the bar, such as how much size was pulled from the bid.

SignatureReturns
mbo.event_count() -> intHow many events happened inside the bar, 0 without data
mbo.event_type(index: int) -> string"add", "modify", "fill" or "cancel", empty when out of range
mbo.event_price(index: int) -> floatThe resting price, or for a fill the execution price
mbo.event_size(index: int) -> floatThe new resting size, the contracts filled, or the size removed by a cancel
mbo.event_side(index: int) -> sideThe side of the resting order: BUY for a bid, SELL for an offer
mbo.event_time(index: int) -> floatWhen it happened, epoch milliseconds
mbo.event_order_id(index: int) -> stringThe order it belongs to
mbo.added_size(side: string) -> floatTotal size placed on that side during the bar; side is "BUY" or "SELL"
mbo.cancelled_size(side: string) -> floatTotal size pulled from that side
mbo.filled_size(side: string) -> floatTotal size filled against resting orders on that side
  • An order that was already resting when the chart started watching has no add event; its later changes are there.
  • Without data the three totals answer nan, the count 0 and the accessors their empty values.
  • Order events are a lot of rows on a busy bar. Filter inside the loop and draw only what matters.
let has_orders: bool = mbo.supported() && mbo.available()
let pulled_bid: float = mbo.cancelled_size("BUY")
let pulled_ask: float = mbo.cancelled_size("SELL")
for i = 0 to (has_orders ? mbo.event_count() : 0) - 1 by 1 {
  if mbo.event_type(i) == "cancel" && mbo.event_size(i) >= 50 {
    plot.dot(true, mbo.event_price(i), mbo.event_side(i) == "BUY" ? "#F97316" : "#38BDF8", 5)
  }
}
plot.label(str.concat("PULLED BID ", format.compact(nz(pulled_bid, 0)), "  ASK ", format.compact(nz(pulled_ask, 0))), "#E5E7EB")
  • Order indexes run from 0 to mbo.count() minus 1, oldest order first. The whole bar answers (largest, totals, iceberg count) are one call; loop over the indexes when you need every order.
  • mbo.largest_index() answers -1 on a bar with no orders, and the per order accessors answer the empty values for -1, so mbo.side(mbo.largest_index()) needs no guard.
  • Order data reaches back one trading day by default. With the Iceberg MBO indicator on the chart, its Days to load setting decides.
  • A bar with no data answers zero counts, -1, UNDEFINED, empty strings and nan.
let has_orders: bool = mbo.supported() && mbo.available()
let big: int = mbo.largest_index()
let big_side: side = mbo.side(big)
let refilled: float = mbo.refills(big)
let icebergs: float = mbo.iceberg_count(3)
plot.marker(has_orders && icebergs > 0 && big_side == "BUY", low, "#22C55E", "circle", "below", 8, 2)
plot.marker(has_orders && icebergs > 0 && big_side == "SELL", high, "#EF4444", "circle", "above", 8, 2)

Všechny vrstvy trhu – od Orderflow po optionflow – v jednom grafu.

Orderflow data institucionální kvality s vestavěným backtestingem a obchodním deníkem. Zapište se na čekací listinu a získejte předběžný přístup.

Získat přístup