|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | +# Copyright (C) 2023 Benjamin Thomas Schwertfeger |
| 4 | +# GitHub: https://github.com/btschwertfeger |
| 5 | +# |
| 6 | + |
| 7 | +""" |
| 8 | +
|
| 9 | +**For websocket API v1** |
| 10 | +
|
| 11 | +This module provides an example on how to use the Spot Orderbook client of the |
| 12 | +python-kraken-sdk (https://github.com/btschwertfeger/python-kraken-sdk) to |
| 13 | +retrieve and maintain a valid Spot order book for (a) specific asset pair(s). |
| 14 | +It can be run directly without any credentials if the python-kraken-sdk is |
| 15 | +installed. |
| 16 | +
|
| 17 | + python3 -m pip install python-kraken-sdk |
| 18 | +
|
| 19 | +The output when running this snippet looks like the following table and updates |
| 20 | +the book as soon as Kraken sent any order book update. |
| 21 | +
|
| 22 | +Bid Volume Ask Volume |
| 23 | +27076.00000 (8.28552127) 27076.10000 (2.85897056) |
| 24 | +27075.90000 (3.75748052) 27077.30000 (0.57243521) |
| 25 | +27074.40000 (0.57249652) 27080.80000 (0.00100000) |
| 26 | +27072.90000 (0.01200917) 27081.00000 (0.00012345) |
| 27 | +27072.80000 (0.25000000) 27081.70000 (0.30000000) |
| 28 | +27072.30000 (4.89735970) 27082.70000 (0.05539777) |
| 29 | +27072.20000 (2.65896716) 27082.80000 (0.00400000) |
| 30 | +27072.10000 (2.77037635) 27082.90000 (0.57231684) |
| 31 | +27072.00000 (0.81770000) 27083.00000 (0.38934000) |
| 32 | +27071.50000 (0.07194657) 27083.80000 (2.76918992) |
| 33 | +
|
| 34 | +This can be the basis of an order book based trading strategy where realtime |
| 35 | +data and fast price movements are considered. |
| 36 | +""" |
| 37 | + |
| 38 | +from __future__ import annotations |
| 39 | + |
| 40 | +import asyncio |
| 41 | +from typing import Any |
| 42 | + |
| 43 | +from kraken.spot import OrderbookClientV1 |
| 44 | + |
| 45 | + |
| 46 | +class Orderbook(OrderbookClientV1): |
| 47 | + """ |
| 48 | + This is a wrapper class that is used to overload the :func:`on_book_update` |
| 49 | + function. It can also be used as a base for trading strategy. Since the |
| 50 | + :class:`kraken.spot.OrderbookClientV1` is derived from |
| 51 | + :class:`kraken.spot.KrakenSpotWSClient` it can also be used to access the |
| 52 | + :func:`subscribe` function and any other provided utility. |
| 53 | + """ |
| 54 | + |
| 55 | + async def on_book_update(self: Orderbook, pair: str, message: list) -> None: |
| 56 | + """ |
| 57 | + This function is called every time the order book of ``pair`` gets |
| 58 | + updated. |
| 59 | +
|
| 60 | + The ``pair`` parameter can be used to access the updated order book as |
| 61 | + shown in the function body below. |
| 62 | +
|
| 63 | + :param pair: The currency pair of the updated order book |
| 64 | + :type pair: str |
| 65 | + :param message: The message sent by Kraken (not needed in most cases) |
| 66 | + :type message: list |
| 67 | + """ |
| 68 | + |
| 69 | + book: dict[str, Any] = self.get(pair=pair) |
| 70 | + bid: list[tuple[str, str]] = list(book["bid"].items()) |
| 71 | + ask: list[tuple[str, str]] = list(book["ask"].items()) |
| 72 | + |
| 73 | + print("Bid Volume\t\t Ask Volume") |
| 74 | + for level in range(self.depth): |
| 75 | + print( |
| 76 | + f"{bid[level][0]} ({bid[level][1][0]}) \t {ask[level][0]} ({ask[level][1][0]})", |
| 77 | + ) |
| 78 | + # assert book["valid"] # ensure that the checksum is valid (will be |
| 79 | + # false after reconnect -- but the client handles the removal and |
| 80 | + # resubscription of the book) |
| 81 | + |
| 82 | + |
| 83 | +async def main() -> None: |
| 84 | + """ |
| 85 | + Here we depth of the order book and also a pair. We could |
| 86 | + subscribe to multiple pairs, but for simplicity only XBT/USD is chosen. |
| 87 | +
|
| 88 | + The Orderbook class can be instantiated, which receives the order |
| 89 | + book-related messages, after we subscribed to the book feed. |
| 90 | +
|
| 91 | + Finally we need some "game loop" - so we create a while loop |
| 92 | + that runs as long as there is no error. |
| 93 | + """ |
| 94 | + orderbook: Orderbook = Orderbook() |
| 95 | + |
| 96 | + await orderbook.add_book( |
| 97 | + pairs=["XBT/USD"], # we can also subscribe to more currency pairs |
| 98 | + ) |
| 99 | + |
| 100 | + while not orderbook.exception_occur: |
| 101 | + await asyncio.sleep(10) |
| 102 | + |
| 103 | + |
| 104 | +if __name__ == "__main__": |
| 105 | + try: |
| 106 | + asyncio.run(main()) |
| 107 | + except KeyboardInterrupt: |
| 108 | + print("KeyboardInterrupt!") |
0 commit comments