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