# Orderbook
[![License](https://img.shields.io/badge/license-GLPv3-blue.svg)](LICENSE)
![Python](https://img.shields.io/badge/Python-3.8+-green.svg)
[![PyPi](https://img.shields.io/badge/PyPi-order--book-brightgreen)](https://pypi.python.org/pypi/order-book)
![coverage-lines](https://img.shields.io/badge/coverage%3A%20lines-84.6%25-blue)
![coverage-functions](https://img.shields.io/badge/coverage%3A%20functions-100%25-blue)
A ***fast*** L2/L3 orderbook data structure, in C, for Python
### Basic Usage
```python
from decimal import Decimal
import requests
from order_book import OrderBook
ob = OrderBook()
# get some orderbook data
data = requests.get("https://api.pro.coinbase.com/products/BTC-USD/book?level=2").json()
ob.bids = {Decimal(price): size for price, size, _ in data['bids']}
ob.asks = {Decimal(price): size for price, size, _ in data['asks']}
# OR
for side in data:
# there is additional data we need to ignore
if side in {'bids', 'asks'}:
ob[side] = {Decimal(price): size for price, size, _ in data[side]}
# Data is accessible by .index(), which returns a tuple of (price, size) at that level in the book
price, size = ob.bids.index(0)
print(f"Best bid price: {price} size: {size}")
price, size = ob.asks.index(0)
print(f"Best ask price: {price} size: {size}")
print(f"The spread is {ob.asks.index(0)[0] - ob.bids.index(0)[0]}\n\n")
# Data is accessible via iteration
# Note: bids/asks are iterators
print("Bids")
for price in ob.bids:
print(f"Price: {price} Size: {ob.bids[price]}")
print("\n\nAsks")
for price in ob.asks:
print(f"Price: {price} Size: {ob.asks[price]}")
# Data can be exported to a sorted dictionary
# In Python3.7+ dictionaries remain in insertion ordering. The
# dict returned by .to_dict() has had its keys inserted in sorted order
print("\n\nRaw asks dictionary")
print(ob.asks.to_dict())
# Data can also be exported as an ordered list
# .to_list() returns a list of (price, size) tuples
print("Top 5 Asks")
print(ob.asks.to_list()[:5])
print("\nTop 5 Bids")
print(ob.bids.to_list()[:5])
```
### Main Features
* Sides maintained in correct order
* Can perform orderbook checksums
* Supports max depth and depth truncation
### Installation
The preferable way to install is via `pip` - `pip install order-book`. Installing from source will require a compiler and can be done with setuptools: `python setup.py install`.
### Running code coverage
The script `coverage.sh` will compile the source using the `-coverage` `CFLAG`, run the unit tests, and build a coverage report in HTML. The script uses tools that may need to be installed (coverage, lcov, genhtml).
### Running the performance tests
You can run the performance tests like so: `python perf/performance_test.py`. The program will profile the time to run for random data samples of various sizes as well as the construction of a sorted orderbook using live L2 orderbook data from Coinbase.
The performance of constructing a sorted orderbook (using live data from Coinbase) using this C library, versus a pure Python sorted dictionary library:
| Library | Time, in seconds |
| ---------------| ---------------- |
| C Library | 0.00021767616271 |
| Python Library | 0.00043988227844 |
The performance of constructing sorted dictionaries using the same libraries, as well as the cost of building unsorted, python dictionaies for dictionaries of random floating point data:
| Library | Number of Keys | Time, in seconds |
| -------------- | -------------- | ---------------- |
| C Library | 100 | 0.00021600723266 |
| Python Library | 100 | 0.00044703483581 |
| Python Dict | 100 | 0.00022006034851 |
| C Library | 500 | 0.00103306770324 |
| Python Library | 500 | 0.00222206115722 |
| Python Dict | 500 | 0.00097918510437 |
| C Library | 1000 | 0.00202703475952 |
| Python Library | 1000 | 0.00423812866210 |
| Python Dict | 1000 | 0.00176715850830 |
This represents a roughly 2x speedup compared to a pure python implementation, and in many cases is close to the performance of an unsorted python dictionary.
For other performance metrics, run `performance_test.py` as well as the other performance tests in [`perf/`](perf/)
----
## Changelog
### 0.6.1 (2024-04-22)
* Update: to_list's behavior matches that of to_dict (respects max_depth, if set).
* Update: resolve build warnings on some compilers.
### 0.6.0 (2022-10-19)
* Update: Drop support for python 3.7
* Feature: to_list method
* Bugfix: Initialize iterator correctly
### 0.5.0 (2022-08-23)
* Bugfix: fix segmentation fault when calculating checksum on empty orderbook
* Bugfix: fix missing reference decrement
* Performance: Improvement to marking dirty keys
### 0.4.3 (2022-05-29)
* Bugfix: handle scientific notation of small values in Kraken checksum
* Update: calculate Kraken checksum on order books less than 10 levels deep
* Bugfix: fix occasional incorrect checksums for OKX, FTX and Bitget
### 0.4.2 (2022-04-17)
* Update: OKEx renamed OKX (for checksum validation)
* Feature: Add support for orderbook checksums with Bitget
### 0.4.1 (2021-10-12)
* Bugfix: unnecessary reference counting prevented sorted dictionaries from being deallocated
* Bugfix: setting ordering on a sorted dict before checking that it was created successfully
### 0.4.0 (2021-09-16)
* Feature: changes to code and setup.py to enable compiling on windows
* Feature: add from_type/to_type kwargs to the to_dict methods, allowing for type conversion when creating the dictionary
### 0.3.2 (2021-09-04)
* Bugfix: depth was incorrectly ignored when converting sorteddict to python dict
### 0.3.1 (2021-09-01)
* Bugfix: truncate and max_depth not being passed from orderbook to sorteddict object correctly
* Feature: let checksum_format kwarg be set to None
### 0.3.0 (2021-07-16)
* Update classifiers to indicate this projects only supports MacOS/Linux
* Bugfix: Using less than the minimum number of levels for a checksum with Kraken not raising error correctly
* Update: add del examples to test code
### 0.2.1 (2021-03-29)
* Bugfix: Invalid deallocation of python object
### 0.2.0 (2021-03-12)
* Feature: Add branch prediction hints around error handling code
* Bugfix: Fix regression from adding branch predictors
* Bugfix: Fix error corner case when iterating twice on an empty dataset
* Feature: Add contains function for membership test
* Bugfix: Fix issues around storing L3 data
* Feature: Enhance testing, add in L3 book test cases
### 0.1.1 (2021-02-12)
* Feature: Checksum support for orderbooks
* Feature: FTX checksum support
* Feature: Kraken checksum support
* Feature: OkEX/OKCoin checksum support
* Perf: Use CRC32 table to improve performance of checksum code
### 0.1.0 (2021-01-18)
* Minor: Use enums to make code more readable
* Bugfix: Add manifest file to ensure headers and changes file are included in sdist builds
* Feature: Add support for max depth and depth truncation
### 0.0.2 (2020-12-27)
* Bugfix: Fix sorted dictionary arg parsing
* Feature: Coverage report generation for C library
* Bugfix: Fix reference counting in index method in SortedDict
* Feature: New unit tests to improve SortedDict coverage
* Feature: Modularize files
* Feature: Add ability to set bids/asks to dictionaries via attributes or \[ \]
* Docs: Update README with simple usage example
### 0.0.1 (2020-12-26)
* Initial Release
Raw data
{
"_id": null,
"home_page": "https://github.com/bmoscon/orderbook",
"name": "order-book",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "market data, trading",
"author": "Bryant Moscon",
"author_email": "bmoscon@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/ca/7e/a118618ff5cb05040a27f3f1c6325c7324e998a90d3635b6f4b557f89f06/order_book-0.6.1.tar.gz",
"platform": null,
"description": "# Orderbook\n\n[![License](https://img.shields.io/badge/license-GLPv3-blue.svg)](LICENSE)\n![Python](https://img.shields.io/badge/Python-3.8+-green.svg)\n[![PyPi](https://img.shields.io/badge/PyPi-order--book-brightgreen)](https://pypi.python.org/pypi/order-book)\n![coverage-lines](https://img.shields.io/badge/coverage%3A%20lines-84.6%25-blue)\n![coverage-functions](https://img.shields.io/badge/coverage%3A%20functions-100%25-blue)\n\n\nA ***fast*** L2/L3 orderbook data structure, in C, for Python\n\n\n### Basic Usage\n\n```python\nfrom decimal import Decimal\n\nimport requests\nfrom order_book import OrderBook\n\nob = OrderBook()\n\n# get some orderbook data\ndata = requests.get(\"https://api.pro.coinbase.com/products/BTC-USD/book?level=2\").json()\n\nob.bids = {Decimal(price): size for price, size, _ in data['bids']}\nob.asks = {Decimal(price): size for price, size, _ in data['asks']}\n\n# OR\n\nfor side in data:\n # there is additional data we need to ignore\n if side in {'bids', 'asks'}:\n ob[side] = {Decimal(price): size for price, size, _ in data[side]}\n\n\n# Data is accessible by .index(), which returns a tuple of (price, size) at that level in the book\nprice, size = ob.bids.index(0)\nprint(f\"Best bid price: {price} size: {size}\")\n\nprice, size = ob.asks.index(0)\nprint(f\"Best ask price: {price} size: {size}\")\n\nprint(f\"The spread is {ob.asks.index(0)[0] - ob.bids.index(0)[0]}\\n\\n\")\n\n# Data is accessible via iteration\n# Note: bids/asks are iterators\n\nprint(\"Bids\")\nfor price in ob.bids:\n print(f\"Price: {price} Size: {ob.bids[price]}\")\n\n\nprint(\"\\n\\nAsks\")\nfor price in ob.asks:\n print(f\"Price: {price} Size: {ob.asks[price]}\")\n\n\n# Data can be exported to a sorted dictionary\n# In Python3.7+ dictionaries remain in insertion ordering. The\n# dict returned by .to_dict() has had its keys inserted in sorted order\nprint(\"\\n\\nRaw asks dictionary\")\nprint(ob.asks.to_dict())\n\n\n# Data can also be exported as an ordered list\n# .to_list() returns a list of (price, size) tuples\nprint(\"Top 5 Asks\")\nprint(ob.asks.to_list()[:5])\nprint(\"\\nTop 5 Bids\")\nprint(ob.bids.to_list()[:5])\n\n```\n\n### Main Features\n\n* Sides maintained in correct order\n* Can perform orderbook checksums\n* Supports max depth and depth truncation\n\n\n### Installation\n\nThe preferable way to install is via `pip` - `pip install order-book`. Installing from source will require a compiler and can be done with setuptools: `python setup.py install`. \n\n\n### Running code coverage\n\nThe script `coverage.sh` will compile the source using the `-coverage` `CFLAG`, run the unit tests, and build a coverage report in HTML. The script uses tools that may need to be installed (coverage, lcov, genhtml).\n\n\n### Running the performance tests\n\nYou can run the performance tests like so: `python perf/performance_test.py`. The program will profile the time to run for random data samples of various sizes as well as the construction of a sorted orderbook using live L2 orderbook data from Coinbase.\n\nThe performance of constructing a sorted orderbook (using live data from Coinbase) using this C library, versus a pure Python sorted dictionary library:\n\n\n| Library | Time, in seconds |\n| ---------------| ---------------- |\n| C Library | 0.00021767616271 |\n| Python Library | 0.00043988227844 |\n\nThe performance of constructing sorted dictionaries using the same libraries, as well as the cost of building unsorted, python dictionaies for dictionaries of random floating point data:\n\n\n| Library | Number of Keys | Time, in seconds |\n| -------------- | -------------- | ---------------- |\n| C Library | 100 | 0.00021600723266 |\n| Python Library | 100 | 0.00044703483581 |\n| Python Dict | 100 | 0.00022006034851 |\n| C Library | 500 | 0.00103306770324 |\n| Python Library | 500 | 0.00222206115722 |\n| Python Dict | 500 | 0.00097918510437 |\n| C Library | 1000 | 0.00202703475952 |\n| Python Library | 1000 | 0.00423812866210 |\n| Python Dict | 1000 | 0.00176715850830 |\n\n\nThis represents a roughly 2x speedup compared to a pure python implementation, and in many cases is close to the performance of an unsorted python dictionary.\n\n\nFor other performance metrics, run `performance_test.py` as well as the other performance tests in [`perf/`](perf/)\n\n\n----\n\n## Changelog\n\n### 0.6.1 (2024-04-22)\n * Update: to_list's behavior matches that of to_dict (respects max_depth, if set).\n * Update: resolve build warnings on some compilers.\n\n### 0.6.0 (2022-10-19)\n * Update: Drop support for python 3.7\n * Feature: to_list method\n * Bugfix: Initialize iterator correctly\n\n### 0.5.0 (2022-08-23)\n * Bugfix: fix segmentation fault when calculating checksum on empty orderbook\n * Bugfix: fix missing reference decrement\n * Performance: Improvement to marking dirty keys\n\n### 0.4.3 (2022-05-29)\n * Bugfix: handle scientific notation of small values in Kraken checksum\n * Update: calculate Kraken checksum on order books less than 10 levels deep\n * Bugfix: fix occasional incorrect checksums for OKX, FTX and Bitget\n\n### 0.4.2 (2022-04-17)\n * Update: OKEx renamed OKX (for checksum validation)\n * Feature: Add support for orderbook checksums with Bitget\n\n### 0.4.1 (2021-10-12)\n * Bugfix: unnecessary reference counting prevented sorted dictionaries from being deallocated\n * Bugfix: setting ordering on a sorted dict before checking that it was created successfully\n\n### 0.4.0 (2021-09-16)\n * Feature: changes to code and setup.py to enable compiling on windows\n * Feature: add from_type/to_type kwargs to the to_dict methods, allowing for type conversion when creating the dictionary\n\n### 0.3.2 (2021-09-04)\n * Bugfix: depth was incorrectly ignored when converting sorteddict to python dict\n\n### 0.3.1 (2021-09-01)\n * Bugfix: truncate and max_depth not being passed from orderbook to sorteddict object correctly\n * Feature: let checksum_format kwarg be set to None\n\n### 0.3.0 (2021-07-16)\n * Update classifiers to indicate this projects only supports MacOS/Linux\n * Bugfix: Using less than the minimum number of levels for a checksum with Kraken not raising error correctly\n * Update: add del examples to test code\n\n### 0.2.1 (2021-03-29)\n * Bugfix: Invalid deallocation of python object\n\n### 0.2.0 (2021-03-12)\n * Feature: Add branch prediction hints around error handling code\n * Bugfix: Fix regression from adding branch predictors\n * Bugfix: Fix error corner case when iterating twice on an empty dataset\n * Feature: Add contains function for membership test\n * Bugfix: Fix issues around storing L3 data\n * Feature: Enhance testing, add in L3 book test cases\n\n### 0.1.1 (2021-02-12)\n * Feature: Checksum support for orderbooks\n * Feature: FTX checksum support\n * Feature: Kraken checksum support\n * Feature: OkEX/OKCoin checksum support\n * Perf: Use CRC32 table to improve performance of checksum code\n\n### 0.1.0 (2021-01-18)\n * Minor: Use enums to make code more readable\n * Bugfix: Add manifest file to ensure headers and changes file are included in sdist builds\n * Feature: Add support for max depth and depth truncation\n\n### 0.0.2 (2020-12-27)\n * Bugfix: Fix sorted dictionary arg parsing\n * Feature: Coverage report generation for C library\n * Bugfix: Fix reference counting in index method in SortedDict\n * Feature: New unit tests to improve SortedDict coverage\n * Feature: Modularize files\n * Feature: Add ability to set bids/asks to dictionaries via attributes or \\[ \\]\n * Docs: Update README with simple usage example\n\n### 0.0.1 (2020-12-26)\n * Initial Release\n",
"bugtrack_url": null,
"license": "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"summary": "A fast orderbook implementation, in C, for Python",
"version": "0.6.1",
"project_urls": {
"Homepage": "https://github.com/bmoscon/orderbook"
},
"split_keywords": [
"market data",
" trading"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "945b882abb8428331617e5c4e89dae807f4c06ca057d78efd250c4a03d805796",
"md5": "72805f1224b2f898f90cb2a16112bbaf",
"sha256": "bf67e524677145562d24cead7a0d79003a8c6d88216e4d109a49501b65693f90"
},
"downloads": -1,
"filename": "order_book-0.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
"has_sig": false,
"md5_digest": "72805f1224b2f898f90cb2a16112bbaf",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": null,
"size": 62151,
"upload_time": "2024-04-23T00:14:43",
"upload_time_iso_8601": "2024-04-23T00:14:43.909080Z",
"url": "https://files.pythonhosted.org/packages/94/5b/882abb8428331617e5c4e89dae807f4c06ca057d78efd250c4a03d805796/order_book-0.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "be09cc7d0f957c1f39762f294d8365d60e1a6a9ccc4ca0a34d73dba2e27cc148",
"md5": "305d64052236cfb3382a0174b1f85946",
"sha256": "eefb640d3b1e408a458df047d6b68954d95e6c7a5287c06318a641e019ce746c"
},
"downloads": -1,
"filename": "order_book-0.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
"has_sig": false,
"md5_digest": "305d64052236cfb3382a0174b1f85946",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": null,
"size": 63483,
"upload_time": "2024-04-23T00:14:45",
"upload_time_iso_8601": "2024-04-23T00:14:45.222528Z",
"url": "https://files.pythonhosted.org/packages/be/09/cc7d0f957c1f39762f294d8365d60e1a6a9ccc4ca0a34d73dba2e27cc148/order_book-0.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "cb4c1b9854b19dc9738d6398786089f5f7a411d28b55b3942ac950a6f7e3ea03",
"md5": "097732d1ad42744735a82fe8e243fb89",
"sha256": "f2c64369d4404614b5a7fdd3687c52e79515d9bac737d70b222527554930542e"
},
"downloads": -1,
"filename": "order_book-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "097732d1ad42744735a82fe8e243fb89",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": null,
"size": 26747,
"upload_time": "2024-04-23T00:15:04",
"upload_time_iso_8601": "2024-04-23T00:15:04.289399Z",
"url": "https://files.pythonhosted.org/packages/cb/4c/1b9854b19dc9738d6398786089f5f7a411d28b55b3942ac950a6f7e3ea03/order_book-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9bb48e4cf9fe1c9c73ce21963b6d5c1005551d4fa6bb4093cadad4c0875574d1",
"md5": "1d5a5b6ae64b443876e819ec1fcede2e",
"sha256": "285e4046751e2aaf0edc3b180fc229c2b316723d9332bcac4575a84ae90090b6"
},
"downloads": -1,
"filename": "order_book-0.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
"has_sig": false,
"md5_digest": "1d5a5b6ae64b443876e819ec1fcede2e",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": null,
"size": 66768,
"upload_time": "2024-04-23T00:14:46",
"upload_time_iso_8601": "2024-04-23T00:14:46.898273Z",
"url": "https://files.pythonhosted.org/packages/9b/b4/8e4cf9fe1c9c73ce21963b6d5c1005551d4fa6bb4093cadad4c0875574d1/order_book-0.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ca7ea118618ff5cb05040a27f3f1c6325c7324e998a90d3635b6f4b557f89f06",
"md5": "2526c04d22f54da171ad800ec40ac79f",
"sha256": "636cee1e6b9b74afd623797ff62a8decbf6de28db398d4a818ff9e73128f9f21"
},
"downloads": -1,
"filename": "order_book-0.6.1.tar.gz",
"has_sig": false,
"md5_digest": "2526c04d22f54da171ad800ec40ac79f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 34054,
"upload_time": "2024-04-23T00:15:05",
"upload_time_iso_8601": "2024-04-23T00:15:05.660791Z",
"url": "https://files.pythonhosted.org/packages/ca/7e/a118618ff5cb05040a27f3f1c6325c7324e998a90d3635b6f4b557f89f06/order_book-0.6.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-23 00:15:05",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "bmoscon",
"github_project": "orderbook",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "order-book"
}