feat: order-book microstructure indicators (part 1 of 4) (#112)
* feat(core): add microstructure input types (OrderBook, Trade, TradeQuote) New non-OHLCV value types for the order-book / trade-flow indicator family: Level, OrderBook (sorted, uncrossed depth snapshot), Side, Trade (with aggressor side), and TradeQuote (trade paired with prevailing mid). Each has a validating constructor plus a new_unchecked hot-path constructor, with full unit coverage. Adds InvalidOrderBook / InvalidTrade error variants. * feat(core): add 5 order-book microstructure indicators OrderBookImbalanceTop1/TopN/Full (signed depth imbalance), Microprice (size-weighted fair value), and QuotedSpread (top-of-book spread in bps). All consume the OrderBook snapshot type, emit f64, are stateless and ready after the first snapshot, with full unit coverage. Registers a new Microstructure family in the taxonomy. * feat(bindings): expose order-book microstructure indicators Python, Node, and WASM bindings for OrderBookImbalanceTop1/TopN/Full, Microprice and QuotedSpread. Each takes a depth snapshot via four equal-length (bid_px, bid_sz, ask_px, ask_sz) arrays. Python and Node expose a batch over a list of snapshots; WASM exposes per-snapshot update (the streaming model that fits a browser book feed). Regenerates node index.d.ts/.js and registers the new InvalidOrderBook/InvalidTrade arms in the Python error mapping. * test(bindings,fuzz): cover order-book microstructure indicators Python: smoke, reference values, streaming-vs-batch, lifecycle/repr and input validation (mismatched lengths, crossed book, misordered levels, zero levels) for all five order-book indicators. Node: reference values, streaming-vs-batch, and rejection cases. Adds an indicator_update_orderbook fuzz target driving every order-book indicator over arbitrary (incl. degenerate) snapshots. * bench(microstructure): synthetic order-book benchmarks Add a bench_orderbook_input harness and synthesise a five-level book around each candle close (no order-book dataset ships with the repo). Benches the cheapest (top-of-book imbalance) and most-expensive (full-depth imbalance) plus microprice, matching the curated cheapest/expensive-per-family approach. * docs: add Microstructure family + bump indicator counter to 224 README gains the Microstructure family row (order-book imbalance, microprice, quoted spread) and the indicator counter goes 219 -> 224 across seventeen families; CHANGELOG records the new order-book indicators and value types.
This commit is contained in:
@@ -847,3 +847,26 @@ def test_doji_signed_dragonfly_gravestone_neutral():
|
||||
assert d.update((10.0, 12.0, 8.0, 10.0, 1.0, 2)) == pytest.approx(0.0)
|
||||
# A large body is not a doji at all -> 0 regardless of position.
|
||||
assert d.update((10.0, 12.0, 10.0, 12.0, 1.0, 3)) == pytest.approx(0.0)
|
||||
|
||||
|
||||
def test_orderbook_imbalance_reference_values():
|
||||
# Top-1: (3 - 1) / (3 + 1) = 0.5.
|
||||
assert ta.OrderBookImbalanceTop1().update([100.0], [3.0], [101.0], [1.0]) == pytest.approx(0.5)
|
||||
# Top-2: bidDepth 3, askDepth 2 -> (3 - 2) / 5 = 0.2.
|
||||
topn = ta.OrderBookImbalanceTopN(2)
|
||||
assert topn.update([100.0, 99.0], [2.0, 1.0], [101.0, 102.0], [1.0, 1.0]) == pytest.approx(0.2)
|
||||
# Full: bidDepth 1, askDepth 3 -> (1 - 3) / 4 = -0.5.
|
||||
full = ta.OrderBookImbalanceFull()
|
||||
assert full.update([100.0], [1.0], [101.0, 102.0], [2.0, 1.0]) == pytest.approx(-0.5)
|
||||
|
||||
|
||||
def test_microprice_reference_value():
|
||||
# (100*3 + 101*1) / (1 + 3) = 401 / 4 = 100.25 — heavy ask pulls toward bid.
|
||||
mp = ta.Microprice()
|
||||
assert mp.update([100.0], [1.0], [101.0], [3.0]) == pytest.approx(100.25)
|
||||
|
||||
|
||||
def test_quoted_spread_reference_value():
|
||||
# spread 1.0, mid 100.5 -> 1 / 100.5 * 10_000 ≈ 99.5025 bps.
|
||||
qs = ta.QuotedSpread()
|
||||
assert qs.update([100.0], [1.0], [101.0], [1.0]) == pytest.approx(99.50248756, abs=1e-6)
|
||||
|
||||
Reference in New Issue
Block a user