Spot Websocket
The examples presented below serve to demonstrate the usage of the Spot websocket clients provided by python-kraken-sdk to access Kraken’s Websocket API v1 and v2.
For questions, feedback, additions, suggestions for improvement or problems python-kraken-sdk/discussions or python-kraken-sdk/issues may be helpful.
Example access and usage for Kraken Spot Websocket API v2
1#!/usr/bin/env python
2# Copyright (C) 2023 Benjamin Thomas Schwertfeger
3# GitHub: https://github.com/btschwertfeger
4#
5
6"""
7Module that provides an example usage for the KrakenSpotWebsocketClient.
8It uses the Kraken Websocket API v2.
9"""
10
11from __future__ import annotations
12
13import asyncio
14import logging
15import logging.config
16import os
17from contextlib import suppress
18
19from kraken.spot import KrakenSpotWSClientV2
20
21logging.basicConfig(
22 format="%(asctime)s %(module)s,line: %(lineno)d %(levelname)8s | %(message)s",
23 datefmt="%Y/%m/%d %H:%M:%S",
24 level=logging.INFO,
25)
26logging.getLogger("requests").setLevel(logging.WARNING)
27logging.getLogger("urllib3").setLevel(logging.WARNING)
28
29
30async def main() -> None:
31 key: str = os.getenv("SPOT_API_KEY")
32 secret: str = os.getenv("SPOT_SECRET_KEY")
33
34 class Client(KrakenSpotWSClientV2):
35 """Can be used to create a custom trading strategy"""
36
37 async def on_message(self: Client, message: dict) -> None:
38 """Receives the websocket messages"""
39 if message.get("method") == "pong" or message.get("channel") == "heartbeat":
40 return
41
42 print(message)
43 # now you can access lots of methods, for example to create an order:
44 # if self._is_auth: # only if the client is authenticated …
45 # await self.send_message(
46 # message={
47 # "method": "add_order",
48 # "params": {
49 # "limit_price": 1234.56,
50 # "order_type": "limit",
51 # "order_userref": 123456789,
52 # "order_qty": 1.0,
53 # "side": "buy",
54 # "symbol": "BTC/USD",
55 # "validate": True,
56 # },
57 # }
58 # )
59 # ... it is also possible to call regular REST endpoints
60 # but using the websocket messages is more efficient.
61 # You can also un-/subscribe here using self.subscribe/self.unsubscribe.
62
63 # Public/unauthenticated websocket client
64 client: Client = Client() # only use this one if you don't need private feeds
65 # print(client.public_channel_names) # list public subscription names
66
67 await client.subscribe(
68 params={"channel": "ticker", "symbol": ["BTC/USD", "DOT/USD"]},
69 )
70 await client.subscribe(
71 params={"channel": "book", "depth": 25, "symbol": ["BTC/USD"]},
72 )
73 # await client.subscribe(params={"channel": "ohlc", "symbol": ["BTC/USD"]})
74 await client.subscribe(
75 params={
76 "channel": "ohlc",
77 "interval": 15,
78 "snapshot": False,
79 "symbol": ["BTC/USD", "DOT/USD"],
80 },
81 )
82 await client.subscribe(params={"channel": "trade", "symbol": ["BTC/USD"]})
83
84 # wait because unsubscribing is faster than unsubscribing ... (just for that example)
85 await asyncio.sleep(3)
86 # print(client.active_public_subscriptions) # … to list active subscriptions
87 await client.unsubscribe(
88 params={"channel": "ticker", "symbol": ["BTC/USD", "DOT/USD"]},
89 )
90 # ...
91
92 if key and secret:
93 # Per default, the authenticated client starts two websocket connections,
94 # one for authenticated and one for public messages. If there is no need
95 # for a public connection, it can be disabled using the ``no_public``
96 # parameter.
97 client_auth = Client(key=key, secret=secret, no_public=True)
98 # print(client_auth.private_channel_names) # … list private channel names
99 # when using the authenticated client, you can also subscribe to public feeds
100 await client_auth.subscribe(params={"channel": "executions"})
101
102 await asyncio.sleep(5)
103 await client_auth.unsubscribe(params={"channel": "executions"})
104
105 while not client.exception_occur: # and not client_auth.exception_occur:
106 await asyncio.sleep(6)
107
108
109if __name__ == "__main__":
110 with suppress(KeyboardInterrupt):
111 asyncio.run(main())
112 # The websocket client will send {'event': 'asyncio.CancelledError'}
113 # via on_message so you can handle the behavior/next actions
114 # individually within your strategy.
115
116# ============================================================
117# Alternative - as ContextManager:
118
119# from kraken.spot import KrakenSpotWSClientV2
120# import asyncio
121
122
123# async def on_message(message: dict) -> None:
124# print(message)
125
126
127# async def main() -> None:
128# async with KrakenSpotWSClientV2(callback=on_message) as session:
129# await session.subscribe(params={"channel": "ticker", "symbol": ["BTC/USD"]})
130
131# while True:
132# await asyncio.sleep(6)
133
134
135# if __name__ == "__main__":
136# try:
137# asyncio.run(main())
138# except KeyboardInterrupt:
139# pass
Example access and usage for Kraken Spot Websocket API v1
1#!/usr/bin/env python
2# Copyright (C) 2023 Benjamin Thomas Schwertfeger
3# GitHub: https://github.com/btschwertfeger
4#
5
6"""
7Module that provides an example usage for the KrakenSpotWebsocketClient.
8It uses the Kraken Websocket API v1.
9"""
10
11from __future__ import annotations
12
13import asyncio
14import logging
15import logging.config
16import os
17from contextlib import suppress
18
19from kraken.spot import KrakenSpotWSClientV1
20
21logging.basicConfig(
22 format="%(asctime)s %(module)s,line: %(lineno)d %(levelname)8s | %(message)s",
23 datefmt="%Y/%m/%d %H:%M:%S",
24 level=logging.INFO,
25)
26logging.getLogger("requests").setLevel(logging.WARNING)
27logging.getLogger("urllib3").setLevel(logging.WARNING)
28
29
30async def main() -> None:
31 """Create a client and subscribe to channels/feeds"""
32
33 key: str = os.getenv("SPOT_API_KEY")
34 secret: str = os.getenv("SPOT_SECRET_KEY")
35
36 class Client(KrakenSpotWSClientV1):
37 """Can be used to create a custom trading strategy"""
38
39 async def on_message(self: Client, message: list | dict) -> None:
40 """Receives the websocket messages"""
41 if isinstance(message, dict) and "event" in message:
42 topic = message["event"]
43 if topic in {"heartbeat", "pong"}:
44 return
45
46 print(message)
47 # if condition:
48 # await self.create_order(
49 # ordertype="limit",
50 # side="buy",
51 # pair="BTC/USD",
52 # price=20000,
53 # volume=200
54 # )
55 # ... it is also possible to call regular REST endpoints
56 # but using the websocket messages is more efficient.
57 # You can also un-/subscribe here using self.subscribe/self.unsubscribe.
58
59 # ___Public_Websocket_Feed_____
60 client: Client = Client() # only use this one if you don't need private feeds
61 # print(client.public_channel_names) # list public subscription names
62
63 await client.subscribe(subscription={"name": "ticker"}, pair=["XBT/USD", "DOT/USD"])
64 await client.subscribe(subscription={"name": "spread"}, pair=["XBT/USD", "DOT/USD"])
65 await client.subscribe(subscription={"name": "book"}, pair=["BTC/USD"])
66 # await client.subscribe(subscription={ "name": "book", "depth": 25}, pair=["BTC/USD"])
67 # await client.subscribe(subscription={ "name": "ohlc" }, pair=["BTC/USD"])
68 # await client.subscribe(subscription={ "name": "ohlc", "interval": 15}, pair=["XBT/USD", "DOT/USD"])
69 # await client.subscribe(subscription={ "name": "trade" }, pair=["BTC/USD"])
70 # await client.subscribe(subscription={ "name": "*"} , pair=["BTC/USD"])
71
72 await asyncio.sleep(2) # wait because unsubscribing is faster than subscribing ...
73 # print(client.active_public_subscriptions)
74 await client.unsubscribe(
75 subscription={"name": "ticker"},
76 pair=["XBT/USD", "DOT/USD"],
77 )
78 await client.unsubscribe(subscription={"name": "spread"}, pair=["XBT/USD"])
79 await client.unsubscribe(subscription={"name": "spread"}, pair=["DOT/USD"])
80 # ...
81
82 if key and secret:
83 client_auth = Client(key=key, secret=secret)
84 # print(client_auth.active_private_subscriptions)
85 # print(client_auth.private_channel_names) # list private channel names
86 # when using the authenticated client, you can also subscribe to public feeds
87 await client_auth.subscribe(subscription={"name": "ownTrades"})
88 await client_auth.subscribe(subscription={"name": "openOrders"})
89
90 await asyncio.sleep(2)
91 await client_auth.unsubscribe(subscription={"name": "ownTrades"})
92 await client_auth.unsubscribe(subscription={"name": "openOrders"})
93
94 while not client.exception_occur: # and not client_auth.exception_occur:
95 await asyncio.sleep(6)
96
97
98if __name__ == "__main__":
99 with suppress(KeyboardInterrupt):
100 asyncio.run(main())
101 # The websocket client will send {'event': 'asyncio.CancelledError'}
102 # via on_message so you can handle the behavior/next actions
103 # individually within your strategy.
104
105# ============================================================
106# Alternative - as ContextManager:
107
108# from kraken.spot import KrakenSpotWSClientV1
109# import asyncio
110
111# async def on_message(message):
112# print(message)
113
114# async def main() -> None:
115# async with KrakenSpotWSClientV1(callback=on_message) as session:
116# await session.subscribe(subscription={"name": "ticker"}, pair=["XBT/USD"])
117
118# while True:
119# await asyncio.sleep(6)
120
121# if __name__ == "__main__":
122# try:
123# asyncio.run(main())
124# except KeyboardInterrupt:
125# pass