Maintain a valid Spot Orderbook

The following examples demonstrate how to use the python-kraken-sdk to retrieve valid realtime orderbooks. The current implementation of the kraken.spot.SpotOrderBookClient uses the websocket API v2.

Sample on how to maintain a valid orderbook w/ websocket API
  1# !/usr/bin/env python3
  2# -*- mode: python; coding: utf-8 -*-
  3#
  4# Copyright (C) 2023 Benjamin Thomas Schwertfeger
  5# All rights reserved.
  6# https://github.com/btschwertfeger
  7#
  8
  9"""
 10
 11**For websocket API v2**
 12
 13This module provides an example on how to use the Spot Orderbook client of the
 14python-kraken-sdk (https://github.com/btschwertfeger/python-kraken-sdk) to
 15retrieve and maintain a valid Spot order book for (a) specific asset pair(s).
 16It can be run directly without any credentials if the python-kraken-sdk is
 17installed.
 18
 19    python3 -m pip install python-kraken-sdk
 20
 21The output when running this snippet looks like the following table and updates
 22the book as soon as Kraken sent any order book update.
 23
 24Bid         Volume               Ask         Volume
 2527076.00000 (8.28552127)         27076.10000 (2.85897056)
 2627075.90000 (3.75748052)         27077.30000 (0.57243521)
 2727074.40000 (0.57249652)         27080.80000 (0.00100000)
 2827072.90000 (0.01200917)         27081.00000 (0.00012345)
 2927072.80000 (0.25000000)         27081.70000 (0.30000000)
 3027072.30000 (4.89735970)         27082.70000 (0.05539777)
 3127072.20000 (2.65896716)         27082.80000 (0.00400000)
 3227072.10000 (2.77037635)         27082.90000 (0.57231684)
 3327072.00000 (0.81770000)         27083.00000 (0.38934000)
 3427071.50000 (0.07194657)         27083.80000 (2.76918992)
 35
 36This can be the basis of an order book based trading strategy where realtime
 37data and fast price movements are considered.
 38"""
 39
 40from __future__ import annotations
 41
 42import asyncio
 43import logging
 44from typing import Any
 45
 46from kraken.spot import SpotOrderBookClient
 47
 48logging.basicConfig(
 49    format="%(asctime)s %(module)s,line: %(lineno)d %(levelname)8s | %(message)s",
 50    datefmt="%Y/%m/%d %H:%M:%S",
 51    level=logging.INFO,
 52)
 53logging.getLogger().setLevel(logging.INFO)
 54logging.getLogger("requests").setLevel(logging.WARNING)
 55
 56
 57class Orderbook(SpotOrderBookClient):
 58    """
 59    This is a wrapper class that is used to overload the :func:`on_book_update`
 60    function. It can also be used as a base for trading strategy. Since the
 61    :class:`kraken.spot.SpotOrderBookClient` is derived from
 62    :class:`kraken.spot.SpotWSClient` it can also be used to access the
 63    :func:`subscribe` function and any other provided utility.
 64    """
 65
 66    async def on_book_update(
 67        self: Orderbook,
 68        pair: str,
 69        message: list,  # noqa: ARG002
 70    ) -> None:
 71        """
 72        This function is called every time the order book of ``pair`` gets
 73        updated.
 74
 75        The ``pair`` parameter can be used to access the updated order book as
 76        shown in the function body below.
 77
 78        :param pair: The currency pair of the updated order book
 79        :type pair: str
 80        :param message: The message sent by Kraken (not needed in most cases)
 81        :type message: list
 82        """
 83        book: dict[str, Any] = self.get(pair=pair)
 84        bid: list[tuple[str, str]] = list(book["bid"].items())
 85        ask: list[tuple[str, str]] = list(book["ask"].items())
 86
 87        print("Bid     Volume\t\t  Ask     Volume")
 88        for level in range(self.depth):
 89            print(
 90                f"{bid[level][0]} ({bid[level][1][0]}) \t {ask[level][0]} ({ask[level][1][0]})",
 91            )
 92
 93        assert book["valid"]  # ensure that the checksum is valid
 94        # … the client will automatically resubscribe to a book feed if the
 95        #   checksum is not valid. The user must not do anything for that, but
 96        #   will get informed.
 97
 98
 99async def main() -> None:
100    """
101    Here we depth of the order book and also a pair. We could
102    subscribe to multiple pairs, but for simplicity only XBT/USD is chosen.
103
104    The Orderbook class can be instantiated, which receives the order
105    book-related messages, after we subscribed to the book feed.
106
107    Finally we need some "game loop" - so we create a while loop
108    that runs as long as there is no error.
109    """
110
111    async with Orderbook(depth=10) as orderbook:
112        await orderbook.add_book(
113            pairs=["BTC/USD"],  # we can also subscribe to more currency pairs
114        )
115
116        while not orderbook.exception_occur:
117            await asyncio.sleep(10)
118
119
120if __name__ == "__main__":
121    try:
122        asyncio.run(main())
123    except KeyboardInterrupt:
124        print("KeyboardInterrupt!")

References: - https://gist.github.com/btschwertfeger/6eea0eeff193f7cd1b262cfce4f0eb51