fastlob

Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
Toggle table of contents sidebar
Fast & minimalist limit-order-book implementation in Python, with almost no dependencies.
GitHub | PyPI

This package is still being developed, bugs are expected.

This is the very first version of the project, the idea was to have a working, correct and clean single-threaded version before making it fast. The next step is to rewrite the core parts in a faster and concurrent fashion.

For now, I have decided to keep it written only in Python (no interfacing with C/C++), but that may change in the future.

### Quickstart

To install the package you can either install it using pip:

    pip install fastlob

Otherwise, you can build the project from source:

    git clone git@github.com:mrochk/fastlob.git
    cd fastlob
    pip install -r requirements.txt
    pip install .

### Examples

Placing a limit GTD order and getting his status.

     1import time, logging
     2from fastlob import Orderbook, OrderParams, OrderSide, OrderType
     3
     4logging.basicConfig(level=logging.INFO) # set maximum logging level
     5
     6lob = Orderbook(name='ABCD', start=True) # create a lob an start it
     7
     8# create an order
     9params = OrderParams(
    10    side=OrderSide.BID,
    11    price=123.32,
    12    quantity=3.4,
    13    otype=OrderType.GTD,
    14    expiry=time.time() + 120 # order will expire in two minutes
    15)
    16
    17result = lob(params); assert result.success() # place order
    18
    19status, qty_left = lob.get_status(result.orderid()) # query status of order
    20print(f'Current order status: {status.name}, quantity left: {qty_left}.\n')
    21
    22lob.render() # pretty-print the lob
    23
    24lob.stop() # stop background processes

Simulate the LOB using various distributions.

     1import random, time, os
     2from scipy import stats
     3
     4from fastlob import Orderbook, OrderParams, OrderSide
     5
     6def generate_orders(T: int, midprice: float):
     7   result = list()
     8
     9   for _ in range(T):
    10
    11      n_ask_limits = stats.poisson.rvs(500)
    12      n_bid_limits = stats.poisson.rvs(500)
    13
    14      ask_limits_price = stats.expon.rvs(loc=midprice, scale=1, size=n_ask_limits)
    15      bid_limits_price = -stats.expon.rvs(loc=midprice, scale=1, size=n_bid_limits) + 2*midprice
    16
    17      ask_limits_quantities = stats.uniform.rvs(loc=1, scale=100, size=n_ask_limits)
    18      bid_limits_quantities = stats.uniform.rvs(loc=1, scale=100, size=n_bid_limits)
    19
    20      ask_limits_params = [OrderParams(OrderSide.ASK, p, q) for (p, q) in zip(ask_limits_price, ask_limits_quantities)]
    21      bid_limits_params = [OrderParams(OrderSide.BID, p, q) for (p, q) in zip(bid_limits_price, bid_limits_quantities)]
    22
    23      n_markets = stats.poisson.rvs(100)
    24
    25      markets_price = stats.norm.rvs(loc=midprice, scale=2, size=n_markets)
    26      markets_quantities = stats.uniform.rvs(loc=1, scale=100, size=n_markets)
    27      markets_bid_or_ask = [random.choice((OrderSide.BID, OrderSide.ASK)) for _ in range(n_markets)]
    28
    29      markets_params = [OrderParams(s, p, q) for (s, p, q) in zip(markets_bid_or_ask, markets_price, markets_quantities)]
    30
    31      orders = ask_limits_params + bid_limits_params + markets_params
    32      random.shuffle(orders)
    33
    34      result.append(orders)
    35
    36   return result
    37
    38def simulate(orders: list, speed: float):
    39   ob = Orderbook('Simulation')
    40   ob.start()
    41
    42   for o in orders:
    43      ob.process_many(o)
    44      print()
    45      ob.render()
    46      time.sleep(speed)
    47      os.system('clear')
    48
    49   ob.stop()
    50
    51orders = generate_orders(10, 100)
    52simulate(orders, 0.5)

Use historical data.

     1from fastlob import Orderbook, OrderParams, OrderSide
     2
     3snapshot = {
     4   'bids': [
     5      (98.78, 11.56),
     6      (95.65, 67.78),
     7      (94.23, 56.76),
     8      (93.23, 101.59),
     9      (90.03, 200.68),
    10   ],
    11   'asks': [
    12      (99.11, 12.87),
    13      (100.89, 45.87),
    14      (101.87, 88.56),
    15      (103.78, 98.77),
    16      (105.02, 152.43),
    17   ]
    18}
    19
    20updates = [
    21   # update 1
    22   {
    23   'bids': [
    24      (99.07, 10.01),
    25      (95.65, 79.78),
    26      (93.23, 89.59),
    27      (90.03, 250.68),
    28   ],
    29   'asks': [
    30      (99.11, 5.81),
    31   ]},
    32
    33   # update 2
    34   {
    35   'bids': [
    36      (99.07, 0.00),
    37      (98.78, 3.56),
    38      (79.90, 100.56),
    39   ],
    40   'asks': [
    41      (103.78, 90.77),
    42      (105.02, 123.43),
    43   ]},
    44
    45   # update 3
    46   {
    47   'bids': [
    48      (98.78, 11.56),
    49      (95.65, 67.78),
    50      (94.23, 56.76),
    51      (93.23, 0.00),
    52      (90.03, 0.00),
    53   ],
    54   'asks': [
    55      (99.11, 0.00),
    56      (100.89, 0.00),
    57      (101.87, 0.00),
    58      (103.78, 1.23),
    59      (105.02, 152.43),
    60   ]}]
    61
    62 ob = Orderbook.from_snapshot(snapshot, start=True)
    63 ob.load_updates(updates)
    64
    65 ob.render()
    66
    67 ob.step()
    68 ob.render()
    69
    70 ob(OrderParams(OrderSide.BID, 99.07, 1.98))
    71
    72 ob.step()
    73 ob.render()
    74
    75 ob.step()
    76 ob.render()
    77
    78 ob.stop()

### API Reference

API Reference

- lob package
- engine package
- side package
- limit package
- order package
- result package
- enums package
- consts package
- utils package