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