{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Collecting ninjabook\n", " Downloading ninjabook-0.1.6-cp38-abi3-macosx_11_0_arm64.whl.metadata (429 bytes)\n", "Collecting tabulate\n", " Using cached tabulate-0.9.0-py3-none-any.whl.metadata (34 kB)\n", "Downloading ninjabook-0.1.6-cp38-abi3-macosx_11_0_arm64.whl (217 kB)\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m217.2/217.2 kB\u001b[0m \u001b[31m6.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[?25hUsing cached tabulate-0.9.0-py3-none-any.whl (35 kB)\n", "Installing collected packages: tabulate, ninjabook\n", " Attempting uninstall: tabulate\n", " Found existing installation: tabulate 0.9.0\n", " Uninstalling tabulate-0.9.0:\n", " Successfully uninstalled tabulate-0.9.0\n", " Attempting uninstall: ninjabook\n", " Found existing installation: ninjabook 0.1.5\n", " Uninstalling ninjabook-0.1.5:\n", " Successfully uninstalled ninjabook-0.1.5\n", "Successfully installed ninjabook-0.1.6 tabulate-0.9.0\n", "\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n", "Note: you may need to restart the kernel to use updated packages.\n" ] } ], "source": [ "%pip install ninjabook tabulate --force-reinstall" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Parsing raw data into `Event`" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "300000" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import csv\n", "from ninjabook import Event\n", "\n", "events = []\n", "with open(\"../data/norm_book_data_300k.csv\", newline='') as csvfile:\n", " reader = csv.DictReader(csvfile)\n", " for row in reader:\n", " event = Event(\n", " timestamp= int(row['timestamp']),\n", " seq=int(row['seq']),\n", " is_trade=bool(row['is_trade']=='1'),\n", " is_buy=bool(row['is_buy']=='1'),\n", " price=float(row['price']),\n", " size=float(row['size'])\n", " )\n", " events.append(event)\n", "\n", "len(events)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Ingesting `Events` and streaming BBO" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+------------------+--------+---------------+---------------+---------+---------------+---------------+\n", "| ts | seq | best_bid_sz | best_bid_px | mid | best_ask_px | best_ask_sz |\n", "+==================+========+===============+===============+=========+===============+===============+\n", "| 1575161162310275 | 199955 | 0.019027 | 7490.55 | 7491.39 | 7492.22 | 0.204504 |\n", "+------------------+--------+---------------+---------------+---------+---------------+---------------+\n", "| 1575161162409739 | 199968 | 0.019027 | 7490.55 | 7491.35 | 7492.16 | 0.019353 |\n", "+------------------+--------+---------------+---------------+---------+---------------+---------------+\n", "| 1575161162509896 | 199980 | 0.019027 | 7490.55 | 7491.33 | 7492.1 | 0.3 |\n", "+------------------+--------+---------------+---------------+---------+---------------+---------------+\n", "| 1575161162610363 | 199987 | 0.019027 | 7490.55 | 7491.29 | 7492.03 | 0.211905 |\n", "+------------------+--------+---------------+---------------+---------+---------------+---------------+\n", "| 1575161162710305 | 199997 | 0.019027 | 7490.55 | 7491.27 | 7491.99 | 0.214587 |\n", "+------------------+--------+---------------+---------------+---------+---------------+---------------+\n" ] } ], "source": [ "from ninjabook import Orderbook \n", "from tabulate import tabulate \n", "\n", "ob = Orderbook(0.01)\n", "\n", "data = []\n", "\n", "for event in events[:200_000]:\n", " bbo = ob.process_stream_bbo(event)\n", " if bbo != None:\n", " best_bid_px = bbo[0].price if bbo[0] is not None else None\n", " best_bid_sz = bbo[0].size if bbo[0] is not None else None\n", " best_ask_px = bbo[1].price if bbo[1] is not None else None\n", " best_ask_sz = bbo[1].size if bbo[1] is not None else None\n", " mid = ob.midprice()\n", " data.append([ob.last_updated, ob.last_sequence, best_bid_sz, best_bid_px, mid, best_ask_px, best_ask_sz])\n", "\n", "headers = [\"ts\", \"seq\", \"best_bid_sz\", \"best_bid_px\", \"mid\", \"best_ask_px\", \"best_ask_sz\"]\n", "\n", "print(tabulate(data[-5:], headers=headers, tablefmt=\"grid\"))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Processing `Events` and getting top 3 bids and asks" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "last sequence: 199999\n", "+---------------+---------------+---------+---------------+---------------+\n", "| best_bid_sz | best_bid_px | mid | best_ask_px | best_ask_sz |\n", "+===============+===============+=========+===============+===============+\n", "| | | | 7492.02 | 4 |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| | | | 7492.01 | 0.149845 |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| | | | 7491.99 | 0.214587 |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| | | 7491.27 | | |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| 0.019027 | 7490.55 | | | |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| 0.812102 | 7490.19 | | | |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| 0.401352 | 7490.1 | | | |\n", "+---------------+---------------+---------+---------------+---------------+\n" ] } ], "source": [ "from ninjabook import Orderbook\n", "from tabulate import tabulate \n", "\n", "ob = Orderbook(0.01)\n", "\n", "for event in events[:200_000]:\n", " ob.process(event)\n", " \n", "data = []\n", "\n", "for ask in sorted(ob.top_asks(3), key=lambda x: x.price, reverse=True):\n", " data.append([None, None, None, ask.price, ask.size])\n", " \n", "data.append([None, None, ob.midprice(), None, None])\n", "\n", "for bid in ob.top_bids(3):\n", " data.append([bid.size, bid.price, None, None, None])\n", " \n", "headers = [\"best_bid_sz\", \"best_bid_px\", \"mid\", \"best_ask_px\", \"best_ask_sz\"]\n", "\n", "print(\"last sequence:\", ob.last_sequence)\n", "print(tabulate(data, headers=headers, tablefmt=\"grid\"))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Processing raw events without using `Event`" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "last sequence: 299999\n", "+---------------+---------------+---------+---------------+---------------+\n", "| best_bid_sz | best_bid_px | mid | best_ask_px | best_ask_sz |\n", "+===============+===============+=========+===============+===============+\n", "| | | | 7451.03 | 2.57563 |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| | | | 7451.02 | 1.11018 |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| | | | 7451.01 | 3.9983 |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| | | 7450.36 | | |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| 0.00279 | 7449.71 | | | |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| 2 | 7447.44 | | | |\n", "+---------------+---------------+---------+---------------+---------------+\n", "| 0.531638 | 7447.43 | | | |\n", "+---------------+---------------+---------+---------------+---------------+\n" ] } ], "source": [ "from tabulate import tabulate \n", "\n", "from ninjabook import Orderbook\n", "\n", "\n", "ob = Orderbook(0.01) # tick_size = 0.01\n", "\n", "for raw in events:\n", " ob.process_raw(\n", " raw.timestamp, \n", " raw.seq, \n", " raw.is_trade, \n", " raw.is_buy, \n", " raw.price, \n", " raw.size\n", " )\n", " \n", "data = []\n", "\n", "for ask in sorted(ob.top_asks(3), key=lambda x: x.price, reverse=True):\n", " data.append([None, None, None, ask.price, ask.size])\n", " \n", "data.append([None, None, ob.midprice(), None, None])\n", "\n", "for bid in ob.top_bids(3):\n", " data.append([bid.size, bid.price, None, None, None])\n", " \n", "headers = [\"best_bid_sz\", \"best_bid_px\", \"mid\", \"best_ask_px\", \"best_ask_sz\"]\n", "\n", "print(\"last sequence:\", ob.last_sequence)\n", "print(tabulate(data, headers=headers, tablefmt=\"grid\"))\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.4" } }, "nbformat": 4, "nbformat_minor": 2 }