{ "cells": [ { "cell_type": "markdown", "id": "c4ce8bd1-58dc-46f5-b290-20d07185e2f0", "metadata": {}, "source": [ "# Order Book Analytics" ] }, { "cell_type": "markdown", "id": "61ba94e2-c191-459c-a5ca-7413cd01ec36", "metadata": { "tags": [] }, "source": [ "`onetick-py` offers functions for analyzing tick-by-tick order book. There are three representations of an order book. We'll show top 3 levels only for ease of exposition.\n", "\n", "A book can be displayed with a tick per level per side. We refer to a level in the book as a 'price level' or 'prl'." ] }, { "cell_type": "code", "execution_count": 1, "id": "0ebfd093-d330-4244-a383-1e1f42f30547", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimePRICEUPDATE_TIMESIZELEVELBUY_SELL_FLAG
02022-03-02 10:00:0014092.002022-03-02 09:59:59.928574271111
12022-03-02 10:00:0014092.252022-03-02 09:59:59.901649655321
22022-03-02 10:00:0014092.502022-03-02 09:59:59.873574571231
32022-03-02 10:00:0014090.752022-03-02 09:59:59.923928381310
42022-03-02 10:00:0014090.502022-03-02 09:59:59.923521093320
52022-03-02 10:00:0014090.252022-03-02 09:59:59.924031067430
\n", "
" ], "text/plain": [ " Time PRICE UPDATE_TIME SIZE LEVEL BUY_SELL_FLAG\n", "0 2022-03-02 10:00:00 14092.00 2022-03-02 09:59:59.928574271 1 1 1\n", "1 2022-03-02 10:00:00 14092.25 2022-03-02 09:59:59.901649655 3 2 1\n", "2 2022-03-02 10:00:00 14092.50 2022-03-02 09:59:59.873574571 2 3 1\n", "3 2022-03-02 10:00:00 14090.75 2022-03-02 09:59:59.923928381 3 1 0\n", "4 2022-03-02 10:00:00 14090.50 2022-03-02 09:59:59.923521093 3 2 0\n", "5 2022-03-02 10:00:00 14090.25 2022-03-02 09:59:59.924031067 4 3 0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import onetick.py as otp\n", "\n", "snapshot_time=otp.dt(2022, 3, 2, 10)\n", "prl = otp.ObSnapshot(db='CME', tick_type='PRL_FULL', max_levels=3) \n", "otp.run(prl, symbols='NQ\\H22', start=snapshot_time, end=snapshot_time)" ] }, { "cell_type": "markdown", "id": "0dc1c79a-86ba-4409-a335-ec3d300017f2", "metadata": {}, "source": [ "Alternatively, a book can show a tick per level with both ask and bid price/size info." ] }, { "cell_type": "code", "execution_count": 3, "id": "23c0f013-63d4-4365-a78c-930e3a84399d", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimeBID_PRICEBID_UPDATE_TIMEBID_SIZEASK_PRICEASK_UPDATE_TIMEASK_SIZELEVEL
02022-03-02 10:00:0014090.752022-03-02 09:59:59.923928381314092.002022-03-02 09:59:59.92857427111
12022-03-02 10:00:0014090.502022-03-02 09:59:59.923521093314092.252022-03-02 09:59:59.90164965532
22022-03-02 10:00:0014090.252022-03-02 09:59:59.924031067414092.502022-03-02 09:59:59.87357457123
\n", "
" ], "text/plain": [ " Time BID_PRICE BID_UPDATE_TIME BID_SIZE ASK_PRICE ASK_UPDATE_TIME ASK_SIZE LEVEL\n", "0 2022-03-02 10:00:00 14090.75 2022-03-02 09:59:59.923928381 3 14092.00 2022-03-02 09:59:59.928574271 1 1\n", "1 2022-03-02 10:00:00 14090.50 2022-03-02 09:59:59.923521093 3 14092.25 2022-03-02 09:59:59.901649655 3 2\n", "2 2022-03-02 10:00:00 14090.25 2022-03-02 09:59:59.924031067 4 14092.50 2022-03-02 09:59:59.873574571 2 3" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "snapshot_time=otp.dt(2022, 3, 2, 10)\n", "prl = otp.ObSnapshotWide(db='CME', tick_type='PRL_FULL', max_levels=3) \n", "otp.run(prl, symbols='NQ\\H22', start=snapshot_time, end=snapshot_time)" ] }, { "cell_type": "markdown", "id": "4c013e5c-2958-4b08-86e3-18fb07df015e", "metadata": {}, "source": [ "Finally, all levels can be displayed in one tick." ] }, { "cell_type": "code", "execution_count": 4, "id": "92e19c89-78f4-4f9b-a8ba-20080e62f367", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Time BID_PRICE1 BID_UPDATE_TIME1 BID_SIZE1 ASK_PRICE1 ASK_UPDATE_TIME1 ASK_SIZE1 BID_PRICE2 BID_UPDATE_TIME2 BID_SIZE2 ASK_PRICE2 ASK_UPDATE_TIME2 ASK_SIZE2 BID_PRICE3 BID_UPDATE_TIME3 BID_SIZE3 ASK_PRICE3 ASK_UPDATE_TIME3 ASK_SIZE3\n", "0 2022-03-02 10:00:00 14090.75 2022-03-02 09:59:59.923928381 3 14092.0 2022-03-02 09:59:59.928574271 1 14090.5 2022-03-02 09:59:59.923521093 3 14092.25 2022-03-02 09:59:59.901649655 3 14090.25 2022-03-02 09:59:59.924031067 4 14092.5 2022-03-02 09:59:59.873574571 2\n" ] } ], "source": [ "snapshot_time=otp.dt(2022, 3, 2, 10)\n", "prl = otp.ObSnapshotFlat(db='CME', tick_type='PRL_FULL', max_levels=3) \n", "print(otp.run(prl, symbols='NQ\\H22', start=snapshot_time, end=snapshot_time))" ] }, { "cell_type": "markdown", "id": "621e5e61-c69c-4bad-9b95-81aef68fb6df", "metadata": {}, "source": [ "We can output the book (in any of the three representation) on every change to price/size at any of the levels." ] }, { "cell_type": "code", "execution_count": 7, "id": "ccf59231-77dc-43b6-935a-f87fd0ef1456", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Time BID_PRICE1 BID_SIZE1 ASK_PRICE1 ASK_SIZE1 BID_PRICE2 BID_SIZE2 ASK_PRICE2 ASK_SIZE2 BID_PRICE3 BID_SIZE3 ASK_PRICE3 ASK_SIZE3\n", "0 2022-03-02 10:00:00.000000000 14090.75 3 14092.00 1 14090.50 3 14092.25 3 14090.25 4 14092.50 2\n", "1 2022-03-02 10:00:00.005759409 14091.00 1 14092.00 1 14090.75 3 14092.25 3 14090.50 3 14092.50 2\n", "2 2022-03-02 10:00:00.005759583 14091.00 1 14092.25 3 14090.75 3 14092.50 2 14090.50 3 14092.75 2\n", "3 2022-03-02 10:00:00.005837891 14091.00 1 14092.25 2 14090.75 3 14092.50 2 14090.50 3 14092.75 2\n", "4 2022-03-02 10:00:00.006117137 14091.25 1 14092.25 2 14091.00 1 14092.50 2 14090.75 3 14092.75 2\n", "5 2022-03-02 10:00:00.006155241 14091.25 1 14092.25 2 14091.00 1 14092.50 3 14090.75 3 14092.75 2\n", "6 2022-03-02 10:00:00.006287769 14091.25 1 14092.25 1 14091.00 1 14092.50 3 14090.75 3 14092.75 2\n", "7 2022-03-02 10:00:00.006485627 14091.00 1 14092.25 1 14090.75 3 14092.50 3 14090.50 3 14092.75 2\n", "8 2022-03-02 10:00:00.006542011 14091.00 1 14092.25 1 14090.75 3 14092.50 2 14090.50 3 14092.75 2\n", "9 2022-03-02 10:00:00.006551707 14091.00 1 14092.25 1 14090.75 3 14092.50 1 14090.50 3 14092.75 2\n", "10 2022-03-02 10:00:00.006736777 14091.00 1 14092.25 2 14090.75 3 14092.50 1 14090.50 3 14092.75 2\n", "11 2022-03-02 10:00:00.006802977 14091.00 1 14092.25 3 14090.75 3 14092.50 1 14090.50 3 14092.75 2\n", "12 2022-03-02 10:00:00.006955737 14091.00 1 14092.25 3 14090.75 3 14092.50 2 14090.50 3 14092.75 2\n", "13 2022-03-02 10:00:00.015703265 14091.00 1 14092.25 2 14090.75 3 14092.50 2 14090.50 3 14092.75 2\n" ] } ], "source": [ "prl = otp.ObSnapshotFlat(db='CME', tick_type='PRL_FULL', max_levels=3, running=True)\n", "prl = prl.drop(r\".+TIME\\d\")\n", "print(otp.run(prl, symbols='NQ\\H22', start=otp.dt(2022, 3, 2, 10), end=otp.dt(2022, 3, 2, 10)+otp.Milli(100)))" ] }, { "cell_type": "markdown", "id": "0543a589-233a-40c3-a232-039f6e4f266c", "metadata": {}, "source": [ "The `ObSnapshot` method doesn't require specifying `max_levels`. The entire book is returned when the parameter is not specified." ] }, { "cell_type": "code", "execution_count": 9, "id": "bc86f6d1-a58f-49e8-9498-b274d2537815", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimePRICEUPDATE_TIMESIZELEVELBUY_SELL_FLAG
02022-03-02 10:00:0014092.002022-03-02 09:59:59.928574271111
12022-03-02 10:00:0014092.252022-03-02 09:59:59.901649655321
22022-03-02 10:00:0014092.502022-03-02 09:59:59.873574571231
32022-03-02 10:00:0014092.752022-03-02 09:59:59.699031867241
42022-03-02 10:00:0014093.002022-03-02 09:59:59.901890847451
.....................
15672022-03-02 10:00:006490.002022-03-01 22:59:59.99900000038310
15682022-03-02 10:00:001586.002022-03-01 22:59:59.99900000018320
15692022-03-02 10:00:00786.502022-03-01 22:59:59.99900000018330
15702022-03-02 10:00:00200.002022-03-01 22:59:59.99900000018340
15712022-03-02 10:00:001.002022-03-01 22:59:59.99900000018350
\n", "

1572 rows × 6 columns

\n", "
" ], "text/plain": [ " Time PRICE UPDATE_TIME SIZE LEVEL BUY_SELL_FLAG\n", "0 2022-03-02 10:00:00 14092.00 2022-03-02 09:59:59.928574271 1 1 1\n", "1 2022-03-02 10:00:00 14092.25 2022-03-02 09:59:59.901649655 3 2 1\n", "2 2022-03-02 10:00:00 14092.50 2022-03-02 09:59:59.873574571 2 3 1\n", "3 2022-03-02 10:00:00 14092.75 2022-03-02 09:59:59.699031867 2 4 1\n", "4 2022-03-02 10:00:00 14093.00 2022-03-02 09:59:59.901890847 4 5 1\n", "... ... ... ... ... ... ...\n", "1567 2022-03-02 10:00:00 6490.00 2022-03-01 22:59:59.999000000 3 831 0\n", "1568 2022-03-02 10:00:00 1586.00 2022-03-01 22:59:59.999000000 1 832 0\n", "1569 2022-03-02 10:00:00 786.50 2022-03-01 22:59:59.999000000 1 833 0\n", "1570 2022-03-02 10:00:00 200.00 2022-03-01 22:59:59.999000000 1 834 0\n", "1571 2022-03-02 10:00:00 1.00 2022-03-01 22:59:59.999000000 1 835 0\n", "\n", "[1572 rows x 6 columns]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "snapshot_time=otp.dt(2022, 3, 2, 10)\n", "prl = otp.ObSnapshot(db='CME', tick_type='PRL_FULL') \n", "otp.run(prl, symbols='NQ\\H22', start=snapshot_time, end=snapshot_time)" ] }, { "cell_type": "markdown", "id": "d020114d-c9fa-47da-be2d-2802b2695423", "metadata": {}, "source": [ "## Book Imbalance\n", "\n", "Let's find the time weighted book imbalance. The imbalance at a given time is defined as the sum of the bid sizes at the top x levels minus the sum of the ask sizes at the top x levels divided by the sum of these two terms: the values close to 1 mean the book is much heavier on the bid side, close to -1 -- on the ask side, equal to zero means the sizes are the same." ] }, { "cell_type": "code", "execution_count": 15, "id": "313a302c-e485-4f47-82cb-9baeb8c6bc8b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Time BID_PRICE BID_UPDATE_TIME BID_SIZE ASK_PRICE ASK_UPDATE_TIME ASK_SIZE LEVEL\n", "0 2022-03-02 10:00:00.000000000 14090.75 2022-03-02 09:59:59.923928381 3 14092.00 2022-03-02 09:59:59.928574271 1 1\n", "1 2022-03-02 10:00:00.000000000 14090.50 2022-03-02 09:59:59.923521093 3 14092.25 2022-03-02 09:59:59.901649655 3 2\n", "2 2022-03-02 10:00:00.000000000 14090.25 2022-03-02 09:59:59.924031067 4 14092.50 2022-03-02 09:59:59.873574571 2 3\n", "3 2022-03-02 10:00:00.005759409 14091.00 2022-03-02 10:00:00.005759409 1 14092.00 2022-03-02 09:59:59.928574271 1 1\n", "4 2022-03-02 10:00:00.005759409 14090.75 2022-03-02 09:59:59.923928381 3 14092.25 2022-03-02 09:59:59.901649655 3 2\n", "5 2022-03-02 10:00:00.005759409 14090.50 2022-03-02 09:59:59.923521093 3 14092.50 2022-03-02 09:59:59.873574571 2 3\n", "6 2022-03-02 10:00:00.005759583 14091.00 2022-03-02 10:00:00.005759409 1 14092.25 2022-03-02 09:59:59.901649655 3 1\n", " Time ask_vol bid_vol imb\n", "0 2022-03-02 10:00:00.000000000 6 10 0.250000\n", "1 2022-03-02 10:00:00.005759409 6 7 0.076923\n", "2 2022-03-02 10:00:00.005759583 7 7 0.000000\n", "3 2022-03-02 10:00:00.005837891 6 7 0.076923\n", "4 2022-03-02 10:00:00.006117137 6 5 -0.090909\n", " Time tw_imb mean stdev\n", "0 2022-03-02 10:00:00.100 0.079814 0.063728 0.12232\n" ] } ], "source": [ "x = 3\n", "\n", "prl = otp.ObSnapshotWide(db='CME', tick_type='PRL_FULL', max_levels=x, running=True)\n", "prls_df = otp.run(prl, symbols='NQ\\H22', start=otp.dt(2022, 3, 2, 10), end=otp.dt(2022, 3, 2, 10)+otp.Milli(100))\n", "print(prls_df.head(7))\n", "\n", "prl = prl.agg({'ask_vol': otp.agg.sum('ASK_SIZE'), 'bid_vol': otp.agg.sum('BID_SIZE')}, bucket_units='ticks', bucket_interval=x)\n", "prl['imb'] = (prl['bid_vol'] - prl['ask_vol']) / (prl['bid_vol'] + prl['ask_vol'])\n", "prls_df = otp.run(prl, symbols='NQ\\H22', start=otp.dt(2022, 3, 2, 10), end=otp.dt(2022, 3, 2, 10)+otp.Milli(100))\n", "print(prls_df.head())\n", "\n", "imb_stats = prl.agg({\n", " 'tw_imb': otp.agg.tw_average('imb'),\n", " 'mean': otp.agg.average('imb'),\n", " 'stdev': otp.agg.stddev('imb'),\n", "})\n", "print(otp.run(imb_stats, symbols='NQ\\H22', start=otp.dt(2022, 3, 2, 10), end=otp.dt(2022, 3, 2, 10)+otp.Milli(100)))\n", "\n" ] }, { "cell_type": "markdown", "id": "7f607216-7bce-4dcf-a84b-34540a668535", "metadata": {}, "source": [ "## Book sweep\n", "\n", "There are two version of book sweep: by price and by quantity. Book sweep by price, take a price as an input and returns the total quatity available at that price or better. Book sweep by quantity, takes a quantity as an input and returns the VWAP if the quantity were executed immediately." ] }, { "cell_type": "code", "execution_count": 16, "id": "97d3429b-4c5f-4ebd-a155-8593301a557a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Time total_qty\n", "0 2022-03-02 10:00:00 169\n", " Time total_qty\n", "0 2022-03-02 10:00:00 0\n" ] } ], "source": [ "def side_to_direction(side):\n", " return 1 if side == 'ASK' else -1\n", "\n", "def sweep_by_price(side, price):\n", " prl = otp.ObSnapshot(db='CME', tick_type='PRL_FULL', side=side)\n", " direction = side_to_direction(side)\n", " prl, _ = prl[direction * prl['PRICE'] <= direction * price]\n", " prl = prl.agg({'total_qty': otp.agg.sum('SIZE')})\n", " return otp.run(prl, symbols='NQ\\H22', start=otp.dt(2022, 3, 2, 10), end=otp.dt(2022, 3, 2, 10))\n", "\n", "print(sweep_by_price('BID', 14075))\n", "print(sweep_by_price('ASK', 14077))" ] }, { "cell_type": "code", "execution_count": 17, "id": "c40a0eb2-aa7b-4800-b28b-a69d4c719097", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Time VWAP\n", "0 2022-03-02 10:00:00 14090.475\n", " Time VWAP\n", "0 2022-03-02 10:00:00 14092.525\n" ] } ], "source": [ "def sweep_by_qty(side, qty):\n", " prl = otp.ObSnapshot(db='CME', tick_type='PRL_FULL', side=side)\n", " prl = prl.agg({'total_qty': otp.agg.sum('SIZE')}, running=True, all_fields=True)\n", " direction = side_to_direction(side)\n", " prl, _ = prl[prl['total_qty'] - prl['SIZE'] < qty]\n", " # update the SIZE in the last tick only so that total_qty is exactly qty\n", " prl['SIZE'] = prl.apply(lambda tick: prl['SIZE'] - (prl['total_qty'] - qty) if prl['total_qty'] > qty else prl['SIZE'])\n", " prl = prl.agg({'VWAP': otp.agg.vwap('PRICE', 'SIZE')})\n", " return otp.run(prl, symbols='NQ\\H22', start=otp.dt(2022, 3, 2, 10), end=otp.dt(2022, 3, 2, 10))\n", "print(sweep_by_qty('BID', 10))\n", "print(sweep_by_qty('ASK', 10))" ] }, { "cell_type": "markdown", "id": "0aa8f44c-073a-4078-b5dd-7664c26fc3fe", "metadata": {}, "source": [ "## Market By Order\n", "Order Book data may be annotated with 'key' fields lets us break down the book by each value of the 'key' fields. For example, a book could by keyed by market participant ID, allowing us to see the book with the orders of a given market participant only. Some exchanges provide 'market-by-order' data where the book is keyed by order id. Set `show_full_detail` to `True` to see the book broken down to the most granular level. The example below is a market-by-order book." ] }, { "cell_type": "code", "execution_count": 18, "id": "77e07c18-6e71-4b05-825b-bb5bdb54518d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Time ORDER_ID BUY_SELL_FLAG ORDER_TYPE PRICE SIZE TIME_PRIORITY RECORD_TYPE DELETED_TIME TICK_STATUS OMDSEQ LEVEL UPDATE_TIME\n", "0 2022-03-02 10:00:00 6830848559575 0 L 14090.75 1 43115683040 R 1970-01-01 0 12 1 2022-03-02 09:59:59.923928381\n", "1 2022-03-02 10:00:00 6830848559573 0 L 14090.75 1 43115683038 R 1970-01-01 0 9 1 2022-03-02 09:59:59.923735565\n", "2 2022-03-02 10:00:00 6830848559571 0 L 14090.75 1 43115683036 R 1970-01-01 0 6 1 2022-03-02 09:59:59.923710433\n", "3 2022-03-02 10:00:00 6830848559570 0 L 14090.50 1 43115683035 R 1970-01-01 0 0 2 2022-03-02 09:59:59.923521093\n", "4 2022-03-02 10:00:00 6830848548970 0 L 14090.50 1 43115668616 R 1970-01-01 0 0 2 2022-03-02 09:59:17.797610227\n" ] } ], "source": [ "prl = otp.ObSnapshot('CME', tick_type='PRL_FULL', side='BID', show_full_detail=True)\n", "prl = prl.first(5)\n", "print(otp.run(prl, symbols='NQ\\H22', start=otp.dt(2022, 3, 2, 10), end=otp.dt(2022, 3, 2, 10)))" ] }, { "cell_type": "markdown", "id": "cf1d6f07-69d8-4017-a690-f4ff914cb027", "metadata": {}, "source": [ "Market-by-order data can be used to analyze/validate the priority mechanism used by the exchange.``" ] }, { "cell_type": "code", "execution_count": 19, "id": "05546b5b-f5b9-44e2-a722-acefb2c1662f", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ORDER_IDPRICELEVELTIME_PRIORITYSIZEBUY_SELL_FLAGORDER_TYPE
0683084855957114090.7514311568303610L
1683084855957314090.7514311568303810L
2683084855957514090.7514311568304010L
3683084854546914090.5024311566381210L
4683084854897014090.5024311566861610L
\n", "
" ], "text/plain": [ " ORDER_ID PRICE LEVEL TIME_PRIORITY SIZE BUY_SELL_FLAG ORDER_TYPE\n", "0 6830848559571 14090.75 1 43115683036 1 0 L\n", "1 6830848559573 14090.75 1 43115683038 1 0 L\n", "2 6830848559575 14090.75 1 43115683040 1 0 L\n", "3 6830848545469 14090.50 2 43115663812 1 0 L\n", "4 6830848548970 14090.50 2 43115668616 1 0 L" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "prl = otp.ObSnapshot('CME', tick_type='PRL_FULL', side='BID', show_full_detail=True)\n", "\n", "\"\"\"\n", "ORDER_TYPE:\n", "L = Limit order\n", "I = Implied order\n", "\n", "Implied liquidity doesn’t have priority as it's always last to execute at any price level. \n", "It also doesn’t have an order ID, so the IDs that we see in the db are synthetic \n", "(consisting of 1 or 2 for the 1st/2nd implied level, and E/F for the buy/sell side respectively).\n", "\n", "In order to rank the orders within a given price point by priority, we need to sort first by ORDER_TYPE (“L” comes before “I”),\n", "then by TIME_PRIORITY (lowest value comes first).\n", "\"\"\"\n", "prl = prl.sort(['LEVEL','ORDER_TYPE', 'TIME_PRIORITY'],ascending=[True,False, True])\n", "orders = otp.run(prl, symbols='NQ\\H22', start=otp.dt(2022, 3, 2, 10), end=otp.dt(2022, 3, 2, 10))\n", "orders = orders[['ORDER_ID', 'PRICE', 'LEVEL', 'TIME_PRIORITY','SIZE', 'BUY_SELL_FLAG', 'ORDER_TYPE']]\n", "orders.head()" ] }, { "cell_type": "code", "execution_count": null, "id": "a092e9c2-3028-4db9-b2a5-65d45932f4df", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.8" } }, "nbformat": 4, "nbformat_minor": 5 }