lobkit 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lobkit-0.2.1/LICENSE +21 -0
- lobkit-0.2.1/PKG-INFO +289 -0
- lobkit-0.2.1/README.md +249 -0
- lobkit-0.2.1/pyproject.toml +54 -0
- lobkit-0.2.1/setup.cfg +4 -0
- lobkit-0.2.1/src/lobkit/__init__.py +18 -0
- lobkit-0.2.1/src/lobkit/analysis.py +262 -0
- lobkit-0.2.1/src/lobkit/book.py +113 -0
- lobkit-0.2.1/src/lobkit/features.py +85 -0
- lobkit-0.2.1/src/lobkit/market_making.py +168 -0
- lobkit-0.2.1/src/lobkit/plotting.py +147 -0
- lobkit-0.2.1/src/lobkit/recorder.py +222 -0
- lobkit-0.2.1/src/lobkit/simulator.py +234 -0
- lobkit-0.2.1/src/lobkit.egg-info/PKG-INFO +289 -0
- lobkit-0.2.1/src/lobkit.egg-info/SOURCES.txt +20 -0
- lobkit-0.2.1/src/lobkit.egg-info/dependency_links.txt +1 -0
- lobkit-0.2.1/src/lobkit.egg-info/requires.txt +16 -0
- lobkit-0.2.1/src/lobkit.egg-info/top_level.txt +1 -0
- lobkit-0.2.1/tests/test_book.py +53 -0
- lobkit-0.2.1/tests/test_features_sim.py +139 -0
- lobkit-0.2.1/tests/test_market_making.py +66 -0
- lobkit-0.2.1/tests/test_recorder.py +69 -0
lobkit-0.2.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yousuf Hossain Shafeen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
lobkit-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lobkit
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Limit order book reconstruction, order-flow analytics and market-making simulation
|
|
5
|
+
Author: Yousuf Hossain Shafeen
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/hossainyousuf751/microstructure-lab
|
|
8
|
+
Project-URL: Documentation, https://github.com/hossainyousuf751/microstructure-lab#readme
|
|
9
|
+
Project-URL: Changelog, https://github.com/hossainyousuf751/microstructure-lab/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Issues, https://github.com/hossainyousuf751/microstructure-lab/issues
|
|
11
|
+
Keywords: market microstructure,limit order book,order flow imbalance,market making,avellaneda-stoikov,micro-price,binance,bybit
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: numpy>=1.24
|
|
27
|
+
Requires-Dist: pandas>=2.0
|
|
28
|
+
Provides-Extra: plot
|
|
29
|
+
Requires-Dist: matplotlib>=3.7; extra == "plot"
|
|
30
|
+
Provides-Extra: live
|
|
31
|
+
Requires-Dist: websockets>=12; extra == "live"
|
|
32
|
+
Requires-Dist: requests>=2.28; extra == "live"
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
35
|
+
Requires-Dist: matplotlib>=3.7; extra == "dev"
|
|
36
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
37
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
38
|
+
Requires-Dist: twine>=6; extra == "dev"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# microstructure-lab
|
|
42
|
+
|
|
43
|
+
[](https://github.com/hossainyousuf751/microstructure-lab/actions/workflows/ci.yml) [](https://github.com/hossainyousuf751/microstructure-lab/blob/main/LICENSE)
|
|
44
|
+
|
|
45
|
+
Limit order book reconstruction, order-flow analytics, and market-making simulation.
|
|
46
|
+
The analytics are validated on a zero-intelligence order book simulator, then run unchanged
|
|
47
|
+
on live Binance data.
|
|
48
|
+
|
|
49
|
+
The library alone, from PyPI:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install lobkit # add [plot] for figures, [live] to record exchange data
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The studies below live in this repository, so to reproduce them clone it and run:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install -e ".[dev]"
|
|
59
|
+
ruff check . && pytest
|
|
60
|
+
cd examples
|
|
61
|
+
python 01_simulated_lob.py # order-flow analytics on a simulated book (~10 s)
|
|
62
|
+
python 02_avellaneda_stoikov.py # market-making replication (~5 s)
|
|
63
|
+
python 05_market_making_in_lob.py # the market maker inside the simulated book (~45 s)
|
|
64
|
+
pip install -e "..[live]"
|
|
65
|
+
python 03_record_binance.py btcusdt 900 # record 15 minutes of Binance + Bybit data
|
|
66
|
+
python 04_analyze_recording.py ../data/btcusdt_<timestamp> 0.01 # 0.01 = tick size
|
|
67
|
+
python 06_cross_venue.py ../data/btcusdt_<timestamp> # which venue leads?
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Components
|
|
71
|
+
|
|
72
|
+
| Module | What it does |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `book.py` | L2 order book; Binance diff-depth synchronisation with sequence-gap detection |
|
|
75
|
+
| `recorder.py` | Async recorder for Binance best quotes, trades and synchronised L2 depth, plus Bybit best quotes and trades; auto-reconnect; loaders |
|
|
76
|
+
| `simulator.py` | Zero-intelligence limit order book (Cont, Stoikov & Talreja 2010), optional multi-level output and a resting quoter with queue position |
|
|
77
|
+
| `features.py` | Mid, spread, queue imbalance, microprice, order-flow imbalance (OFI, single and multi-level), time buckets |
|
|
78
|
+
| `analysis.py` | Price-impact regressions, impact vs depth, out-of-sample predictability, Stoikov micro-price, cross-venue lead-lag |
|
|
79
|
+
| `market_making.py` | Avellaneda–Stoikov optimal market maker vs a symmetric benchmark, in the paper's model and inside the order book |
|
|
80
|
+
|
|
81
|
+
See [CONTRIBUTING.md](https://github.com/hossainyousuf751/microstructure-lab/blob/main/CONTRIBUTING.md) for the rules, roles and workflow, and
|
|
82
|
+
[CHANGELOG.md](https://github.com/hossainyousuf751/microstructure-lab/blob/main/CHANGELOG.md) for what changed.
|
|
83
|
+
|
|
84
|
+
**Book synchronisation.** Binance publishes a REST snapshot plus a diff stream. A correct
|
|
85
|
+
local book has to drop diffs already in the snapshot, check that the first applied diff
|
|
86
|
+
bridges the snapshot's update ID, and verify every later diff continues the sequence exactly.
|
|
87
|
+
`BinanceDepthSync` implements these rules, raises `SequenceGap` on a missed update, and the
|
|
88
|
+
recorder resyncs automatically. Each rule has a unit test.
|
|
89
|
+
|
|
90
|
+
## Study 1: order flow and prices
|
|
91
|
+
|
|
92
|
+
On 4.6 simulated hours (400,000 book events) of a market where no participant has information:
|
|
93
|
+
|
|
94
|
+
| Result | Value | Literature |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| Δmid on OFI, 10-second buckets | β = 0.285 ticks per unit, **R² = 0.66**, t = 56 | Cont, Kukanov & Stoikov (2014): average R² ≈ 65% on US stocks |
|
|
97
|
+
| Impact coefficient vs 1/depth | linear, R² = 0.93 | β inversely proportional to depth |
|
|
98
|
+
| P(next move up), imbalance 0.1–0.2 → 0.8–0.9 | 0.25 → 0.79, monotone | Gould & Bonart (2016) |
|
|
99
|
+
| Next 10-second move from OFI / imbalance | out-of-sample R² ≤ 0.7% | — |
|
|
100
|
+
| Δmid on OFI of the best 1 → 5 levels, 10 s | out-of-sample R² 0.66 → 0.79 → 0.85 → 0.86 → **0.88** | Xu, Gould & Howison (2019) |
|
|
101
|
+
| Forecast of the mid after the next mid change | Stoikov micro-price −6.6% MSE vs mid; naive microprice −1.3% | Stoikov (2018) |
|
|
102
|
+
|
|
103
|
+

|
|
104
|
+
|
|
105
|
+

|
|
106
|
+
|
|
107
|
+
**Explaining is not predicting.** Order flow explains two-thirds of price changes in the same
|
|
108
|
+
interval but almost none of the next 10 seconds. Queue imbalance strongly predicts the *next*
|
|
109
|
+
price move, but in a liquid book many moves happen within a 10-second bucket. The edge is real
|
|
110
|
+
at the event horizon, and only accessible to someone fast enough to act on it.
|
|
111
|
+
|
|
112
|
+

|
|
113
|
+
|
|
114
|
+
**Deeper order flow matters.** Best-level OFI misses flow that arrives one level back and becomes
|
|
115
|
+
the best queue a moment later. Adding the second level lifts out-of-sample R² from 0.66 to 0.79,
|
|
116
|
+
and five levels reach 0.88. In-sample and out-of-sample R² agree, so this is not overfitting.
|
|
117
|
+
|
|
118
|
+

|
|
119
|
+
|
|
120
|
+
**The naive microprice overshoots; Stoikov's micro-price doesn't.** The imbalance-weighted mid is
|
|
121
|
+
a worse forecast of the very next mid than the mid itself (−82% at one update, out of sample), and
|
|
122
|
+
only marginally better at 10–100 updates. With small queues it over-reacts to imbalance.
|
|
123
|
+
Stoikov's (2018) micro-price is estimated as a Markov chain on (spread, imbalance): fitted on the
|
|
124
|
+
first 70% of the data, it shades the mid by at most 0.29 ticks at a one-tick spread, against 0.36
|
|
125
|
+
for the naive formula in the same bucket, and much less when the spread is two ticks. It is built
|
|
126
|
+
to forecast the mid at the next *price changes*, and there it wins clearly: 6.6% lower squared
|
|
127
|
+
error than the mid for the next change, and 4.2% for the one after, against 1.3% and 2.6% for the
|
|
128
|
+
naive microprice. At one book update it still loses to the mid (−18%), because most updates
|
|
129
|
+
don't move the price at all.
|
|
130
|
+
|
|
131
|
+

|
|
132
|
+
|
|
133
|
+
One detail matters for the estimator: with small integer queues a perfectly balanced book
|
|
134
|
+
(imbalance exactly 0.5) is common. With the usual 10 imbalance buckets those states land in an
|
|
135
|
+
"up" bucket and break the symmetry the method relies on, so lobkit uses an odd number (11).
|
|
136
|
+
|
|
137
|
+
## Study 2: Avellaneda–Stoikov market making
|
|
138
|
+
|
|
139
|
+
The market maker quotes around a reservation price r = s − qγσ²(T − t), shifted against its
|
|
140
|
+
inventory q, with the optimal spread γσ²(T − t) + (2/γ)ln(1 + γ/k). The symmetric benchmark uses
|
|
141
|
+
the same spread centred on the mid. Paper parameters: s₀ = 100, σ = 2, T = 1, dt = 0.005,
|
|
142
|
+
A = 140, k = 1.5, 4,000 simulations:
|
|
143
|
+
|
|
144
|
+
| γ | Strategy | Mean P&L | Std P&L | Std final inventory |
|
|
145
|
+
|---|---|---|---|---|
|
|
146
|
+
| 0.01 | inventory | 66.8 | 8.9 | 5.4 |
|
|
147
|
+
| 0.01 | symmetric | 67.1 | 13.8 | 9.0 |
|
|
148
|
+
| **0.1** | **inventory** | **63.4** | **6.4** | **3.0** |
|
|
149
|
+
| **0.1** | **symmetric** | **66.8** | **13.1** | **8.6** |
|
|
150
|
+
| 0.5 | inventory | 47.3 | 5.8 | 2.0 |
|
|
151
|
+
| 0.5 | symmetric | 57.7 | 11.6 | 7.2 |
|
|
152
|
+
|
|
153
|
+
The paper reports approximately 62.9 (std 5.9) and 67.2 (std 13.4) for γ = 0.1. Inventory
|
|
154
|
+
management halves P&L volatility and keeps inventory three times tighter, for about 5% less profit.
|
|
155
|
+
|
|
156
|
+

|
|
157
|
+
|
|
158
|
+
**A finding along the way.** My first implementation evaluated fills before moving the mid within
|
|
159
|
+
each time step, and gave 65.1 for the inventory strategy, about 2 above the paper and outside
|
|
160
|
+
Monte Carlo error. Moving the mid first, then evaluating fills against quotes set before the
|
|
161
|
+
move, reproduces the paper. It is also the more realistic ordering: it captures adverse
|
|
162
|
+
selection, where quotes the price has moved through are more likely to fill.
|
|
163
|
+
|
|
164
|
+
## Study 3: live Binance data
|
|
165
|
+
|
|
166
|
+
`03_record_binance.py` records best quotes, trades and synchronised L2 depth for any spot pair;
|
|
167
|
+
`04_analyze_recording.py` runs the same analysis as Study 1 at 1-second buckets, plus multi-level
|
|
168
|
+
OFI on the recorded top-10 depth (sampled once a second, so 5-second buckets). Comparing the
|
|
169
|
+
simulated and live tables shows which effects are mechanical consequences of the order book
|
|
170
|
+
and which require informed traders. Record at least 15 minutes; the script warns when there is
|
|
171
|
+
too little data to say anything.
|
|
172
|
+
|
|
173
|
+
Results for one session: BTCUSDT, 40 minutes on 2026-11-01 from 03:18 local time (76,296 quote
|
|
174
|
+
updates, 5,813 trades). It was a quiet market: the price stayed within a 181 USDT range and the
|
|
175
|
+
mid changed 688 times, about once every 3.5 seconds. That session is one sample, not a study, and
|
|
176
|
+
the recording is not in the repository (market data is never committed), so treat these numbers
|
|
177
|
+
as an illustration of the pipeline.
|
|
178
|
+
|
|
179
|
+
| Result | Live, 1 s buckets | Simulated |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| Δmid on OFI | β = 0.221 USDT per unit, **R² = 0.56**, t = 55 | R² = 0.42 at 1 s (Study 5), 0.66 at 10 s |
|
|
182
|
+
| Impact coefficient vs 1/depth | R² = 0.85 across depth quintiles | R² = 0.93 (10 s) |
|
|
183
|
+
| P(next move up), imbalance < 0.1 → > 0.9 | 0.38 → 0.97, not monotone in between | monotone |
|
|
184
|
+
| Next 1 s move from queue imbalance | out-of-sample R² 3.3% | 0.7% (next 10 s) |
|
|
185
|
+
| Multi-level OFI, best 1 → 10 levels (5 s) | out-of-sample R² 0.50 → 0.40–0.49: no gain | 0.66 → 0.88, 1 → 5 levels (10 s) |
|
|
186
|
+
| Micro-price vs mid, next price change | Stoikov −0.34% MSE, naive −0.32%: no real edge | Stoikov −6.6%, naive −1.3% |
|
|
187
|
+
|
|
188
|
+

|
|
189
|
+
|
|
190
|
+
**What survives contact with a real book.** The contemporaneous OFI relation is at least as
|
|
191
|
+
strong live as in the simulator at 1-second buckets, and impact is still larger when the book is
|
|
192
|
+
thin. Queue imbalance predicts the next move at the extremes, and on the live book it even has a
|
|
193
|
+
little out-of-sample power over the next second.
|
|
194
|
+
|
|
195
|
+
**What doesn't.** Deeper levels add nothing out of sample, while they explained a lot in the
|
|
196
|
+
simulator. On BTCUSDT the levels behind the best quote are a cent apart and mostly small resting
|
|
197
|
+
orders, so their flow carries little information. Neither micro-price beats the mid by more than
|
|
198
|
+
a third of a percent. Most rows sit at a one-tick spread with the price unchanged. The 688 price
|
|
199
|
+
changes include 323 updates where one side of the book thinned out for an instant and the spread
|
|
200
|
+
jumped past 1 USDT (up to 10.8), and a squared-error comparison over so few moves is decided by
|
|
201
|
+
those points. A busier session, or a robust loss, is the next step.
|
|
202
|
+
|
|
203
|
+
## Study 4: the market maker inside the order book
|
|
204
|
+
|
|
205
|
+
Study 2 assumes fills arrive at rate A·e^(−kδ), independent of what the price does next. In a real
|
|
206
|
+
book an order fills only when market orders have eaten the queue ahead of it, which is exactly
|
|
207
|
+
when the price is about to move through it. `05_market_making_in_lob.py` puts the same quoter
|
|
208
|
+
into the zero-intelligence book: one unit per side, joining the back of the queue, keeping its
|
|
209
|
+
place if the quote doesn't change at the once-a-second requote, and filling only when a market
|
|
210
|
+
order reaches it.
|
|
211
|
+
|
|
212
|
+
The paper's inputs are calibrated on the book itself: σ = 1.08 ticks/√s from 1-second mid
|
|
213
|
+
changes; A = 0.59 fills/s and k = 1.39 per tick from a quoter resting at fixed distances from the
|
|
214
|
+
mid. Episodes last T = 300 s, 200 per row:
|
|
215
|
+
|
|
216
|
+
| γ | Strategy | Mean P&L | Std P&L | Std final inventory | Fills | Spread captured | Adverse sel. 1 s | Adverse sel. 10 s | Kept |
|
|
217
|
+
|---|---|---|---|---|---|---|---|---|---|
|
|
218
|
+
| 0.001 | inventory | 30.1 | 25.9 | 4.0 | 71 | 0.82 | −0.21 | −0.30 | 63% |
|
|
219
|
+
| 0.001 | symmetric | 46.5 | 58.3 | 7.2 | 70 | 0.84 | −0.18 | −0.17 | 80% |
|
|
220
|
+
| **0.005** | **inventory** | **19.4** | **13.3** | **2.4** | **64** | **0.79** | **−0.30** | **−0.48** | **39%** |
|
|
221
|
+
| **0.005** | **symmetric** | **28.9** | **59.0** | **6.9** | **51** | **0.88** | **−0.19** | **−0.20** | **77%** |
|
|
222
|
+
| 0.02 | inventory | 8.0 | 7.5 | 1.4 | 26 | 0.81 | −0.35 | −0.53 | 35% |
|
|
223
|
+
| 0.02 | symmetric | 14.5 | 25.9 | 4.1 | 18 | 0.96 | −0.20 | −0.17 | 82% |
|
|
224
|
+
|
|
225
|
+
(P&L in ticks; spread captured and adverse selection in ticks per fill; "kept" is after 10 s. Markouts
|
|
226
|
+
leave out fills too close to the end of an episode to have a full horizon.)
|
|
227
|
+
|
|
228
|
+
**Inventory control still works.** The skewed quoter cuts P&L volatility by 2.3–4.4× and final
|
|
229
|
+
inventory by 1.8–2.9×, as in the paper.
|
|
230
|
+
|
|
231
|
+
**But it pays for it in adverse selection.** Every fill captures 0.79–0.96 ticks against the mid
|
|
232
|
+
at that moment. Ten seconds later the symmetric quoter has given back about a fifth of that; the
|
|
233
|
+
inventory quoter gives back 37–65%. To unload inventory it quotes aggressively on one side, often
|
|
234
|
+
alone at a new best price, and an order alone at the front is the first to be hit when the price
|
|
235
|
+
moves. As a result inventory control costs 33–45% of mean P&L here, against about 5% in the
|
|
236
|
+
paper's model (Study 2), where a fill says little about the next price move.
|
|
237
|
+
|
|
238
|
+
**The two costs have different clocks.** The symmetric quoter's loss is complete within a second
|
|
239
|
+
(−0.17 to −0.21 ticks at both horizons): it is the tick the price jumps when the quoter's queue
|
|
240
|
+
is used up. The inventory quoter loses −0.21 to −0.35 in the first second and keeps losing until
|
|
241
|
+
−0.30 to −0.53 at ten seconds, so its fills come before sustained moves, not just a one-tick jump.
|
|
242
|
+
|
|
243
|
+

|
|
244
|
+
|
|
245
|
+
## Study 5: which venue moves first?
|
|
246
|
+
|
|
247
|
+
`06_cross_venue.py` compares the Binance and Bybit BTCUSDT books recorded in the same session,
|
|
248
|
+
on one local clock. `lead_lag` correlates the two venues' mid returns at lags of ±2 s on a 50 ms
|
|
249
|
+
grid; `cross_venue_impact` asks how much of each venue's 1-second price change its own and the
|
|
250
|
+
other venue's order flow explain, and whether either venue's flow or return predicts the other's
|
|
251
|
+
*next* second. Following the repo's rule, the estimators are first run where the answer is
|
|
252
|
+
known: a simulated venue B that copies venue A 300 ms late. They find the delay exactly
|
|
253
|
+
(correlation 1.00 at +300 ms) and the direction: only B's next move is predictable from A.
|
|
254
|
+
|
|
255
|
+
Same session as Study 3 (40 minutes; 76,296 Binance and 24,969 Bybit quote updates):
|
|
256
|
+
|
|
257
|
+
| Target venue | R² own OFI | R² other venue's OFI | R² both | Next 1 s from other's OFI (OOS) | Next 1 s from other's return (OOS) |
|
|
258
|
+
|---|---|---|---|---|---|
|
|
259
|
+
| Binance | 0.56 | 0.16 | 0.56 | 0.014 | 0.009 |
|
|
260
|
+
| Bybit | 0.58 | 0.28 | 0.60 | 0.004 | 0.004 |
|
|
261
|
+
|
|
262
|
+

|
|
263
|
+
|
|
264
|
+
**No exploitable lead at this resolution.** Returns are most correlated at 0 ms (0.09): the
|
|
265
|
+
venues move within the same 50 ms. Each venue's own order flow explains its price far better than
|
|
266
|
+
the other's. Neither venue's flow or return predicts the other's next second by more than about
|
|
267
|
+
1% out of sample. There is more correlation at negative lags (Bybit first, summed 0.62 against
|
|
268
|
+
0.20 for Binance first), and it persisted after the recorder's timestamp bug was fixed (see
|
|
269
|
+
CHANGELOG), but Bybit's price changed only 218 times, so this is a hypothesis for a longer
|
|
270
|
+
recording, not a finding. One limitation is built in: timestamps are local receive times, so each
|
|
271
|
+
venue's network latency to the recording machine is part of the measured lag. A lead shorter than
|
|
272
|
+
the difference in latencies can't be seen from one machine.
|
|
273
|
+
|
|
274
|
+
## Roadmap
|
|
275
|
+
|
|
276
|
+
- [x] **M1** Book sync, recorder, ZI simulator, OFI/imbalance analytics, Avellaneda–Stoikov replication
|
|
277
|
+
- [x] **M2** Multi-level OFI (Xu, Gould & Howison 2019) using the recorded L2 depth
|
|
278
|
+
- [x] **M3** Stoikov (2018) micro-price, estimated as a Markov chain on (imbalance, spread)
|
|
279
|
+
- [x] **M4** Run the Avellaneda–Stoikov quoter inside the order book simulator, with queue position and adverse selection
|
|
280
|
+
- [x] **M5** Cross-venue study: OFI and lead-lag between Binance and a second exchange (Bybit)
|
|
281
|
+
|
|
282
|
+
## References
|
|
283
|
+
|
|
284
|
+
- Avellaneda, M. & Stoikov, S. (2008). High-frequency trading in a limit order book. *Quantitative Finance* 8(3).
|
|
285
|
+
- Cont, R., Stoikov, S. & Talreja, R. (2010). A stochastic model for order book dynamics. *Operations Research* 58(3).
|
|
286
|
+
- Cont, R., Kukanov, A. & Stoikov, S. (2014). The price impact of order book events. *Journal of Financial Econometrics* 12(1).
|
|
287
|
+
- Gould, M. & Bonart, J. (2016). Queue imbalance as a one-tick-ahead price predictor in a limit order book. *Market Microstructure and Liquidity* 2(2).
|
|
288
|
+
- Stoikov, S. (2018). The micro-price: a high-frequency estimator of future prices. *Quantitative Finance* 18(12).
|
|
289
|
+
- Xu, K., Gould, M. D. & Howison, S. D. (2019). Multi-level order-flow imbalance in a limit order book. *Market Microstructure and Liquidity* 4(3–4).
|
lobkit-0.2.1/README.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# microstructure-lab
|
|
2
|
+
|
|
3
|
+
[](https://github.com/hossainyousuf751/microstructure-lab/actions/workflows/ci.yml) [](https://github.com/hossainyousuf751/microstructure-lab/blob/main/LICENSE)
|
|
4
|
+
|
|
5
|
+
Limit order book reconstruction, order-flow analytics, and market-making simulation.
|
|
6
|
+
The analytics are validated on a zero-intelligence order book simulator, then run unchanged
|
|
7
|
+
on live Binance data.
|
|
8
|
+
|
|
9
|
+
The library alone, from PyPI:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install lobkit # add [plot] for figures, [live] to record exchange data
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The studies below live in this repository, so to reproduce them clone it and run:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install -e ".[dev]"
|
|
19
|
+
ruff check . && pytest
|
|
20
|
+
cd examples
|
|
21
|
+
python 01_simulated_lob.py # order-flow analytics on a simulated book (~10 s)
|
|
22
|
+
python 02_avellaneda_stoikov.py # market-making replication (~5 s)
|
|
23
|
+
python 05_market_making_in_lob.py # the market maker inside the simulated book (~45 s)
|
|
24
|
+
pip install -e "..[live]"
|
|
25
|
+
python 03_record_binance.py btcusdt 900 # record 15 minutes of Binance + Bybit data
|
|
26
|
+
python 04_analyze_recording.py ../data/btcusdt_<timestamp> 0.01 # 0.01 = tick size
|
|
27
|
+
python 06_cross_venue.py ../data/btcusdt_<timestamp> # which venue leads?
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Components
|
|
31
|
+
|
|
32
|
+
| Module | What it does |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `book.py` | L2 order book; Binance diff-depth synchronisation with sequence-gap detection |
|
|
35
|
+
| `recorder.py` | Async recorder for Binance best quotes, trades and synchronised L2 depth, plus Bybit best quotes and trades; auto-reconnect; loaders |
|
|
36
|
+
| `simulator.py` | Zero-intelligence limit order book (Cont, Stoikov & Talreja 2010), optional multi-level output and a resting quoter with queue position |
|
|
37
|
+
| `features.py` | Mid, spread, queue imbalance, microprice, order-flow imbalance (OFI, single and multi-level), time buckets |
|
|
38
|
+
| `analysis.py` | Price-impact regressions, impact vs depth, out-of-sample predictability, Stoikov micro-price, cross-venue lead-lag |
|
|
39
|
+
| `market_making.py` | Avellaneda–Stoikov optimal market maker vs a symmetric benchmark, in the paper's model and inside the order book |
|
|
40
|
+
|
|
41
|
+
See [CONTRIBUTING.md](https://github.com/hossainyousuf751/microstructure-lab/blob/main/CONTRIBUTING.md) for the rules, roles and workflow, and
|
|
42
|
+
[CHANGELOG.md](https://github.com/hossainyousuf751/microstructure-lab/blob/main/CHANGELOG.md) for what changed.
|
|
43
|
+
|
|
44
|
+
**Book synchronisation.** Binance publishes a REST snapshot plus a diff stream. A correct
|
|
45
|
+
local book has to drop diffs already in the snapshot, check that the first applied diff
|
|
46
|
+
bridges the snapshot's update ID, and verify every later diff continues the sequence exactly.
|
|
47
|
+
`BinanceDepthSync` implements these rules, raises `SequenceGap` on a missed update, and the
|
|
48
|
+
recorder resyncs automatically. Each rule has a unit test.
|
|
49
|
+
|
|
50
|
+
## Study 1: order flow and prices
|
|
51
|
+
|
|
52
|
+
On 4.6 simulated hours (400,000 book events) of a market where no participant has information:
|
|
53
|
+
|
|
54
|
+
| Result | Value | Literature |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| Δmid on OFI, 10-second buckets | β = 0.285 ticks per unit, **R² = 0.66**, t = 56 | Cont, Kukanov & Stoikov (2014): average R² ≈ 65% on US stocks |
|
|
57
|
+
| Impact coefficient vs 1/depth | linear, R² = 0.93 | β inversely proportional to depth |
|
|
58
|
+
| P(next move up), imbalance 0.1–0.2 → 0.8–0.9 | 0.25 → 0.79, monotone | Gould & Bonart (2016) |
|
|
59
|
+
| Next 10-second move from OFI / imbalance | out-of-sample R² ≤ 0.7% | — |
|
|
60
|
+
| Δmid on OFI of the best 1 → 5 levels, 10 s | out-of-sample R² 0.66 → 0.79 → 0.85 → 0.86 → **0.88** | Xu, Gould & Howison (2019) |
|
|
61
|
+
| Forecast of the mid after the next mid change | Stoikov micro-price −6.6% MSE vs mid; naive microprice −1.3% | Stoikov (2018) |
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+

|
|
66
|
+
|
|
67
|
+
**Explaining is not predicting.** Order flow explains two-thirds of price changes in the same
|
|
68
|
+
interval but almost none of the next 10 seconds. Queue imbalance strongly predicts the *next*
|
|
69
|
+
price move, but in a liquid book many moves happen within a 10-second bucket. The edge is real
|
|
70
|
+
at the event horizon, and only accessible to someone fast enough to act on it.
|
|
71
|
+
|
|
72
|
+

|
|
73
|
+
|
|
74
|
+
**Deeper order flow matters.** Best-level OFI misses flow that arrives one level back and becomes
|
|
75
|
+
the best queue a moment later. Adding the second level lifts out-of-sample R² from 0.66 to 0.79,
|
|
76
|
+
and five levels reach 0.88. In-sample and out-of-sample R² agree, so this is not overfitting.
|
|
77
|
+
|
|
78
|
+

|
|
79
|
+
|
|
80
|
+
**The naive microprice overshoots; Stoikov's micro-price doesn't.** The imbalance-weighted mid is
|
|
81
|
+
a worse forecast of the very next mid than the mid itself (−82% at one update, out of sample), and
|
|
82
|
+
only marginally better at 10–100 updates. With small queues it over-reacts to imbalance.
|
|
83
|
+
Stoikov's (2018) micro-price is estimated as a Markov chain on (spread, imbalance): fitted on the
|
|
84
|
+
first 70% of the data, it shades the mid by at most 0.29 ticks at a one-tick spread, against 0.36
|
|
85
|
+
for the naive formula in the same bucket, and much less when the spread is two ticks. It is built
|
|
86
|
+
to forecast the mid at the next *price changes*, and there it wins clearly: 6.6% lower squared
|
|
87
|
+
error than the mid for the next change, and 4.2% for the one after, against 1.3% and 2.6% for the
|
|
88
|
+
naive microprice. At one book update it still loses to the mid (−18%), because most updates
|
|
89
|
+
don't move the price at all.
|
|
90
|
+
|
|
91
|
+

|
|
92
|
+
|
|
93
|
+
One detail matters for the estimator: with small integer queues a perfectly balanced book
|
|
94
|
+
(imbalance exactly 0.5) is common. With the usual 10 imbalance buckets those states land in an
|
|
95
|
+
"up" bucket and break the symmetry the method relies on, so lobkit uses an odd number (11).
|
|
96
|
+
|
|
97
|
+
## Study 2: Avellaneda–Stoikov market making
|
|
98
|
+
|
|
99
|
+
The market maker quotes around a reservation price r = s − qγσ²(T − t), shifted against its
|
|
100
|
+
inventory q, with the optimal spread γσ²(T − t) + (2/γ)ln(1 + γ/k). The symmetric benchmark uses
|
|
101
|
+
the same spread centred on the mid. Paper parameters: s₀ = 100, σ = 2, T = 1, dt = 0.005,
|
|
102
|
+
A = 140, k = 1.5, 4,000 simulations:
|
|
103
|
+
|
|
104
|
+
| γ | Strategy | Mean P&L | Std P&L | Std final inventory |
|
|
105
|
+
|---|---|---|---|---|
|
|
106
|
+
| 0.01 | inventory | 66.8 | 8.9 | 5.4 |
|
|
107
|
+
| 0.01 | symmetric | 67.1 | 13.8 | 9.0 |
|
|
108
|
+
| **0.1** | **inventory** | **63.4** | **6.4** | **3.0** |
|
|
109
|
+
| **0.1** | **symmetric** | **66.8** | **13.1** | **8.6** |
|
|
110
|
+
| 0.5 | inventory | 47.3 | 5.8 | 2.0 |
|
|
111
|
+
| 0.5 | symmetric | 57.7 | 11.6 | 7.2 |
|
|
112
|
+
|
|
113
|
+
The paper reports approximately 62.9 (std 5.9) and 67.2 (std 13.4) for γ = 0.1. Inventory
|
|
114
|
+
management halves P&L volatility and keeps inventory three times tighter, for about 5% less profit.
|
|
115
|
+
|
|
116
|
+

|
|
117
|
+
|
|
118
|
+
**A finding along the way.** My first implementation evaluated fills before moving the mid within
|
|
119
|
+
each time step, and gave 65.1 for the inventory strategy, about 2 above the paper and outside
|
|
120
|
+
Monte Carlo error. Moving the mid first, then evaluating fills against quotes set before the
|
|
121
|
+
move, reproduces the paper. It is also the more realistic ordering: it captures adverse
|
|
122
|
+
selection, where quotes the price has moved through are more likely to fill.
|
|
123
|
+
|
|
124
|
+
## Study 3: live Binance data
|
|
125
|
+
|
|
126
|
+
`03_record_binance.py` records best quotes, trades and synchronised L2 depth for any spot pair;
|
|
127
|
+
`04_analyze_recording.py` runs the same analysis as Study 1 at 1-second buckets, plus multi-level
|
|
128
|
+
OFI on the recorded top-10 depth (sampled once a second, so 5-second buckets). Comparing the
|
|
129
|
+
simulated and live tables shows which effects are mechanical consequences of the order book
|
|
130
|
+
and which require informed traders. Record at least 15 minutes; the script warns when there is
|
|
131
|
+
too little data to say anything.
|
|
132
|
+
|
|
133
|
+
Results for one session: BTCUSDT, 40 minutes on 2026-11-01 from 03:18 local time (76,296 quote
|
|
134
|
+
updates, 5,813 trades). It was a quiet market: the price stayed within a 181 USDT range and the
|
|
135
|
+
mid changed 688 times, about once every 3.5 seconds. That session is one sample, not a study, and
|
|
136
|
+
the recording is not in the repository (market data is never committed), so treat these numbers
|
|
137
|
+
as an illustration of the pipeline.
|
|
138
|
+
|
|
139
|
+
| Result | Live, 1 s buckets | Simulated |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| Δmid on OFI | β = 0.221 USDT per unit, **R² = 0.56**, t = 55 | R² = 0.42 at 1 s (Study 5), 0.66 at 10 s |
|
|
142
|
+
| Impact coefficient vs 1/depth | R² = 0.85 across depth quintiles | R² = 0.93 (10 s) |
|
|
143
|
+
| P(next move up), imbalance < 0.1 → > 0.9 | 0.38 → 0.97, not monotone in between | monotone |
|
|
144
|
+
| Next 1 s move from queue imbalance | out-of-sample R² 3.3% | 0.7% (next 10 s) |
|
|
145
|
+
| Multi-level OFI, best 1 → 10 levels (5 s) | out-of-sample R² 0.50 → 0.40–0.49: no gain | 0.66 → 0.88, 1 → 5 levels (10 s) |
|
|
146
|
+
| Micro-price vs mid, next price change | Stoikov −0.34% MSE, naive −0.32%: no real edge | Stoikov −6.6%, naive −1.3% |
|
|
147
|
+
|
|
148
|
+

|
|
149
|
+
|
|
150
|
+
**What survives contact with a real book.** The contemporaneous OFI relation is at least as
|
|
151
|
+
strong live as in the simulator at 1-second buckets, and impact is still larger when the book is
|
|
152
|
+
thin. Queue imbalance predicts the next move at the extremes, and on the live book it even has a
|
|
153
|
+
little out-of-sample power over the next second.
|
|
154
|
+
|
|
155
|
+
**What doesn't.** Deeper levels add nothing out of sample, while they explained a lot in the
|
|
156
|
+
simulator. On BTCUSDT the levels behind the best quote are a cent apart and mostly small resting
|
|
157
|
+
orders, so their flow carries little information. Neither micro-price beats the mid by more than
|
|
158
|
+
a third of a percent. Most rows sit at a one-tick spread with the price unchanged. The 688 price
|
|
159
|
+
changes include 323 updates where one side of the book thinned out for an instant and the spread
|
|
160
|
+
jumped past 1 USDT (up to 10.8), and a squared-error comparison over so few moves is decided by
|
|
161
|
+
those points. A busier session, or a robust loss, is the next step.
|
|
162
|
+
|
|
163
|
+
## Study 4: the market maker inside the order book
|
|
164
|
+
|
|
165
|
+
Study 2 assumes fills arrive at rate A·e^(−kδ), independent of what the price does next. In a real
|
|
166
|
+
book an order fills only when market orders have eaten the queue ahead of it, which is exactly
|
|
167
|
+
when the price is about to move through it. `05_market_making_in_lob.py` puts the same quoter
|
|
168
|
+
into the zero-intelligence book: one unit per side, joining the back of the queue, keeping its
|
|
169
|
+
place if the quote doesn't change at the once-a-second requote, and filling only when a market
|
|
170
|
+
order reaches it.
|
|
171
|
+
|
|
172
|
+
The paper's inputs are calibrated on the book itself: σ = 1.08 ticks/√s from 1-second mid
|
|
173
|
+
changes; A = 0.59 fills/s and k = 1.39 per tick from a quoter resting at fixed distances from the
|
|
174
|
+
mid. Episodes last T = 300 s, 200 per row:
|
|
175
|
+
|
|
176
|
+
| γ | Strategy | Mean P&L | Std P&L | Std final inventory | Fills | Spread captured | Adverse sel. 1 s | Adverse sel. 10 s | Kept |
|
|
177
|
+
|---|---|---|---|---|---|---|---|---|---|
|
|
178
|
+
| 0.001 | inventory | 30.1 | 25.9 | 4.0 | 71 | 0.82 | −0.21 | −0.30 | 63% |
|
|
179
|
+
| 0.001 | symmetric | 46.5 | 58.3 | 7.2 | 70 | 0.84 | −0.18 | −0.17 | 80% |
|
|
180
|
+
| **0.005** | **inventory** | **19.4** | **13.3** | **2.4** | **64** | **0.79** | **−0.30** | **−0.48** | **39%** |
|
|
181
|
+
| **0.005** | **symmetric** | **28.9** | **59.0** | **6.9** | **51** | **0.88** | **−0.19** | **−0.20** | **77%** |
|
|
182
|
+
| 0.02 | inventory | 8.0 | 7.5 | 1.4 | 26 | 0.81 | −0.35 | −0.53 | 35% |
|
|
183
|
+
| 0.02 | symmetric | 14.5 | 25.9 | 4.1 | 18 | 0.96 | −0.20 | −0.17 | 82% |
|
|
184
|
+
|
|
185
|
+
(P&L in ticks; spread captured and adverse selection in ticks per fill; "kept" is after 10 s. Markouts
|
|
186
|
+
leave out fills too close to the end of an episode to have a full horizon.)
|
|
187
|
+
|
|
188
|
+
**Inventory control still works.** The skewed quoter cuts P&L volatility by 2.3–4.4× and final
|
|
189
|
+
inventory by 1.8–2.9×, as in the paper.
|
|
190
|
+
|
|
191
|
+
**But it pays for it in adverse selection.** Every fill captures 0.79–0.96 ticks against the mid
|
|
192
|
+
at that moment. Ten seconds later the symmetric quoter has given back about a fifth of that; the
|
|
193
|
+
inventory quoter gives back 37–65%. To unload inventory it quotes aggressively on one side, often
|
|
194
|
+
alone at a new best price, and an order alone at the front is the first to be hit when the price
|
|
195
|
+
moves. As a result inventory control costs 33–45% of mean P&L here, against about 5% in the
|
|
196
|
+
paper's model (Study 2), where a fill says little about the next price move.
|
|
197
|
+
|
|
198
|
+
**The two costs have different clocks.** The symmetric quoter's loss is complete within a second
|
|
199
|
+
(−0.17 to −0.21 ticks at both horizons): it is the tick the price jumps when the quoter's queue
|
|
200
|
+
is used up. The inventory quoter loses −0.21 to −0.35 in the first second and keeps losing until
|
|
201
|
+
−0.30 to −0.53 at ten seconds, so its fills come before sustained moves, not just a one-tick jump.
|
|
202
|
+
|
|
203
|
+

|
|
204
|
+
|
|
205
|
+
## Study 5: which venue moves first?
|
|
206
|
+
|
|
207
|
+
`06_cross_venue.py` compares the Binance and Bybit BTCUSDT books recorded in the same session,
|
|
208
|
+
on one local clock. `lead_lag` correlates the two venues' mid returns at lags of ±2 s on a 50 ms
|
|
209
|
+
grid; `cross_venue_impact` asks how much of each venue's 1-second price change its own and the
|
|
210
|
+
other venue's order flow explain, and whether either venue's flow or return predicts the other's
|
|
211
|
+
*next* second. Following the repo's rule, the estimators are first run where the answer is
|
|
212
|
+
known: a simulated venue B that copies venue A 300 ms late. They find the delay exactly
|
|
213
|
+
(correlation 1.00 at +300 ms) and the direction: only B's next move is predictable from A.
|
|
214
|
+
|
|
215
|
+
Same session as Study 3 (40 minutes; 76,296 Binance and 24,969 Bybit quote updates):
|
|
216
|
+
|
|
217
|
+
| Target venue | R² own OFI | R² other venue's OFI | R² both | Next 1 s from other's OFI (OOS) | Next 1 s from other's return (OOS) |
|
|
218
|
+
|---|---|---|---|---|---|
|
|
219
|
+
| Binance | 0.56 | 0.16 | 0.56 | 0.014 | 0.009 |
|
|
220
|
+
| Bybit | 0.58 | 0.28 | 0.60 | 0.004 | 0.004 |
|
|
221
|
+
|
|
222
|
+

|
|
223
|
+
|
|
224
|
+
**No exploitable lead at this resolution.** Returns are most correlated at 0 ms (0.09): the
|
|
225
|
+
venues move within the same 50 ms. Each venue's own order flow explains its price far better than
|
|
226
|
+
the other's. Neither venue's flow or return predicts the other's next second by more than about
|
|
227
|
+
1% out of sample. There is more correlation at negative lags (Bybit first, summed 0.62 against
|
|
228
|
+
0.20 for Binance first), and it persisted after the recorder's timestamp bug was fixed (see
|
|
229
|
+
CHANGELOG), but Bybit's price changed only 218 times, so this is a hypothesis for a longer
|
|
230
|
+
recording, not a finding. One limitation is built in: timestamps are local receive times, so each
|
|
231
|
+
venue's network latency to the recording machine is part of the measured lag. A lead shorter than
|
|
232
|
+
the difference in latencies can't be seen from one machine.
|
|
233
|
+
|
|
234
|
+
## Roadmap
|
|
235
|
+
|
|
236
|
+
- [x] **M1** Book sync, recorder, ZI simulator, OFI/imbalance analytics, Avellaneda–Stoikov replication
|
|
237
|
+
- [x] **M2** Multi-level OFI (Xu, Gould & Howison 2019) using the recorded L2 depth
|
|
238
|
+
- [x] **M3** Stoikov (2018) micro-price, estimated as a Markov chain on (imbalance, spread)
|
|
239
|
+
- [x] **M4** Run the Avellaneda–Stoikov quoter inside the order book simulator, with queue position and adverse selection
|
|
240
|
+
- [x] **M5** Cross-venue study: OFI and lead-lag between Binance and a second exchange (Bybit)
|
|
241
|
+
|
|
242
|
+
## References
|
|
243
|
+
|
|
244
|
+
- Avellaneda, M. & Stoikov, S. (2008). High-frequency trading in a limit order book. *Quantitative Finance* 8(3).
|
|
245
|
+
- Cont, R., Stoikov, S. & Talreja, R. (2010). A stochastic model for order book dynamics. *Operations Research* 58(3).
|
|
246
|
+
- Cont, R., Kukanov, A. & Stoikov, S. (2014). The price impact of order book events. *Journal of Financial Econometrics* 12(1).
|
|
247
|
+
- Gould, M. & Bonart, J. (2016). Queue imbalance as a one-tick-ahead price predictor in a limit order book. *Market Microstructure and Liquidity* 2(2).
|
|
248
|
+
- Stoikov, S. (2018). The micro-price: a high-frequency estimator of future prices. *Quantitative Finance* 18(12).
|
|
249
|
+
- Xu, K., Gould, M. D. & Howison, S. D. (2019). Multi-level order-flow imbalance in a limit order book. *Market Microstructure and Liquidity* 4(3–4).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"] # SPDX license expression (PEP 639)
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "lobkit"
|
|
7
|
+
version = "0.2.1"
|
|
8
|
+
description = "Limit order book reconstruction, order-flow analytics and market-making simulation"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
authors = [{name = "Yousuf Hossain Shafeen"}]
|
|
13
|
+
requires-python = ">=3.10"
|
|
14
|
+
keywords = ["market microstructure", "limit order book", "order flow imbalance", "market making",
|
|
15
|
+
"avellaneda-stoikov", "micro-price", "binance", "bybit"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
27
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
28
|
+
]
|
|
29
|
+
dependencies = ["numpy>=1.24", "pandas>=2.0"]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/hossainyousuf751/microstructure-lab"
|
|
33
|
+
Documentation = "https://github.com/hossainyousuf751/microstructure-lab#readme"
|
|
34
|
+
Changelog = "https://github.com/hossainyousuf751/microstructure-lab/blob/main/CHANGELOG.md"
|
|
35
|
+
Issues = "https://github.com/hossainyousuf751/microstructure-lab/issues"
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
plot = ["matplotlib>=3.7"]
|
|
39
|
+
live = ["websockets>=12", "requests>=2.28"]
|
|
40
|
+
dev = ["pytest>=7", "matplotlib>=3.7", "ruff>=0.5", "build>=1.2", "twine>=6"]
|
|
41
|
+
|
|
42
|
+
[tool.setuptools.packages.find]
|
|
43
|
+
where = ["src"]
|
|
44
|
+
|
|
45
|
+
[tool.pytest.ini_options]
|
|
46
|
+
testpaths = ["tests"]
|
|
47
|
+
markers = ["slow: takes more than a few seconds; deselect with -m \"not slow\""]
|
|
48
|
+
|
|
49
|
+
[tool.ruff]
|
|
50
|
+
line-length = 120
|
|
51
|
+
|
|
52
|
+
[tool.ruff.lint]
|
|
53
|
+
select = ["E", "F", "W", "B", "UP"]
|
|
54
|
+
ignore = ["B008"] # frozen dataclass defaults are safe
|
lobkit-0.2.1/setup.cfg
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""lobkit: limit order book reconstruction, order-flow analytics and market making."""
|
|
2
|
+
|
|
3
|
+
from lobkit.analysis import (
|
|
4
|
+
MicroPrice, RegressionResult, cross_venue_impact, estimate_microprice, impact_by_depth, imbalance_next_move,
|
|
5
|
+
lead_lag, microprice_forecast_error, multi_level_impact, ofi_price_impact, predictive_r2,
|
|
6
|
+
)
|
|
7
|
+
from lobkit.book import BinanceDepthSync, OrderBook, SequenceGap
|
|
8
|
+
from lobkit.features import bucket_features, l1_features, multi_level_ofi, order_flow_imbalance
|
|
9
|
+
from lobkit.market_making import ASParams, ASResult, optimal_spread, reservation_price, simulate_as
|
|
10
|
+
from lobkit.simulator import SimulationResult, simulate_lob
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"ASParams", "ASResult", "BinanceDepthSync", "MicroPrice", "OrderBook", "RegressionResult", "SequenceGap",
|
|
14
|
+
"SimulationResult", "bucket_features", "cross_venue_impact", "estimate_microprice", "imbalance_next_move",
|
|
15
|
+
"impact_by_depth", "l1_features", "lead_lag", "microprice_forecast_error", "multi_level_impact",
|
|
16
|
+
"multi_level_ofi", "ofi_price_impact", "optimal_spread", "order_flow_imbalance", "predictive_r2",
|
|
17
|
+
"reservation_price", "simulate_as", "simulate_lob",
|
|
18
|
+
]
|