walrasquant-lib 0.4.20__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- walrasquant/__init__.py +7 -0
- walrasquant/aggregation.py +449 -0
- walrasquant/backends/__init__.py +5 -0
- walrasquant/backends/db.py +109 -0
- walrasquant/backends/db_memory.py +61 -0
- walrasquant/backends/db_postgresql.py +321 -0
- walrasquant/backends/db_sqlite.py +310 -0
- walrasquant/base/__init__.py +24 -0
- walrasquant/base/api_client.py +46 -0
- walrasquant/base/connector.py +863 -0
- walrasquant/base/ems.py +794 -0
- walrasquant/base/exchange.py +213 -0
- walrasquant/base/oms.py +428 -0
- walrasquant/base/retry.py +220 -0
- walrasquant/base/sms.py +545 -0
- walrasquant/base/ws_client.py +408 -0
- walrasquant/config.py +284 -0
- walrasquant/constants.py +413 -0
- walrasquant/core/__init__.py +0 -0
- walrasquant/core/cache.py +688 -0
- walrasquant/core/clock.py +59 -0
- walrasquant/core/connection.py +41 -0
- walrasquant/core/entity.py +504 -0
- walrasquant/core/nautilius_core.py +103 -0
- walrasquant/core/registry.py +41 -0
- walrasquant/engine.py +745 -0
- walrasquant/error.py +34 -0
- walrasquant/exchange/__init__.py +13 -0
- walrasquant/exchange/base_factory.py +172 -0
- walrasquant/exchange/binance/__init__.py +30 -0
- walrasquant/exchange/binance/connector.py +1093 -0
- walrasquant/exchange/binance/constants.py +934 -0
- walrasquant/exchange/binance/ems.py +140 -0
- walrasquant/exchange/binance/error.py +48 -0
- walrasquant/exchange/binance/exchange.py +144 -0
- walrasquant/exchange/binance/factory.py +115 -0
- walrasquant/exchange/binance/oms.py +1807 -0
- walrasquant/exchange/binance/rest_api.py +1653 -0
- walrasquant/exchange/binance/schema.py +1063 -0
- walrasquant/exchange/binance/websockets.py +389 -0
- walrasquant/exchange/bitget/__init__.py +28 -0
- walrasquant/exchange/bitget/connector.py +578 -0
- walrasquant/exchange/bitget/constants.py +392 -0
- walrasquant/exchange/bitget/ems.py +202 -0
- walrasquant/exchange/bitget/error.py +36 -0
- walrasquant/exchange/bitget/exchange.py +128 -0
- walrasquant/exchange/bitget/factory.py +135 -0
- walrasquant/exchange/bitget/oms.py +1619 -0
- walrasquant/exchange/bitget/rest_api.py +610 -0
- walrasquant/exchange/bitget/schema.py +885 -0
- walrasquant/exchange/bitget/websockets.py +753 -0
- walrasquant/exchange/bybit/__init__.py +32 -0
- walrasquant/exchange/bybit/connector.py +819 -0
- walrasquant/exchange/bybit/constants.py +479 -0
- walrasquant/exchange/bybit/ems.py +93 -0
- walrasquant/exchange/bybit/error.py +36 -0
- walrasquant/exchange/bybit/exchange.py +108 -0
- walrasquant/exchange/bybit/factory.py +128 -0
- walrasquant/exchange/bybit/oms.py +1195 -0
- walrasquant/exchange/bybit/rest_api.py +570 -0
- walrasquant/exchange/bybit/schema.py +867 -0
- walrasquant/exchange/bybit/websockets.py +307 -0
- walrasquant/exchange/hyperliquid/__init__.py +28 -0
- walrasquant/exchange/hyperliquid/connector.py +370 -0
- walrasquant/exchange/hyperliquid/constants.py +371 -0
- walrasquant/exchange/hyperliquid/ems.py +156 -0
- walrasquant/exchange/hyperliquid/error.py +48 -0
- walrasquant/exchange/hyperliquid/exchange.py +120 -0
- walrasquant/exchange/hyperliquid/factory.py +135 -0
- walrasquant/exchange/hyperliquid/oms.py +1081 -0
- walrasquant/exchange/hyperliquid/rest_api.py +348 -0
- walrasquant/exchange/hyperliquid/schema.py +583 -0
- walrasquant/exchange/hyperliquid/websockets.py +592 -0
- walrasquant/exchange/okx/__init__.py +25 -0
- walrasquant/exchange/okx/connector.py +931 -0
- walrasquant/exchange/okx/constants.py +518 -0
- walrasquant/exchange/okx/ems.py +144 -0
- walrasquant/exchange/okx/error.py +66 -0
- walrasquant/exchange/okx/exchange.py +102 -0
- walrasquant/exchange/okx/factory.py +138 -0
- walrasquant/exchange/okx/oms.py +1199 -0
- walrasquant/exchange/okx/rest_api.py +799 -0
- walrasquant/exchange/okx/schema.py +1449 -0
- walrasquant/exchange/okx/websockets.py +420 -0
- walrasquant/exchange/registry.py +201 -0
- walrasquant/execution/__init__.py +24 -0
- walrasquant/execution/algorithm.py +968 -0
- walrasquant/execution/algorithms/__init__.py +3 -0
- walrasquant/execution/algorithms/twap.py +392 -0
- walrasquant/execution/config.py +34 -0
- walrasquant/execution/constants.py +27 -0
- walrasquant/execution/schema.py +62 -0
- walrasquant/indicator.py +382 -0
- walrasquant/push.py +77 -0
- walrasquant/schema.py +755 -0
- walrasquant/strategy.py +1805 -0
- walrasquant/tools/__init__.py +0 -0
- walrasquant/tools/pm2_wrapper.py +1016 -0
- walrasquant/web/__init__.py +26 -0
- walrasquant/web/app.py +157 -0
- walrasquant/web/server.py +92 -0
- walrasquant_lib-0.4.20.dist-info/METADATA +162 -0
- walrasquant_lib-0.4.20.dist-info/RECORD +105 -0
- walrasquant_lib-0.4.20.dist-info/WHEEL +4 -0
- walrasquant_lib-0.4.20.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,885 @@
|
|
|
1
|
+
import msgspec
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from typing import Any, List
|
|
5
|
+
from walrasquant.schema import BaseMarket, Balance
|
|
6
|
+
from walrasquant.exchange.bitget.constants import (
|
|
7
|
+
BitgetInstType,
|
|
8
|
+
BitgetUtaInstType,
|
|
9
|
+
BitgetOrderSide,
|
|
10
|
+
BitgetOrderStatus,
|
|
11
|
+
BitgetTimeInForce,
|
|
12
|
+
BitgetPositionSide,
|
|
13
|
+
BitgetOrderType,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BitgetWsUtaArgMsg(msgspec.Struct):
|
|
18
|
+
instType: BitgetUtaInstType
|
|
19
|
+
topic: str
|
|
20
|
+
symbol: str | None = None
|
|
21
|
+
interval: str | None = None
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def message(self) -> str:
|
|
25
|
+
if not self.symbol:
|
|
26
|
+
return f"{self.instType.value}.{self.topic}"
|
|
27
|
+
if self.interval:
|
|
28
|
+
return f"{self.instType.value}.{self.topic}{self.interval}.{self.symbol}"
|
|
29
|
+
return f"{self.instType.value}.{self.topic}.{self.symbol}"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class BitgetWsUtaGeneralMsg(msgspec.Struct, kw_only=True):
|
|
33
|
+
event: str | None = None
|
|
34
|
+
arg: BitgetWsUtaArgMsg | None = None
|
|
35
|
+
code: int | None = None
|
|
36
|
+
msg: str | None = None
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def is_event_data(self) -> bool:
|
|
40
|
+
return self.event is not None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class BitgetGeneralResponse(msgspec.Struct, kw_only=True):
|
|
44
|
+
code: str
|
|
45
|
+
msg: str
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class BitgetWsArgMsg(msgspec.Struct):
|
|
49
|
+
instType: BitgetInstType
|
|
50
|
+
channel: str
|
|
51
|
+
instId: str | None = None
|
|
52
|
+
coin: str | None = None
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def message(self) -> str:
|
|
56
|
+
if self.instId:
|
|
57
|
+
return f"{self.instType.value}.{self.channel}.{self.instId}"
|
|
58
|
+
if self.coin:
|
|
59
|
+
return f"{self.instType.value}.{self.channel}.{self.coin}"
|
|
60
|
+
return f"{self.instType.value}.{self.channel}"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class BitgetWsGeneralMsg(msgspec.Struct, kw_only=True):
|
|
64
|
+
event: str | None = None
|
|
65
|
+
arg: BitgetWsArgMsg | None = None
|
|
66
|
+
code: int | None = None
|
|
67
|
+
msg: str | None = None
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def is_event_data(self) -> bool:
|
|
71
|
+
return self.event is not None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class BookData(msgspec.Struct, array_like=True):
|
|
75
|
+
px: str
|
|
76
|
+
sz: str
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class BitgetBooks1WsMsgData(msgspec.Struct):
|
|
80
|
+
a: List[BookData]
|
|
81
|
+
b: List[BookData]
|
|
82
|
+
ts: str
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class BitgetBooks1WsMsg(msgspec.Struct):
|
|
86
|
+
data: list[BitgetBooks1WsMsgData]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class BitgetTradeWsMsgData(msgspec.Struct):
|
|
90
|
+
p: str # fill price
|
|
91
|
+
S: BitgetOrderSide # fill side
|
|
92
|
+
T: str # ts
|
|
93
|
+
v: str # fill size
|
|
94
|
+
i: str # trade id
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class BitgetWsTradeWsMsg(msgspec.Struct):
|
|
98
|
+
data: list[BitgetTradeWsMsgData]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class BitgetWsCandleWsMsgData(msgspec.Struct):
|
|
102
|
+
start: str
|
|
103
|
+
open: str
|
|
104
|
+
close: str
|
|
105
|
+
high: str
|
|
106
|
+
low: str
|
|
107
|
+
volume: str
|
|
108
|
+
turnover: str
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class BitgetWsCandleWsMsg(msgspec.Struct):
|
|
112
|
+
data: list[BitgetWsCandleWsMsgData]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# # --- Kline ---
|
|
116
|
+
# class BitgetKline(msgspec.Struct):
|
|
117
|
+
# openTime: int
|
|
118
|
+
# open: str
|
|
119
|
+
# high: str
|
|
120
|
+
# low: str
|
|
121
|
+
# close: str
|
|
122
|
+
# volume: str
|
|
123
|
+
# quoteVolume: str
|
|
124
|
+
# closeTime: int
|
|
125
|
+
|
|
126
|
+
# class BitgetKlineMsg(msgspec.Struct):
|
|
127
|
+
# event: str
|
|
128
|
+
# arg: Dict[str, Any]
|
|
129
|
+
# data: List[BitgetKline]
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# # --- Trade ---
|
|
133
|
+
# class BitgetTrade(msgspec.Struct):
|
|
134
|
+
# tradeId: str
|
|
135
|
+
# price: str
|
|
136
|
+
# size: str
|
|
137
|
+
# side: str
|
|
138
|
+
# timestamp: int
|
|
139
|
+
|
|
140
|
+
# class BitgetTradeMsg(msgspec.Struct):
|
|
141
|
+
# event: str
|
|
142
|
+
# arg: Dict[str, Any]
|
|
143
|
+
# data: List[BitgetTrade]
|
|
144
|
+
|
|
145
|
+
# # --- Order Book ---
|
|
146
|
+
# class BitgetOrderBookSnapshot(msgspec.Struct):
|
|
147
|
+
# asks: List[List[str]]
|
|
148
|
+
# bids: List[List[str]]
|
|
149
|
+
# ts: int
|
|
150
|
+
# checksum: int
|
|
151
|
+
|
|
152
|
+
# class BitgetOrderBookUpdate(msgspec.Struct):
|
|
153
|
+
# asks: List[List[str]]
|
|
154
|
+
# bids: List[List[str]]
|
|
155
|
+
# ts: int
|
|
156
|
+
# checksum: int
|
|
157
|
+
|
|
158
|
+
# class BitgetOrderBookMsg(msgspec.Struct):
|
|
159
|
+
# event: str
|
|
160
|
+
# arg: Dict[str, Any]
|
|
161
|
+
# action: str # snapshot or update
|
|
162
|
+
# data: List[BitgetOrderBookSnapshot | BitgetOrderBookUpdate]
|
|
163
|
+
|
|
164
|
+
# class BitgetOrderBook(msgspec.Struct):
|
|
165
|
+
# bids: Dict[float, float] = {}
|
|
166
|
+
# asks: Dict[float, float] = {}
|
|
167
|
+
|
|
168
|
+
# def parse_orderbook(self, msg: BitgetOrderBookMsg, levels: int = 1):
|
|
169
|
+
# for entry in msg.data:
|
|
170
|
+
# if msg.action == "snapshot":
|
|
171
|
+
# self._handle_snapshot(entry)
|
|
172
|
+
# elif msg.action == "update":
|
|
173
|
+
# self._handle_delta(entry)
|
|
174
|
+
# return self._get_orderbook(levels)
|
|
175
|
+
|
|
176
|
+
# def _handle_snapshot(self, data: BitgetOrderBookSnapshot):
|
|
177
|
+
# self.bids.clear()
|
|
178
|
+
# self.asks.clear()
|
|
179
|
+
# for price, size in data.bids:
|
|
180
|
+
# self.bids[float(price)] = float(size)
|
|
181
|
+
# for price, size in data.asks:
|
|
182
|
+
# self.asks[float(price)] = float(size)
|
|
183
|
+
|
|
184
|
+
# def _handle_delta(self, data: BitgetOrderBookUpdate):
|
|
185
|
+
# for price, size in data.bids:
|
|
186
|
+
# price_f = float(price)
|
|
187
|
+
# size_f = float(size)
|
|
188
|
+
# if size_f == 0:
|
|
189
|
+
# self.bids.pop(price_f, None)
|
|
190
|
+
# else:
|
|
191
|
+
# self.bids[price_f] = size_f
|
|
192
|
+
# for price, size in data.asks:
|
|
193
|
+
# price_f = float(price)
|
|
194
|
+
# size_f = float(size)
|
|
195
|
+
# if size_f == 0:
|
|
196
|
+
# self.asks.pop(price_f, None)
|
|
197
|
+
# else:
|
|
198
|
+
# self.asks[price_f] = size_f
|
|
199
|
+
|
|
200
|
+
# def _get_orderbook(self, levels: int):
|
|
201
|
+
# bids = sorted(self.bids.items(), reverse=True)[:levels]
|
|
202
|
+
# asks = sorted(self.asks.items())[:levels]
|
|
203
|
+
# return {
|
|
204
|
+
# "bids": [BookOrderData(price=price, size=size) for price, size in bids],
|
|
205
|
+
# "asks": [BookOrderData(price=price, size=size) for price, size in asks],
|
|
206
|
+
# }
|
|
207
|
+
|
|
208
|
+
# # --- Ticker ---
|
|
209
|
+
# class BitgetTicker(msgspec.Struct):
|
|
210
|
+
# symbol: str
|
|
211
|
+
# markPrice: str | None = None
|
|
212
|
+
# indexPrice: str | None = None
|
|
213
|
+
# nextFundingTime: str | None = None
|
|
214
|
+
# fundingRate: str | None = None
|
|
215
|
+
|
|
216
|
+
# class BitgetTickerMsg(msgspec.Struct):
|
|
217
|
+
# event: str
|
|
218
|
+
# arg: Dict[str, Any]
|
|
219
|
+
# data: List[Dict[str, Any]]
|
|
220
|
+
|
|
221
|
+
# # --- Balance ---
|
|
222
|
+
# class BitgetBalanceCoin(msgspec.Struct):
|
|
223
|
+
# coin: str
|
|
224
|
+
# available: str
|
|
225
|
+
# frozen: str
|
|
226
|
+
|
|
227
|
+
# def parse_to_balance(self) -> Balance:
|
|
228
|
+
# locked = Decimal(self.frozen)
|
|
229
|
+
# free = Decimal(self.available)
|
|
230
|
+
# return Balance(asset=self.coin, locked=locked, free=free)
|
|
231
|
+
|
|
232
|
+
# class BitgetBalanceResponse(msgspec.Struct):
|
|
233
|
+
# code: str
|
|
234
|
+
# msg: str
|
|
235
|
+
# data: List[BitgetBalanceCoin]
|
|
236
|
+
|
|
237
|
+
# def parse_to_balances(self) -> List[Balance]:
|
|
238
|
+
# return [coin.parse_to_balance() for coin in self.data]
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
# # --- Market Info ---
|
|
242
|
+
class BitgetMarketInfo(msgspec.Struct, kw_only=True, omit_defaults=True):
|
|
243
|
+
# Common required fields
|
|
244
|
+
symbol: str
|
|
245
|
+
baseCoin: str
|
|
246
|
+
quoteCoin: str
|
|
247
|
+
makerFeeRate: str
|
|
248
|
+
takerFeeRate: str
|
|
249
|
+
minTradeUSDT: str
|
|
250
|
+
|
|
251
|
+
# Spot-only optional fields
|
|
252
|
+
minTradeAmount: Optional[str] = None
|
|
253
|
+
maxTradeAmount: Optional[str] = None
|
|
254
|
+
pricePrecision: Optional[str] = None
|
|
255
|
+
quantityPrecision: Optional[str] = None
|
|
256
|
+
quotePrecision: Optional[str] = None
|
|
257
|
+
status: Optional[str] = None
|
|
258
|
+
buyLimitPriceRatio: Optional[str] = None
|
|
259
|
+
sellLimitPriceRatio: Optional[str] = None
|
|
260
|
+
areaSymbol: Optional[str] = None
|
|
261
|
+
orderQuantity: Optional[str] = None
|
|
262
|
+
openTime: Optional[str] = None
|
|
263
|
+
offTime: Optional[str] = None
|
|
264
|
+
|
|
265
|
+
# Futures-only optional fields
|
|
266
|
+
feeRateUpRatio: Optional[str] = None
|
|
267
|
+
openCostUpRatio: Optional[str] = None
|
|
268
|
+
supportMarginCoins: Optional[List[str]] = None
|
|
269
|
+
minTradeNum: Optional[str] = None
|
|
270
|
+
priceEndStep: Optional[str] = None
|
|
271
|
+
volumePlace: Optional[str] = None
|
|
272
|
+
pricePlace: Optional[str] = None
|
|
273
|
+
sizeMultiplier: Optional[str] = None
|
|
274
|
+
symbolType: Optional[str] = None
|
|
275
|
+
maxSymbolOrderNum: Optional[str] = None
|
|
276
|
+
maxProductOrderNum: Optional[str] = None
|
|
277
|
+
maxPositionNum: Optional[str] = None
|
|
278
|
+
symbolStatus: Optional[str] = None
|
|
279
|
+
limitOpenTime: Optional[str] = None
|
|
280
|
+
deliveryTime: Optional[str] = None
|
|
281
|
+
deliveryStartTime: Optional[str] = None
|
|
282
|
+
launchTime: Optional[str] = None
|
|
283
|
+
fundInterval: Optional[str] = None
|
|
284
|
+
minLever: Optional[str] = None
|
|
285
|
+
maxLever: Optional[str] = None
|
|
286
|
+
posLimit: Optional[str] = None
|
|
287
|
+
maintainTime: Optional[str] = None
|
|
288
|
+
maxMarketOrderQty: Optional[str] = None
|
|
289
|
+
maxOrderQty: Optional[str] = None
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
class BitgetMarket(BaseMarket):
|
|
293
|
+
info: BitgetMarketInfo
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class BitgetOrderCancelData(msgspec.Struct):
|
|
297
|
+
orderId: str
|
|
298
|
+
clientOid: str
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class BitgetOrderCancelResponse(msgspec.Struct):
|
|
302
|
+
code: str
|
|
303
|
+
msg: str
|
|
304
|
+
requestTime: int
|
|
305
|
+
data: BitgetOrderCancelData
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
class BitgetOrderPlaceData(msgspec.Struct, kw_only=True):
|
|
309
|
+
orderId: str
|
|
310
|
+
clientOid: str | None = None
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
class BitgetOrderPlaceResponse(msgspec.Struct):
|
|
314
|
+
code: str
|
|
315
|
+
msg: str
|
|
316
|
+
requestTime: int
|
|
317
|
+
data: BitgetOrderPlaceData
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
class BitgetPositionItem(msgspec.Struct):
|
|
321
|
+
symbol: str
|
|
322
|
+
marginCoin: str
|
|
323
|
+
holdSide: BitgetPositionSide
|
|
324
|
+
openDelegateSize: str
|
|
325
|
+
marginSize: str
|
|
326
|
+
available: str
|
|
327
|
+
locked: str
|
|
328
|
+
total: str
|
|
329
|
+
leverage: str
|
|
330
|
+
openPriceAvg: str
|
|
331
|
+
marginMode: str
|
|
332
|
+
posMode: str
|
|
333
|
+
unrealizedPL: str
|
|
334
|
+
liquidationPrice: str
|
|
335
|
+
markPrice: str
|
|
336
|
+
breakEvenPrice: str
|
|
337
|
+
achievedProfits: str | None = None
|
|
338
|
+
keepMarginRate: str | None = None
|
|
339
|
+
totalFee: str | None = None
|
|
340
|
+
deductedFee: str | None = None
|
|
341
|
+
marginRatio: str | None = None
|
|
342
|
+
assetMode: str | None = None
|
|
343
|
+
uTime: str | None = None
|
|
344
|
+
autoMargin: str | None = None
|
|
345
|
+
cTime: str | None = None
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
class BitgetPositionListResponse(msgspec.Struct):
|
|
349
|
+
code: str
|
|
350
|
+
msg: str
|
|
351
|
+
requestTime: int
|
|
352
|
+
data: list[BitgetPositionItem]
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
class BitgetOrder(msgspec.Struct, kw_only=True):
|
|
356
|
+
orderId: str
|
|
357
|
+
clientOid: Optional[str]
|
|
358
|
+
symbol: str
|
|
359
|
+
baseCoin: str
|
|
360
|
+
quoteCoin: str
|
|
361
|
+
size: Decimal
|
|
362
|
+
price: Decimal
|
|
363
|
+
state: str
|
|
364
|
+
orderType: str
|
|
365
|
+
side: str
|
|
366
|
+
timeInForceValue: Optional[str] = None
|
|
367
|
+
force: Optional[str] = None
|
|
368
|
+
priceAvg: Optional[Decimal] = None
|
|
369
|
+
fillPrice: Optional[Decimal] = None
|
|
370
|
+
filledQty: Optional[Decimal] = None
|
|
371
|
+
fee: Optional[Decimal] = None
|
|
372
|
+
orderSource: Optional[str] = None
|
|
373
|
+
cTime: Optional[int] = None
|
|
374
|
+
uTime: Optional[int] = None
|
|
375
|
+
status: Optional[str] = None
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
class BitgetOpenOrdersResponse(msgspec.Struct, kw_only=True):
|
|
379
|
+
code: str
|
|
380
|
+
msg: Optional[str]
|
|
381
|
+
requestTime: int
|
|
382
|
+
data: List[BitgetOrder]
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
class BitgetOrderHistoryItem(msgspec.Struct, kw_only=True, omit_defaults=True):
|
|
386
|
+
orderId: str
|
|
387
|
+
symbol: str
|
|
388
|
+
price: str
|
|
389
|
+
size: str
|
|
390
|
+
orderType: str
|
|
391
|
+
side: str
|
|
392
|
+
status: str
|
|
393
|
+
createTime: int
|
|
394
|
+
baseCoin: Optional[str] = None
|
|
395
|
+
quoteCoin: Optional[str] = None
|
|
396
|
+
clientOid: Optional[str] = None
|
|
397
|
+
priceAvg: Optional[str] = None
|
|
398
|
+
filledAmount: Optional[str] = None
|
|
399
|
+
enterPointSource: Optional[str] = None
|
|
400
|
+
tradeSide: Optional[str] = None
|
|
401
|
+
forceClose: Optional[bool] = None
|
|
402
|
+
marginMode: Optional[str] = None
|
|
403
|
+
reduceOnly: Optional[bool] = None
|
|
404
|
+
presetStopSurplusPrice: Optional[str] = None
|
|
405
|
+
presetStopLossPrice: Optional[str] = None
|
|
406
|
+
feeDetail: Optional[str] = None
|
|
407
|
+
tradeId: Optional[str] = None
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
class BitgetOrderHistoryResponse(msgspec.Struct, kw_only=True, omit_defaults=True):
|
|
411
|
+
code: str
|
|
412
|
+
msg: str
|
|
413
|
+
requestTime: int
|
|
414
|
+
data: List[BitgetOrderHistoryItem]
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
class BitgetAccountAssetItem(msgspec.Struct):
|
|
418
|
+
coin: str
|
|
419
|
+
available: str
|
|
420
|
+
frozen: str
|
|
421
|
+
locked: str
|
|
422
|
+
limitAvailable: str
|
|
423
|
+
uTime: str
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
class BitgetAccountAssetResponse(msgspec.Struct):
|
|
427
|
+
code: str
|
|
428
|
+
message: str
|
|
429
|
+
requestTime: int
|
|
430
|
+
data: List[BitgetAccountAssetItem]
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
class BitgetOrderModifyResponse(msgspec.Struct, kw_only=True):
|
|
434
|
+
orderId: str
|
|
435
|
+
clientOid: str
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
class BitgetResponse(msgspec.Struct, kw_only=True):
|
|
439
|
+
code: str
|
|
440
|
+
msg: str
|
|
441
|
+
data: BitgetOrderModifyResponse
|
|
442
|
+
requestTime: int
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
class BitgetBaseResponse(msgspec.Struct, kw_only=True):
|
|
446
|
+
code: str
|
|
447
|
+
msg: str
|
|
448
|
+
requestTime: int
|
|
449
|
+
data: Any
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
class BitgetKlineItem(msgspec.Struct):
|
|
453
|
+
timestamp: str # index[0]
|
|
454
|
+
open: str # index[1]
|
|
455
|
+
high: str # index[2]
|
|
456
|
+
low: str # index[3]
|
|
457
|
+
close: str # index[4]
|
|
458
|
+
volume_base: str # index[5]
|
|
459
|
+
volume_quote: str # index[6]
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
class BitgetKlineResponse(msgspec.Struct):
|
|
463
|
+
code: str
|
|
464
|
+
msg: str
|
|
465
|
+
requestTime: int
|
|
466
|
+
data: List[List[str]]
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
class BitgetIndexPriceKlineItem(msgspec.Struct):
|
|
470
|
+
timestamp: str
|
|
471
|
+
open_price: str
|
|
472
|
+
high_price: str
|
|
473
|
+
low_price: str
|
|
474
|
+
close_price: str
|
|
475
|
+
base_volume: str
|
|
476
|
+
quote_volume: str
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
class BitgetIndexPriceKlineResponse(msgspec.Struct):
|
|
480
|
+
code: str
|
|
481
|
+
msg: str
|
|
482
|
+
requestTime: int
|
|
483
|
+
data: List[BitgetIndexPriceKlineItem]
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class BitgetOrderFeeDetail(msgspec.Struct):
|
|
487
|
+
feeCoin: str
|
|
488
|
+
fee: str
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
class BitgetOrderData(msgspec.Struct, kw_only=True):
|
|
492
|
+
# Common required fields (present in both spot and futures)
|
|
493
|
+
instId: str
|
|
494
|
+
orderId: str
|
|
495
|
+
clientOid: str
|
|
496
|
+
size: str
|
|
497
|
+
orderType: BitgetOrderType
|
|
498
|
+
force: BitgetTimeInForce
|
|
499
|
+
side: BitgetOrderSide
|
|
500
|
+
|
|
501
|
+
tradeId: Optional[str] = None
|
|
502
|
+
fillTime: Optional[str] = None
|
|
503
|
+
fillFee: Optional[str] = None
|
|
504
|
+
fillFeeCoin: Optional[str] = None
|
|
505
|
+
tradeScope: Optional[str] = None
|
|
506
|
+
priceAvg: Optional[str] = None
|
|
507
|
+
status: BitgetOrderStatus
|
|
508
|
+
cTime: str
|
|
509
|
+
uTime: str
|
|
510
|
+
stpMode: str
|
|
511
|
+
feeDetail: List[BitgetOrderFeeDetail]
|
|
512
|
+
enterPointSource: str
|
|
513
|
+
|
|
514
|
+
# Optional fields (may be present in spot, futures, or both)
|
|
515
|
+
fillPrice: Optional[str] = None
|
|
516
|
+
newSize: Optional[str] = None
|
|
517
|
+
notional: Optional[str] = None
|
|
518
|
+
baseVolume: Optional[str] = None
|
|
519
|
+
accBaseVolume: Optional[str] = None
|
|
520
|
+
|
|
521
|
+
# Futures-specific optional fields
|
|
522
|
+
fillNotionalUsd: Optional[str] = None
|
|
523
|
+
leverage: Optional[str] = None
|
|
524
|
+
marginCoin: Optional[str] = None
|
|
525
|
+
marginMode: Optional[str] = None
|
|
526
|
+
notionalUsd: Optional[str] = None
|
|
527
|
+
pnl: Optional[str] = None
|
|
528
|
+
posMode: Optional[str] = None
|
|
529
|
+
posSide: Optional[BitgetPositionSide] = None
|
|
530
|
+
price: Optional[str] = None
|
|
531
|
+
reduceOnly: Optional[str] = None
|
|
532
|
+
tradeSide: Optional[str] = None
|
|
533
|
+
presetStopSurplusPrice: Optional[str] = None
|
|
534
|
+
totalProfits: Optional[str] = None
|
|
535
|
+
presetStopLossPrice: Optional[str] = None
|
|
536
|
+
cancelReason: Optional[str] = None
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
class BitgetOrderWsMsg(msgspec.Struct):
|
|
540
|
+
action: str
|
|
541
|
+
arg: BitgetWsArgMsg
|
|
542
|
+
data: List[BitgetOrderData]
|
|
543
|
+
ts: int
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
class BitgetPositionData(msgspec.Struct):
|
|
547
|
+
posId: str
|
|
548
|
+
instId: str
|
|
549
|
+
marginCoin: str
|
|
550
|
+
marginSize: str
|
|
551
|
+
marginMode: str
|
|
552
|
+
holdSide: BitgetPositionSide
|
|
553
|
+
posMode: str
|
|
554
|
+
total: str
|
|
555
|
+
available: str
|
|
556
|
+
frozen: str
|
|
557
|
+
openPriceAvg: str
|
|
558
|
+
leverage: int
|
|
559
|
+
achievedProfits: str
|
|
560
|
+
unrealizedPL: str
|
|
561
|
+
unrealizedPLR: str
|
|
562
|
+
liquidationPrice: str
|
|
563
|
+
keepMarginRate: str
|
|
564
|
+
marginRate: str
|
|
565
|
+
cTime: str
|
|
566
|
+
breakEvenPrice: str
|
|
567
|
+
totalFee: str
|
|
568
|
+
deductedFee: str
|
|
569
|
+
markPrice: str
|
|
570
|
+
uTime: str
|
|
571
|
+
autoMargin: str
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
class BitgetPositionWsMsg(msgspec.Struct):
|
|
575
|
+
action: str
|
|
576
|
+
arg: BitgetWsArgMsg
|
|
577
|
+
data: List[BitgetPositionData]
|
|
578
|
+
ts: int
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
class BitgetSpotAccountData(msgspec.Struct):
|
|
582
|
+
coin: str
|
|
583
|
+
available: str
|
|
584
|
+
frozen: str
|
|
585
|
+
locked: str
|
|
586
|
+
limitAvailable: str
|
|
587
|
+
uTime: str
|
|
588
|
+
|
|
589
|
+
def parse_to_balance(self) -> Balance:
|
|
590
|
+
locked = Decimal(self.frozen) + Decimal(self.locked)
|
|
591
|
+
free = Decimal(self.available)
|
|
592
|
+
return Balance(asset=self.coin, locked=locked, free=free)
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
class BitgetSpotAccountWsMsg(msgspec.Struct):
|
|
596
|
+
data: List[BitgetSpotAccountData]
|
|
597
|
+
ts: int
|
|
598
|
+
|
|
599
|
+
def parse_to_balances(self) -> List[Balance]:
|
|
600
|
+
return [account_data.parse_to_balance() for account_data in self.data]
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
class BitgetFuturesAccountData(msgspec.Struct):
|
|
604
|
+
marginCoin: str
|
|
605
|
+
frozen: str
|
|
606
|
+
available: str
|
|
607
|
+
maxOpenPosAvailable: str
|
|
608
|
+
maxTransferOut: str
|
|
609
|
+
equity: str
|
|
610
|
+
usdtEquity: str
|
|
611
|
+
crossedRiskRate: str
|
|
612
|
+
unrealizedPL: str
|
|
613
|
+
|
|
614
|
+
def parse_to_balance(self) -> Balance:
|
|
615
|
+
locked = Decimal(self.frozen)
|
|
616
|
+
free = Decimal(self.available)
|
|
617
|
+
return Balance(asset=self.marginCoin, locked=locked, free=free)
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
class BitgetFuturesAccountWsMsg(msgspec.Struct):
|
|
621
|
+
data: List[BitgetFuturesAccountData]
|
|
622
|
+
ts: int
|
|
623
|
+
|
|
624
|
+
def parse_to_balances(self) -> List[Balance]:
|
|
625
|
+
return [account_data.parse_to_balance() for account_data in self.data]
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
class BitgetUtaCoinData(msgspec.Struct):
|
|
629
|
+
debts: str
|
|
630
|
+
balance: str
|
|
631
|
+
available: str
|
|
632
|
+
borrow: str
|
|
633
|
+
locked: str
|
|
634
|
+
equity: str
|
|
635
|
+
coin: str
|
|
636
|
+
usdValue: str
|
|
637
|
+
|
|
638
|
+
def parse_to_balance(self) -> Balance:
|
|
639
|
+
locked = Decimal(self.locked)
|
|
640
|
+
free = Decimal(self.available)
|
|
641
|
+
return Balance(asset=self.coin, locked=locked, free=free)
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
class BitgetUtaAccountData(msgspec.Struct):
|
|
645
|
+
unrealisedPnL: str
|
|
646
|
+
totalEquity: str
|
|
647
|
+
positionMgnRatio: str
|
|
648
|
+
mmr: str
|
|
649
|
+
effEquity: str
|
|
650
|
+
imr: str
|
|
651
|
+
mgnRatio: str
|
|
652
|
+
coin: List[BitgetUtaCoinData]
|
|
653
|
+
|
|
654
|
+
def parse_to_balances(self) -> List[Balance]:
|
|
655
|
+
return [coin_data.parse_to_balance() for coin_data in self.coin]
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
class BitgetUtaAccountWsMsg(msgspec.Struct):
|
|
659
|
+
data: List[BitgetUtaAccountData]
|
|
660
|
+
ts: int
|
|
661
|
+
|
|
662
|
+
def parse_to_balances(self) -> List[Balance]:
|
|
663
|
+
balances = []
|
|
664
|
+
for account_data in self.data:
|
|
665
|
+
balances.extend(account_data.parse_to_balances())
|
|
666
|
+
return balances
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
class BitgetUtaOrderFeeDetail(msgspec.Struct):
|
|
670
|
+
feeCoin: str
|
|
671
|
+
fee: str
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
class BitgetUtaOrderData(msgspec.Struct, kw_only=True):
|
|
675
|
+
category: BitgetUtaInstType
|
|
676
|
+
symbol: str
|
|
677
|
+
orderId: str
|
|
678
|
+
clientOid: str
|
|
679
|
+
price: str
|
|
680
|
+
qty: str
|
|
681
|
+
holdMode: str
|
|
682
|
+
holdSide: str
|
|
683
|
+
tradeSide: str
|
|
684
|
+
orderType: BitgetOrderType
|
|
685
|
+
timeInForce: BitgetTimeInForce
|
|
686
|
+
side: BitgetOrderSide
|
|
687
|
+
marginMode: str
|
|
688
|
+
marginCoin: str
|
|
689
|
+
reduceOnly: str
|
|
690
|
+
cumExecQty: str
|
|
691
|
+
cumExecValue: str
|
|
692
|
+
avgPrice: str
|
|
693
|
+
totalProfit: str
|
|
694
|
+
orderStatus: BitgetOrderStatus
|
|
695
|
+
cancelReason: str
|
|
696
|
+
leverage: str
|
|
697
|
+
feeDetail: List[BitgetUtaOrderFeeDetail] | None = None
|
|
698
|
+
createdTime: str
|
|
699
|
+
updatedTime: str
|
|
700
|
+
stpMode: str
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
class BitgetUtaOrderWsMsg(msgspec.Struct):
|
|
704
|
+
data: List[BitgetUtaOrderData]
|
|
705
|
+
ts: int
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
class BitgetUtaPositionData(msgspec.Struct, kw_only=True):
|
|
709
|
+
symbol: str
|
|
710
|
+
leverage: str
|
|
711
|
+
openFeeTotal: str
|
|
712
|
+
mmr: str
|
|
713
|
+
breakEvenPrice: str
|
|
714
|
+
available: str
|
|
715
|
+
liqPrice: str
|
|
716
|
+
marginMode: str
|
|
717
|
+
unrealisedPnl: str
|
|
718
|
+
markPrice: str
|
|
719
|
+
createdTime: str
|
|
720
|
+
openPriceAvg: str | None = None
|
|
721
|
+
totalFundingFee: str
|
|
722
|
+
updatedTime: str
|
|
723
|
+
marginCoin: str
|
|
724
|
+
frozen: str
|
|
725
|
+
profitRate: str
|
|
726
|
+
closeFeeTotal: str
|
|
727
|
+
marginSize: str
|
|
728
|
+
curRealisedPnl: str
|
|
729
|
+
size: str
|
|
730
|
+
posSide: BitgetPositionSide
|
|
731
|
+
holdMode: str
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
class BitgetUtaPositionWsMsg(msgspec.Struct):
|
|
735
|
+
data: List[BitgetUtaPositionData]
|
|
736
|
+
ts: int
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
class BitgetWsApiArgParamsMsg(msgspec.Struct):
|
|
740
|
+
orderId: str | None = None
|
|
741
|
+
clientOid: str | None = None
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
class BitgetWsApiArgMsg(msgspec.Struct):
|
|
745
|
+
id: str
|
|
746
|
+
instType: str
|
|
747
|
+
channel: str
|
|
748
|
+
instId: str
|
|
749
|
+
params: BitgetWsApiArgParamsMsg
|
|
750
|
+
|
|
751
|
+
@property
|
|
752
|
+
def is_place_order(self):
|
|
753
|
+
return self.channel == "place-order"
|
|
754
|
+
|
|
755
|
+
@property
|
|
756
|
+
def is_cancel_order(self):
|
|
757
|
+
return self.channel == "cancel-order"
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
class BitgetWsApiGeneralMsg(msgspec.Struct):
|
|
761
|
+
event: str
|
|
762
|
+
code: int | str
|
|
763
|
+
arg: list[BitgetWsApiArgMsg] | None = None
|
|
764
|
+
msg: str | None = None
|
|
765
|
+
|
|
766
|
+
@property
|
|
767
|
+
def is_success(self):
|
|
768
|
+
return int(self.code) == 0
|
|
769
|
+
|
|
770
|
+
@property
|
|
771
|
+
def is_login_msg(self):
|
|
772
|
+
return self.event == "login"
|
|
773
|
+
|
|
774
|
+
@property
|
|
775
|
+
def is_arg_msg(self):
|
|
776
|
+
return self.arg is not None
|
|
777
|
+
|
|
778
|
+
@property
|
|
779
|
+
def is_error_msg(self):
|
|
780
|
+
return int(self.code) != 0
|
|
781
|
+
|
|
782
|
+
@property
|
|
783
|
+
def error_msg(self):
|
|
784
|
+
return f"code={self.code} msg={self.msg}"
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
class BitgetWsApiUtaArgMsg(msgspec.Struct, kw_only=True):
|
|
788
|
+
orderId: str
|
|
789
|
+
clientOid: str
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
class BitgetWsApiUtaGeneralMsg(msgspec.Struct, kw_only=True):
|
|
793
|
+
event: str
|
|
794
|
+
id: str | None = None
|
|
795
|
+
code: str | int
|
|
796
|
+
args: list[BitgetWsApiUtaArgMsg] | None = None
|
|
797
|
+
msg: str | None = None
|
|
798
|
+
|
|
799
|
+
@property
|
|
800
|
+
def oid(self):
|
|
801
|
+
if not self.id:
|
|
802
|
+
raise ValueError("id is None")
|
|
803
|
+
return self.id[1:]
|
|
804
|
+
|
|
805
|
+
@property
|
|
806
|
+
def is_cancel_order(self) -> bool:
|
|
807
|
+
if not self.id:
|
|
808
|
+
raise ValueError("id is None")
|
|
809
|
+
return self.id.startswith("c")
|
|
810
|
+
|
|
811
|
+
@property
|
|
812
|
+
def is_place_order(self) -> bool:
|
|
813
|
+
if not self.id:
|
|
814
|
+
raise ValueError("id is None")
|
|
815
|
+
return self.id.startswith("n")
|
|
816
|
+
|
|
817
|
+
@property
|
|
818
|
+
def is_success(self):
|
|
819
|
+
return int(self.code) == 0
|
|
820
|
+
|
|
821
|
+
@property
|
|
822
|
+
def is_id_msg(self):
|
|
823
|
+
return self.id is not None
|
|
824
|
+
|
|
825
|
+
@property
|
|
826
|
+
def is_error_msg(self):
|
|
827
|
+
return int(self.code) != 0
|
|
828
|
+
|
|
829
|
+
@property
|
|
830
|
+
def error_msg(self):
|
|
831
|
+
return f"code={self.code} msg={self.msg}"
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
class BitgetTickerResponseData(msgspec.Struct):
|
|
835
|
+
category: BitgetInstType
|
|
836
|
+
symbol: str
|
|
837
|
+
lastPrice: str
|
|
838
|
+
volume24h: str
|
|
839
|
+
turnover24h: str
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
class BitgetTickerResponse(msgspec.Struct):
|
|
843
|
+
code: str
|
|
844
|
+
msg: str
|
|
845
|
+
requestTime: int
|
|
846
|
+
data: List[BitgetTickerResponseData]
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
class BitgetV3PositionData(msgspec.Struct, kw_only=True):
|
|
850
|
+
category: str
|
|
851
|
+
symbol: str
|
|
852
|
+
marginCoin: str
|
|
853
|
+
holdMode: str
|
|
854
|
+
posSide: str
|
|
855
|
+
marginMode: str
|
|
856
|
+
positionBalance: str
|
|
857
|
+
available: str
|
|
858
|
+
frozen: str
|
|
859
|
+
total: str
|
|
860
|
+
leverage: str
|
|
861
|
+
curRealisedPnl: str
|
|
862
|
+
avgPrice: str
|
|
863
|
+
positionStatus: str
|
|
864
|
+
unrealisedPnl: str
|
|
865
|
+
liquidationPrice: str
|
|
866
|
+
mmr: str
|
|
867
|
+
profitRate: str
|
|
868
|
+
markPrice: str
|
|
869
|
+
breakEvenPrice: str
|
|
870
|
+
totalFunding: str
|
|
871
|
+
openFeeTotal: str
|
|
872
|
+
closeFeeTotal: str
|
|
873
|
+
createdTime: str
|
|
874
|
+
updatedTime: str
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
class BitgetV3PositionResponseData(msgspec.Struct):
|
|
878
|
+
list: List[BitgetV3PositionData] | None = None
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
class BitgetV3PositionResponse(msgspec.Struct):
|
|
882
|
+
code: str
|
|
883
|
+
msg: str
|
|
884
|
+
requestTime: int
|
|
885
|
+
data: BitgetV3PositionResponseData
|