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.
Files changed (105) hide show
  1. walrasquant/__init__.py +7 -0
  2. walrasquant/aggregation.py +449 -0
  3. walrasquant/backends/__init__.py +5 -0
  4. walrasquant/backends/db.py +109 -0
  5. walrasquant/backends/db_memory.py +61 -0
  6. walrasquant/backends/db_postgresql.py +321 -0
  7. walrasquant/backends/db_sqlite.py +310 -0
  8. walrasquant/base/__init__.py +24 -0
  9. walrasquant/base/api_client.py +46 -0
  10. walrasquant/base/connector.py +863 -0
  11. walrasquant/base/ems.py +794 -0
  12. walrasquant/base/exchange.py +213 -0
  13. walrasquant/base/oms.py +428 -0
  14. walrasquant/base/retry.py +220 -0
  15. walrasquant/base/sms.py +545 -0
  16. walrasquant/base/ws_client.py +408 -0
  17. walrasquant/config.py +284 -0
  18. walrasquant/constants.py +413 -0
  19. walrasquant/core/__init__.py +0 -0
  20. walrasquant/core/cache.py +688 -0
  21. walrasquant/core/clock.py +59 -0
  22. walrasquant/core/connection.py +41 -0
  23. walrasquant/core/entity.py +504 -0
  24. walrasquant/core/nautilius_core.py +103 -0
  25. walrasquant/core/registry.py +41 -0
  26. walrasquant/engine.py +745 -0
  27. walrasquant/error.py +34 -0
  28. walrasquant/exchange/__init__.py +13 -0
  29. walrasquant/exchange/base_factory.py +172 -0
  30. walrasquant/exchange/binance/__init__.py +30 -0
  31. walrasquant/exchange/binance/connector.py +1093 -0
  32. walrasquant/exchange/binance/constants.py +934 -0
  33. walrasquant/exchange/binance/ems.py +140 -0
  34. walrasquant/exchange/binance/error.py +48 -0
  35. walrasquant/exchange/binance/exchange.py +144 -0
  36. walrasquant/exchange/binance/factory.py +115 -0
  37. walrasquant/exchange/binance/oms.py +1807 -0
  38. walrasquant/exchange/binance/rest_api.py +1653 -0
  39. walrasquant/exchange/binance/schema.py +1063 -0
  40. walrasquant/exchange/binance/websockets.py +389 -0
  41. walrasquant/exchange/bitget/__init__.py +28 -0
  42. walrasquant/exchange/bitget/connector.py +578 -0
  43. walrasquant/exchange/bitget/constants.py +392 -0
  44. walrasquant/exchange/bitget/ems.py +202 -0
  45. walrasquant/exchange/bitget/error.py +36 -0
  46. walrasquant/exchange/bitget/exchange.py +128 -0
  47. walrasquant/exchange/bitget/factory.py +135 -0
  48. walrasquant/exchange/bitget/oms.py +1619 -0
  49. walrasquant/exchange/bitget/rest_api.py +610 -0
  50. walrasquant/exchange/bitget/schema.py +885 -0
  51. walrasquant/exchange/bitget/websockets.py +753 -0
  52. walrasquant/exchange/bybit/__init__.py +32 -0
  53. walrasquant/exchange/bybit/connector.py +819 -0
  54. walrasquant/exchange/bybit/constants.py +479 -0
  55. walrasquant/exchange/bybit/ems.py +93 -0
  56. walrasquant/exchange/bybit/error.py +36 -0
  57. walrasquant/exchange/bybit/exchange.py +108 -0
  58. walrasquant/exchange/bybit/factory.py +128 -0
  59. walrasquant/exchange/bybit/oms.py +1195 -0
  60. walrasquant/exchange/bybit/rest_api.py +570 -0
  61. walrasquant/exchange/bybit/schema.py +867 -0
  62. walrasquant/exchange/bybit/websockets.py +307 -0
  63. walrasquant/exchange/hyperliquid/__init__.py +28 -0
  64. walrasquant/exchange/hyperliquid/connector.py +370 -0
  65. walrasquant/exchange/hyperliquid/constants.py +371 -0
  66. walrasquant/exchange/hyperliquid/ems.py +156 -0
  67. walrasquant/exchange/hyperliquid/error.py +48 -0
  68. walrasquant/exchange/hyperliquid/exchange.py +120 -0
  69. walrasquant/exchange/hyperliquid/factory.py +135 -0
  70. walrasquant/exchange/hyperliquid/oms.py +1081 -0
  71. walrasquant/exchange/hyperliquid/rest_api.py +348 -0
  72. walrasquant/exchange/hyperliquid/schema.py +583 -0
  73. walrasquant/exchange/hyperliquid/websockets.py +592 -0
  74. walrasquant/exchange/okx/__init__.py +25 -0
  75. walrasquant/exchange/okx/connector.py +931 -0
  76. walrasquant/exchange/okx/constants.py +518 -0
  77. walrasquant/exchange/okx/ems.py +144 -0
  78. walrasquant/exchange/okx/error.py +66 -0
  79. walrasquant/exchange/okx/exchange.py +102 -0
  80. walrasquant/exchange/okx/factory.py +138 -0
  81. walrasquant/exchange/okx/oms.py +1199 -0
  82. walrasquant/exchange/okx/rest_api.py +799 -0
  83. walrasquant/exchange/okx/schema.py +1449 -0
  84. walrasquant/exchange/okx/websockets.py +420 -0
  85. walrasquant/exchange/registry.py +201 -0
  86. walrasquant/execution/__init__.py +24 -0
  87. walrasquant/execution/algorithm.py +968 -0
  88. walrasquant/execution/algorithms/__init__.py +3 -0
  89. walrasquant/execution/algorithms/twap.py +392 -0
  90. walrasquant/execution/config.py +34 -0
  91. walrasquant/execution/constants.py +27 -0
  92. walrasquant/execution/schema.py +62 -0
  93. walrasquant/indicator.py +382 -0
  94. walrasquant/push.py +77 -0
  95. walrasquant/schema.py +755 -0
  96. walrasquant/strategy.py +1805 -0
  97. walrasquant/tools/__init__.py +0 -0
  98. walrasquant/tools/pm2_wrapper.py +1016 -0
  99. walrasquant/web/__init__.py +26 -0
  100. walrasquant/web/app.py +157 -0
  101. walrasquant/web/server.py +92 -0
  102. walrasquant_lib-0.4.20.dist-info/METADATA +162 -0
  103. walrasquant_lib-0.4.20.dist-info/RECORD +105 -0
  104. walrasquant_lib-0.4.20.dist-info/WHEEL +4 -0
  105. walrasquant_lib-0.4.20.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,1063 @@
1
+ import msgspec
2
+ from decimal import Decimal
3
+ from typing import Any, Dict, List
4
+ from walrasquant.schema import BaseMarket, Balance, BookOrderData # noqa: F401
5
+ from walrasquant.exchange.binance.constants import (
6
+ BinanceAccountEventReasonType,
7
+ BinanceOrderStatus,
8
+ BinanceOrderType,
9
+ BinancePositionSide,
10
+ BinanceWsEventType,
11
+ BinanceKlineInterval,
12
+ BinancePriceMatch,
13
+ BinanceUserDataStreamWsEventType,
14
+ BinanceOrderSide,
15
+ BinanceTimeInForce,
16
+ BinanceExecutionType,
17
+ BinanceFuturesWorkingType,
18
+ BinanceBusinessUnit,
19
+ )
20
+
21
+
22
+ class BinanceResultId(msgspec.Struct):
23
+ id: int | None = None
24
+
25
+
26
+ class BinanceBnbTransferResponse(msgspec.Struct):
27
+ tranId: int
28
+
29
+
30
+ class BinanceFuturesBalanceInfo(msgspec.Struct, frozen=True):
31
+ asset: str # asset name
32
+ walletBalance: str # wallet balance
33
+ unrealizedProfit: str # unrealized profit
34
+ marginBalance: str # margin balance
35
+ maintMargin: str # maintenance margin required
36
+ initialMargin: str # total initial margin required with current mark price
37
+ positionInitialMargin: (
38
+ str # initial margin required for positions with current mark price
39
+ )
40
+ openOrderInitialMargin: (
41
+ str # initial margin required for open orders with current mark price
42
+ )
43
+ crossWalletBalance: str # crossed wallet balance
44
+ crossUnPnl: str # unrealized profit of crossed positions
45
+ availableBalance: str # available balance
46
+ maxWithdrawAmount: str # maximum amount for transfer out
47
+ # whether the asset can be used as margin in Multi - Assets mode
48
+ marginAvailable: bool | None = None
49
+ updateTime: int | None = None # last update time
50
+
51
+ def parse_to_balance(self) -> Balance:
52
+ free = Decimal(self.availableBalance)
53
+ locked = Decimal(self.marginBalance) - free
54
+ return Balance(
55
+ asset=self.asset,
56
+ free=free,
57
+ locked=locked,
58
+ )
59
+
60
+
61
+ class BinanceFuturesPositionInfo(msgspec.Struct, kw_only=True):
62
+ symbol: str # symbol name
63
+ initialMargin: str # initial margin required with current mark price
64
+ maintMargin: str # maintenance margin required
65
+ unrealizedProfit: str # unrealized profit
66
+ positionInitialMargin: (
67
+ str # initial margin required for positions with current mark price
68
+ )
69
+ openOrderInitialMargin: (
70
+ str # initial margin required for open orders with current mark price
71
+ )
72
+ leverage: str # current initial leverage
73
+ isolated: bool # if the position is isolated
74
+ entryPrice: str # average entry price
75
+ maxNotional: str | None = None # maximum available notional with current leverage
76
+ bidNotional: str | None = None # bids notional, ignore
77
+ askNotional: str | None = None # ask notional, ignore
78
+ positionSide: BinancePositionSide # position side
79
+ positionAmt: str # position amount
80
+ updateTime: int
81
+ breakEvenPrice: str | None = None # break-even price
82
+ maxQty: str | None = None # maximum quantity of base asset
83
+
84
+
85
+ class BinancePortfolioMarginPositionRisk(msgspec.Struct, kw_only=True):
86
+ """
87
+ "entryPrice": "0.00000",
88
+ "leverage": "10",
89
+ "markPrice": "6679.50671178",
90
+ "maxNotionalValue": "20000000",
91
+ "positionAmt": "0.000",
92
+ "notional": "0",
93
+ "symbol": "BTCUSDT",
94
+ "unRealizedProfit": "0.00000000",
95
+ "liquidationPrice": "6170.20509059",
96
+ "positionSide": "BOTH",
97
+ "updateTime": 1625474304765
98
+
99
+ "symbol": "BTCUSD_201225",
100
+ "positionAmt": "1",
101
+ "entryPrice": "11707.70000003",
102
+ "markPrice": "11788.66626667",
103
+ "unRealizedProfit": "0.00005866",
104
+ "liquidationPrice": "6170.20509059",
105
+ "leverage": "125",
106
+ "positionSide": "LONG",
107
+ "updateTime": 1627026881327,
108
+ "maxQty": "50",
109
+ "notionalValue": "0.00084827"
110
+ """
111
+
112
+ symbol: str
113
+ markPrice: str
114
+ entryPrice: str
115
+ unRealizedProfit: str
116
+ positionAmt: str
117
+ positionSide: BinancePositionSide
118
+ liquidationPrice: str
119
+ updateTime: int
120
+ leverage: str
121
+
122
+ notional: str | None = None
123
+ maxNotionalValue: str | None = None
124
+
125
+ maxQty: str | None = None
126
+ notionalValue: str | None = None
127
+
128
+
129
+ class BinancePortfolioMarginBalance(msgspec.Struct, kw_only=True):
130
+ """
131
+ "asset": "USDT", // asset name
132
+ "totalWalletBalance": "122607.35137903", // wallet balance = cross margin free + cross margin locked + UM wallet balance + CM wallet balance
133
+ "crossMarginAsset": "92.27530794", // crossMarginAsset = crossMarginFree + crossMarginLocked
134
+ "crossMarginBorrowed": "10.00000000", // principal of cross margin
135
+ "crossMarginFree": "100.00000000", // free asset of cross margin
136
+ "crossMarginInterest": "0.72469206", // interest of cross margin
137
+ "crossMarginLocked": "3.00000000", //lock asset of cross margin
138
+ "umWalletBalance": "0.00000000", // wallet balance of um
139
+ "umUnrealizedPNL": "23.72469206", // unrealized profit of um
140
+ "cmWalletBalance": "23.72469206", // wallet balance of cm
141
+ "cmUnrealizedPNL": "", // unrealized profit of cm
142
+ "updateTime": 1617939110373,
143
+ "negativeBalance": "0"
144
+ """
145
+
146
+ asset: str
147
+ totalWalletBalance: str
148
+ crossMarginAsset: str
149
+ crossMarginBorrowed: str
150
+ crossMarginFree: str
151
+ crossMarginInterest: str
152
+ crossMarginLocked: str
153
+ umWalletBalance: str
154
+ umUnrealizedPNL: str
155
+ cmWalletBalance: str
156
+ cmUnrealizedPNL: str
157
+ updateTime: int
158
+ negativeBalance: str
159
+
160
+ def parse_to_balances(self) -> list[Balance]:
161
+ return [
162
+ Balance(
163
+ asset=f"{self.asset}.SPOT",
164
+ free=Decimal(self.crossMarginFree),
165
+ locked=Decimal(self.crossMarginLocked),
166
+ ),
167
+ Balance(
168
+ asset=f"{self.asset}.UM",
169
+ free=Decimal(self.umWalletBalance),
170
+ ),
171
+ Balance(
172
+ asset=f"{self.asset}.CM",
173
+ free=Decimal(self.cmWalletBalance),
174
+ ),
175
+ ]
176
+
177
+
178
+ class BinanceFuturesAccountInfo(msgspec.Struct, kw_only=True):
179
+ feeTier: int # account commission tier
180
+ canTrade: bool # if can trade
181
+ canDeposit: bool # if can transfer in asset
182
+ canWithdraw: bool # if can transfer out asset
183
+ updateTime: int
184
+ totalInitialMargin: str | None = (
185
+ None # total initial margin required with current mark price (useless with isolated positions), only for USDT
186
+ )
187
+ totalMaintMargin: str | None = (
188
+ None # total maintenance margin required, only for USDT asset
189
+ )
190
+ totalWalletBalance: str | None = None # total wallet balance, only for USDT asset
191
+ totalUnrealizedProfit: str | None = (
192
+ None # total unrealized profit, only for USDT asset
193
+ )
194
+ totalMarginBalance: str | None = None # total margin balance, only for USDT asset
195
+ # initial margin required for positions with current mark price, only for USDT asset
196
+ totalPositionInitialMargin: str | None = None
197
+ # initial margin required for open orders with current mark price, only for USDT asset
198
+ totalOpenOrderInitialMargin: str | None = None
199
+ totalCrossWalletBalance: str | None = (
200
+ None # crossed wallet balance, only for USDT asset
201
+ )
202
+ # unrealized profit of crossed positions, only for USDT asset
203
+ totalCrossUnPnl: str | None = None
204
+ availableBalance: str | None = None # available balance, only for USDT asset
205
+ maxWithdrawAmount: str | None = (
206
+ None # maximum amount for transfer out, only for USDT asset
207
+ )
208
+ assets: list[BinanceFuturesBalanceInfo]
209
+ positions: list[BinanceFuturesPositionInfo]
210
+
211
+ def parse_to_balances(self) -> List[Balance]:
212
+ return [balance.parse_to_balance() for balance in self.assets]
213
+
214
+
215
+ class BinanceSpotBalanceInfo(msgspec.Struct):
216
+ asset: str
217
+ free: str
218
+ locked: str
219
+
220
+ def parse_to_balance(self) -> Balance:
221
+ return Balance(
222
+ asset=self.asset,
223
+ free=Decimal(self.free),
224
+ locked=Decimal(self.locked),
225
+ )
226
+
227
+
228
+ class BinanceSpotAccountInfo(msgspec.Struct, frozen=True):
229
+ makerCommission: int
230
+ takerCommission: int
231
+ buyerCommission: int
232
+ sellerCommission: int
233
+ canTrade: bool
234
+ canWithdraw: bool
235
+ canDeposit: bool
236
+ updateTime: int
237
+ accountType: str
238
+ balances: list[BinanceSpotBalanceInfo]
239
+ permissions: list[str]
240
+
241
+ def parse_to_balances(self) -> List[Balance]:
242
+ return [balance.parse_to_balance() for balance in self.balances]
243
+
244
+
245
+ class _BinanceSpotOrderUpdateMsg(msgspec.Struct, kw_only=True):
246
+ C: str | None = None
247
+ E: int
248
+ F: str | None = None
249
+ I: int # noqa: E741
250
+ L: str
251
+ M: bool | None = None
252
+ N: str | None = None
253
+ O: int # noqa: E741
254
+ P: str
255
+ Q: str | None = None
256
+ S: BinanceOrderSide
257
+ T: int
258
+ V: str
259
+ W: int | None = None # Working Time
260
+ X: BinanceOrderStatus
261
+ Y: str
262
+ Z: str
263
+ c: str
264
+ e: BinanceUserDataStreamWsEventType
265
+ f: BinanceTimeInForce
266
+ g: int
267
+ i: int
268
+ l: str # noqa: E741
269
+ m: bool
270
+ n: str | None = None
271
+ o: BinanceOrderType
272
+ p: str
273
+ q: str
274
+ r: str | None = None
275
+ s: str
276
+ t: int
277
+ v: int | None = None
278
+ w: bool
279
+ x: BinanceExecutionType
280
+ z: str
281
+
282
+ A: str | None = None # Prevented Quantity
283
+ B: str | None = None # Last Prevented Quantity
284
+ D: int | None = None # trailing time
285
+ J: int | None = None # strategy type
286
+ U: int | None = None # CounterOrderId
287
+ d: int | None = None # trailing Delta
288
+ j: int | None = None # strategy id
289
+ u: int | None = None # Trade Group id
290
+
291
+
292
+ class BinanceSpotOrderUpdateMsg(msgspec.Struct, kw_only=True):
293
+ event: _BinanceSpotOrderUpdateMsg
294
+
295
+
296
+ class BinanceFuturesOrderData(msgspec.Struct, kw_only=True):
297
+ L: str # Last Filled Price
298
+ N: str | None = None # Commission Asset, omitted when no commission is charged
299
+ R: bool # Is reduce only
300
+ S: BinanceOrderSide
301
+ T: int # Order Trade Time
302
+ V: str # Order Filled Accumulated Quantity
303
+ X: BinanceOrderStatus
304
+ a: str # Ask Notional
305
+ ap: str # Average Price
306
+ b: str # Bids Notional
307
+ c: str # Client Order ID
308
+ f: BinanceTimeInForce
309
+ i: int # Order ID
310
+ l: str # Order Last Filled Quantity # noqa: E741
311
+ m: bool # Is trade the maker side
312
+ n: str | None = None # Commission, omitted when no commission is charged
313
+ o: BinanceOrderType
314
+ p: str # Original Price
315
+ ps: BinancePositionSide
316
+ q: str # Original Quantity
317
+ rp: str # Realized Profit of the trade
318
+ s: str # Symbol
319
+ sp: str # Stop Price
320
+ t: int # Trade ID
321
+ x: BinanceExecutionType
322
+ z: str # Order Filled Accumulated Quantity
323
+
324
+ AP: str | None = None # Activation Price
325
+ cp: bool | None = None # If Close-All, pushed with conditional order
326
+ cr: str | None = None # Callback Rate
327
+ gtd: int | None = None # TIF GTD order auto cancel time
328
+ ot: BinanceOrderType | None = None
329
+ pP: bool | None = None # ignore
330
+ pm: str | None = None # Order Margin Type
331
+ si: int | None = None # ignore
332
+ ss: int | None = None # ignore
333
+ wt: BinanceFuturesWorkingType | None = None
334
+ ma: str | None = None # Order Margin Type
335
+ st: str | None = (
336
+ None # Strategy type, only pushed with conditional order triggered
337
+ )
338
+
339
+
340
+ class BinanceFuturesOrderUpdateMsg(msgspec.Struct, kw_only=True):
341
+ """
342
+ WebSocket message for Binance Futures Order Update events.
343
+ """
344
+
345
+ e: BinanceUserDataStreamWsEventType
346
+ E: int # Event Time
347
+ T: int # Transaction Time
348
+ fs: BinanceBusinessUnit | None = (
349
+ None # Event business unit. 'UM' for USDS-M futures and 'CM' for COIN-M futures
350
+ )
351
+ o: BinanceFuturesOrderData
352
+
353
+
354
+ class BinanceMarkPriceDataStream(msgspec.Struct):
355
+ e: BinanceWsEventType
356
+ E: int
357
+ s: str
358
+ p: str
359
+ i: str
360
+ P: str
361
+ r: str
362
+ T: int
363
+
364
+
365
+ class BinanceMarkPrice(msgspec.Struct):
366
+ data: BinanceMarkPriceDataStream
367
+ stream: str
368
+
369
+
370
+ class BinanceKlineData(msgspec.Struct):
371
+ t: int # Kline start time
372
+ T: int # Kline close time
373
+ s: str # Symbol
374
+ i: BinanceKlineInterval # Interval
375
+ f: int # First trade ID
376
+ L: int # Last trade ID
377
+ o: str # Open price
378
+ c: str # Close price
379
+ h: str # High price
380
+ l: str # Low price # noqa
381
+ v: str # Base asset volume
382
+ n: int # Number of trades
383
+ x: bool # Is this kline closed?
384
+ q: str # Quote asset volume
385
+ V: str # Taker buy base asset volume
386
+ Q: str # Taker buy quote asset volume
387
+ B: str # Ignore
388
+
389
+
390
+ class BinanceKlineDataStream(msgspec.Struct):
391
+ e: BinanceWsEventType
392
+ E: int
393
+ s: str
394
+ k: BinanceKlineData
395
+
396
+
397
+ class BinanceKline(msgspec.Struct):
398
+ data: BinanceKlineDataStream
399
+ stream: str
400
+
401
+
402
+ class BinanceTradeDataStream(msgspec.Struct):
403
+ e: BinanceWsEventType
404
+ E: int
405
+ s: str
406
+ t: int
407
+ p: str
408
+ q: str
409
+ T: int
410
+ m: bool # Is the buyer the market maker? true -> side=SELL, false -> side=BUY
411
+
412
+
413
+ class BinanceTradeData(msgspec.Struct):
414
+ data: BinanceTradeDataStream
415
+ stream: str
416
+
417
+
418
+ class BinanceSpotBookTickerData(msgspec.Struct):
419
+ """
420
+ {
421
+ "u":400900217, // order book updateId
422
+ "s":"BNBUSDT", // symbol
423
+ "b":"25.35190000", // best bid price
424
+ "B":"31.21000000", // best bid qty
425
+ "a":"25.36520000", // best ask price
426
+ "A":"40.66000000" // best ask qty
427
+ }
428
+ """
429
+
430
+ u: int
431
+ s: str
432
+ b: str
433
+ B: str
434
+ a: str
435
+ A: str
436
+
437
+
438
+ class BinanceSpotBookTicker(msgspec.Struct):
439
+ data: BinanceSpotBookTickerData
440
+ stream: str
441
+
442
+
443
+ class BinanceFuturesBookTickerData(msgspec.Struct):
444
+ e: BinanceWsEventType
445
+ u: int
446
+ E: int
447
+ T: int
448
+ s: str
449
+ b: str
450
+ B: str
451
+ a: str
452
+ A: str
453
+
454
+
455
+ class BinanceFuturesBookTicker(msgspec.Struct):
456
+ data: BinanceFuturesBookTickerData
457
+ stream: str
458
+
459
+
460
+ class BinanceWsMessageGeneralData(msgspec.Struct):
461
+ e: BinanceWsEventType | None = None
462
+ u: int | None = None
463
+
464
+
465
+ class BinanceWsMessageGeneral(msgspec.Struct):
466
+ data: BinanceWsMessageGeneralData
467
+
468
+
469
+ class BinanceUserDataStreamMsg(msgspec.Struct):
470
+ e: BinanceUserDataStreamWsEventType | None = None
471
+
472
+
473
+ class BinanceSpotUserDataStreamMsg(msgspec.Struct):
474
+ event: BinanceUserDataStreamMsg | None = None
475
+
476
+
477
+ class BinanceListenKey(msgspec.Struct):
478
+ listenKey: str
479
+
480
+
481
+ class BinanceUserTrade(msgspec.Struct, frozen=True):
482
+ commission: str
483
+ commissionAsset: str
484
+ price: str
485
+ qty: str
486
+
487
+ # Parameters not present in 'fills' list (see FULL response of BinanceOrder)
488
+ symbol: str | None = None
489
+ id: int | None = None
490
+ orderId: int | None = None
491
+ time: int | None = None
492
+ quoteQty: str | None = None # SPOT/MARGIN & USD-M FUTURES only
493
+
494
+ # Parameters in SPOT/MARGIN only:
495
+ orderListId: int | None = None # unless OCO, the value will always be -1
496
+ isBuyer: bool | None = None
497
+ isMaker: bool | None = None
498
+ isBestMatch: bool | None = None
499
+ tradeId: int | None = None # only in BinanceOrder FULL response
500
+
501
+ # Parameters in FUTURES only:
502
+ buyer: bool | None = None
503
+ maker: bool | None = None
504
+ realizedPnl: str | None = None
505
+ side: BinanceOrderSide | None = None
506
+ positionSide: str | None = None
507
+ baseQty: str | None = None # COIN-M FUTURES only
508
+ pair: str | None = None # COIN-M FUTURES only
509
+
510
+
511
+ class BinanceOrder(msgspec.Struct, frozen=True):
512
+ symbol: str
513
+ orderId: int
514
+ clientOrderId: str
515
+
516
+ # Parameters not in ACK response:
517
+ price: str | None = None
518
+ origQty: str | None = None
519
+ executedQty: str | None = None
520
+ status: BinanceOrderStatus | None = None
521
+ timeInForce: BinanceTimeInForce | None = None
522
+ goodTillDate: int | None = None
523
+ type: BinanceOrderType | None = None
524
+ side: BinanceOrderSide | None = None
525
+ stopPrice: str | None = (
526
+ None # please ignore when order type is TRAILING_STOP_MARKET
527
+ )
528
+ time: int | None = None
529
+ updateTime: int | None = None
530
+
531
+ # Parameters in SPOT/MARGIN only:
532
+ orderListId: int | None = None # Unless OCO, the value will always be -1
533
+ cumulativeQuoteQty: str | None = None # cumulative quote qty
534
+ icebergQty: str | None = None
535
+ isWorking: bool | None = None
536
+ workingTime: int | None = None
537
+ origQuoteOrderQty: str | None = None
538
+ selfTradePreventionMode: str | None = None
539
+ transactTime: int | None = None # POST & DELETE methods only
540
+ fills: list[BinanceUserTrade] | None = None # FULL response only
541
+
542
+ # Parameters in FUTURES only:
543
+ avgPrice: str | None = None
544
+ origType: BinanceOrderType | None = None
545
+ reduceOnly: bool | None = None
546
+ positionSide: BinancePositionSide | None = None
547
+ closePosition: bool | None = None
548
+ activatePrice: str | None = (
549
+ None # activation price, only for TRAILING_STOP_MARKET order
550
+ )
551
+ priceRate: str | None = None # callback rate, only for TRAILING_STOP_MARKET order
552
+ workingType: str | None = None
553
+ priceProtect: bool | None = None # if conditional order trigger is protected
554
+ cumQuote: str | None = None # USD-M FUTURES only
555
+ cumBase: str | None = None # COIN-M FUTURES only
556
+ pair: str | None = None # COIN-M FUTURES only
557
+
558
+
559
+ class BinanceFuturesModifyOrderResponse(msgspec.Struct, frozen=True, kw_only=True):
560
+ """
561
+ {
562
+ "orderId": 20072994037,
563
+ "symbol": "BTCUSDT",
564
+ "pair": "BTCUSDT",
565
+ "status": "NEW",
566
+ "clientOrderId": "LJ9R4QZDihCaS8UAOOLpgW",
567
+ "price": "30005",
568
+ "avgPrice": "0.0",
569
+ "origQty": "1",
570
+ "executedQty": "0",
571
+ "cumQty": "0",
572
+ "cumBase": "0",
573
+ "timeInForce": "GTC",
574
+ "type": "LIMIT",
575
+ "reduceOnly": false,
576
+ "closePosition": false,
577
+ "side": "BUY",
578
+ "positionSide": "LONG",
579
+ "stopPrice": "0",
580
+ "workingType": "CONTRACT_PRICE",
581
+ "priceProtect": false,
582
+ "origType": "LIMIT",
583
+ "priceMatch": "NONE", //price match mode
584
+ "selfTradePreventionMode": "NONE", //self trading preventation mode
585
+ "goodTillDate": 0, //order pre-set auot cancel time for TIF GTD order
586
+ "updateTime": 1629182711600
587
+ }
588
+ """
589
+
590
+ orderId: int
591
+ symbol: str
592
+ pair: str | None = None
593
+ status: BinanceOrderStatus
594
+ clientOrderId: str
595
+ price: str
596
+ avgPrice: str
597
+ origQty: str
598
+ executedQty: str
599
+ cumQty: str
600
+ cumBase: str | None = None
601
+ cumQuote: str | None = None
602
+ timeInForce: BinanceTimeInForce
603
+ type: BinanceOrderType
604
+ reduceOnly: bool | None = None
605
+ closePosition: bool | None = None
606
+ side: BinanceOrderSide
607
+ positionSide: BinancePositionSide
608
+ stopPrice: str | None = None
609
+ workingType: BinanceFuturesWorkingType | None = None
610
+ priceProtect: bool | None = None
611
+ origType: BinanceOrderType
612
+ priceMatch: BinancePriceMatch | None = None
613
+ selfTradePreventionMode: str | None = None
614
+ goodTillDate: int | None = None
615
+ updateTime: int
616
+
617
+
618
+ class BinanceMarketInfo(msgspec.Struct):
619
+ symbol: str | None = None
620
+ status: str | None = None
621
+ baseAsset: str | None = None
622
+ baseAssetPrecision: str | int | None = None
623
+ quoteAsset: str | None = None
624
+ quotePrecision: str | int | None = None
625
+ quoteAssetPrecision: str | int | None = None
626
+ baseCommissionPrecision: str | int | None = None
627
+ quoteCommissionPrecision: str | int | None = None
628
+ orderTypes: List[BinanceOrderType] | None = None
629
+ icebergAllowed: bool | None = None
630
+ ocoAllowed: bool | None = None
631
+ otoAllowed: bool | None = None
632
+ quoteOrderQtyMarketAllowed: bool | None = None
633
+ allowTrailingStop: bool | None = None
634
+ cancelReplaceAllowed: bool | None = None
635
+ isSpotTradingAllowed: bool | None = None
636
+ isMarginTradingAllowed: bool | None = None
637
+ filters: List[Dict[str, Any]] | None = None
638
+ permissions: List[str] | None = None
639
+ permissionSets: List[List[str] | str] | None = None
640
+ defaultSelfTradePreventionMode: str | None = None
641
+ allowedSelfTradePreventionModes: List[str] | None = None
642
+
643
+
644
+ class BinanceMarket(BaseMarket):
645
+ info: BinanceMarketInfo
646
+ feeSide: str
647
+
648
+
649
+ class BinanceFuturesBalanceData(msgspec.Struct):
650
+ a: str
651
+ wb: str # wallet balance
652
+ cw: str # cross wallet balance
653
+ bc: str # wallet change except PnL and Commission
654
+
655
+ def parse_to_balance(self) -> Balance:
656
+ return Balance(
657
+ asset=self.a,
658
+ free=Decimal(self.wb),
659
+ locked=Decimal(0),
660
+ )
661
+
662
+ def pm_parse_to_balance(self, fs: BinanceBusinessUnit) -> Balance:
663
+ return Balance(
664
+ asset=f"{self.a}.{fs.value}",
665
+ free=Decimal(self.wb),
666
+ locked=Decimal(0),
667
+ )
668
+
669
+
670
+ class BinanceFuturesPositionData(msgspec.Struct, kw_only=True):
671
+ s: str
672
+ pa: str # position amount
673
+ ep: str # entry price
674
+ bep: str | float # breakeven price
675
+ cr: str # (Pre-fee) Accumulated Realized
676
+ up: str # Unrealized PnL
677
+ mt: str | None = None # margin type (if isolated position)
678
+ iw: str | None = None # isolated wallet (if isolated position)
679
+ ps: BinancePositionSide
680
+
681
+
682
+ class BinanceFuturesUpdateData(msgspec.Struct, kw_only=True):
683
+ m: BinanceAccountEventReasonType
684
+ B: list[BinanceFuturesBalanceData]
685
+ P: list[BinanceFuturesPositionData]
686
+
687
+ def parse_to_balances(self) -> List[Balance]:
688
+ return [balance.parse_to_balance() for balance in self.B]
689
+
690
+ def pm_parse_to_balances(self, fs: BinanceBusinessUnit) -> List[Balance]:
691
+ return [balance.pm_parse_to_balance(fs) for balance in self.B]
692
+
693
+
694
+ class BinanceFuturesUpdateMsg(msgspec.Struct, kw_only=True):
695
+ e: BinanceUserDataStreamWsEventType
696
+ E: int
697
+ T: int
698
+ fs: BinanceBusinessUnit | None = None
699
+ a: BinanceFuturesUpdateData
700
+
701
+ def parse_to_balances(self) -> List[Balance]:
702
+ if self.fs is not None:
703
+ return self.a.pm_parse_to_balances(self.fs)
704
+ else:
705
+ return self.a.parse_to_balances()
706
+
707
+
708
+ class BinanceSpotBalanceData(msgspec.Struct):
709
+ a: str # asset
710
+ f: str # free
711
+ l: str # locked # noqa: E741
712
+
713
+ def parse_to_balance(self) -> Balance:
714
+ return Balance(
715
+ asset=self.a,
716
+ free=Decimal(self.f),
717
+ locked=Decimal(self.l),
718
+ )
719
+
720
+ def pm_parse_to_balance(self) -> Balance:
721
+ return Balance(
722
+ asset=f"{self.a}.SPOT",
723
+ free=Decimal(self.f),
724
+ locked=Decimal(self.l),
725
+ )
726
+
727
+
728
+ class _BinanceSpotUpdateMsg(msgspec.Struct, kw_only=True):
729
+ e: BinanceUserDataStreamWsEventType # event type
730
+ E: int # event time
731
+ u: int # Time of last account update
732
+ B: list[BinanceSpotBalanceData] # balance array of the account
733
+
734
+ def parse_to_balances(self) -> List[Balance]:
735
+ return [balance.parse_to_balance() for balance in self.B]
736
+
737
+ def pm_parse_to_balances(self) -> List[Balance]:
738
+ return [balance.pm_parse_to_balance() for balance in self.B]
739
+
740
+
741
+ class BinanceSpotUpdateMsg(msgspec.Struct, kw_only=True):
742
+ event: _BinanceSpotUpdateMsg
743
+
744
+
745
+ class BinanceResponseKline(msgspec.Struct, array_like=True):
746
+ """
747
+ [
748
+ 1499040000000, // Kline open time
749
+ "0.01634790", // Open price
750
+ "0.80000000", // High price
751
+ "0.01575800", // Low price
752
+ "0.01577100", // Close price
753
+ "148976.11427815", // Volume
754
+ 1499644799999, // Kline Close time
755
+ "2434.19055334", // Quote asset volume
756
+ 308, // Number of trades
757
+ "1756.87402397", // Taker buy base asset volume
758
+ "28.46694368", // Taker buy quote asset volume
759
+ "0" // Unused field, ignore.
760
+ ]
761
+ """
762
+
763
+ open_time: int
764
+ open: str
765
+ high: str
766
+ low: str
767
+ close: str
768
+ volume: str
769
+ close_time: int
770
+ asset_volume: str
771
+ trades_count: int
772
+ taker_base_volume: str
773
+ taker_quote_volume: str
774
+ ignore: str
775
+
776
+
777
+ class BinanceIndexResponseKline(msgspec.Struct, array_like=True):
778
+ """
779
+ 1591256400000, // Open time
780
+ "9653.69440000", // Open
781
+ "9653.69640000", // High
782
+ "9651.38600000", // Low
783
+ "9651.55200000", // Close (or latest price)
784
+ "0 ", // Ignore
785
+ 1591256459999, // Close time
786
+ "0", // Ignore
787
+ 60, // Ignore
788
+ "0", // Ignore
789
+ "0", // Ignore
790
+ "0" // Ignore
791
+ """
792
+
793
+ open_time: int
794
+ open: str
795
+ high: str
796
+ low: str
797
+ close: str
798
+ ignore_1: str
799
+ close_time: int
800
+ ignore_2: str
801
+ ignore_3: int
802
+ ignore_4: str
803
+ ignore_5: str
804
+ ignore_6: str
805
+
806
+
807
+ class BinanceSpotOrderBookMsg(msgspec.Struct):
808
+ """
809
+ WebSocket message for 'Binance Spot/Margin' Partial Book Depth Streams.
810
+ """
811
+
812
+ stream: str
813
+ data: "BinanceSpotOrderBookData"
814
+
815
+
816
+ class BinanceSpotOrderBookData(msgspec.Struct):
817
+ """
818
+ Websocket message 'inner struct' for 'Binance Spot/Margin Partial Book Depth
819
+ Streams.'.
820
+ """
821
+
822
+ lastUpdateId: int
823
+ bids: list["BinanceOrderBookDelta"]
824
+ asks: list["BinanceOrderBookDelta"]
825
+
826
+
827
+ class BinanceOrderBookDelta(msgspec.Struct, array_like=True):
828
+ """
829
+ Schema of single ask/bid delta.
830
+ """
831
+
832
+ price: str
833
+ size: str
834
+
835
+ def parse_to_book_order_data(self) -> BookOrderData:
836
+ return BookOrderData(
837
+ price=float(self.price),
838
+ size=float(self.size),
839
+ )
840
+
841
+
842
+ class BinanceFuturesOrderBookMsg(msgspec.Struct, frozen=True):
843
+ """
844
+ WebSocket message from Binance Partial & Diff.
845
+
846
+ Book Depth Streams.
847
+
848
+ """
849
+
850
+ stream: str
851
+ data: "BinanceFuturesOrderBookData"
852
+
853
+
854
+ class BinanceFuturesOrderBookData(msgspec.Struct, frozen=True):
855
+ """
856
+ WebSocket message 'inner struct' for Binance Partial & Diff.
857
+
858
+ Book Depth Streams.
859
+
860
+ """
861
+
862
+ e: str # Event type
863
+ E: int # Event time
864
+ s: str # Symbol
865
+ U: int # First update ID in event
866
+ u: int # Final update ID in event
867
+ b: list[BinanceOrderBookDelta] # Bids to be updated
868
+ a: list[BinanceOrderBookDelta] # Asks to be updated
869
+
870
+ T: int | None = None # FUTURES only, transaction time
871
+ pu: int | None = None # FUTURES only, previous final update ID
872
+ ps: str | None = None # COIN-M FUTURES only, pair
873
+
874
+
875
+ class BinanceCancelAllOrdersResponse(msgspec.Struct, frozen=True):
876
+ code: int
877
+ msg: str
878
+
879
+
880
+ class BinanceFundingRateResponse(msgspec.Struct, frozen=True):
881
+ symbol: str
882
+ fundingRate: str
883
+ fundingTime: int
884
+ markPrice: str | None = None
885
+
886
+
887
+ class BinanceBatchOrderResponse(msgspec.Struct, frozen=True, omit_defaults=True):
888
+ clientOrderId: str | None = None
889
+ cumQty: str | None = None
890
+ executedQty: str | None = None
891
+ orderId: int | None = None
892
+ avgPrice: str | None = None
893
+ origQty: str | None = None
894
+ price: str | None = None
895
+ reduceOnly: bool | None = None
896
+ side: BinanceOrderSide | None = None
897
+ positionSide: BinancePositionSide | None = None
898
+ status: BinanceOrderStatus | None = None
899
+ stopPrice: str | None = None
900
+ closePosition: bool | None = None
901
+ symbol: str | None = None
902
+ timeInForce: BinanceTimeInForce | None = None
903
+ type: BinanceOrderType | None = None
904
+ origType: BinanceOrderType | None = None
905
+ updateTime: int | None = None
906
+ priceProtect: bool | None = None
907
+ # USD-M specific fields
908
+ cumQuote: str | None = None
909
+ goodTillDate: int | None = None
910
+ # Coin-M specific fields
911
+ cumBase: str | None = None
912
+ pair: str | None = None
913
+ # Optional fields for both
914
+ activatePrice: str | None = None
915
+ priceRate: str | None = None
916
+ workingType: BinanceFuturesWorkingType | None = None
917
+ priceMatch: BinancePriceMatch | None = None
918
+ selfTradePreventionMode: str | None = None
919
+ code: int | None = None
920
+ msg: str | None = None
921
+
922
+
923
+ ################################################################################
924
+ # GET /fapi/v1/ticker/24hr and GET /dapi/v1/ticker/24hr
925
+ ################################################################################
926
+
927
+
928
+ class BinanceFuture24hrTicker(msgspec.Struct):
929
+ """
930
+ 24hr ticker data structure for Binance Futures (FAPI and DAPI).
931
+ Supports both USD-M and Coin-M futures.
932
+ """
933
+
934
+ symbol: str # Symbol name
935
+ priceChange: str # Price change
936
+ priceChangePercent: str # Price change percentage
937
+ weightedAvgPrice: str # Weighted average price
938
+ lastPrice: str # Last price
939
+ lastQty: str # Last quantity
940
+ openPrice: str # Open price
941
+ highPrice: str # High price
942
+ lowPrice: str # Low price
943
+ volume: str # Volume
944
+ openTime: int # Open time
945
+ closeTime: int # Close time
946
+ firstId: int # First trade ID
947
+ lastId: int # Last trade ID
948
+ count: int # Trade count
949
+
950
+ # FAPI specific fields
951
+ quoteVolume: str | None = None # Quote volume (FAPI only)
952
+
953
+ # DAPI specific fields
954
+ pair: str | None = None # Pair name (DAPI only)
955
+ baseVolume: str | None = None # Base volume (DAPI only)
956
+
957
+
958
+ class BinanceSpot24hrTicker(msgspec.Struct):
959
+ """
960
+ 24hr ticker data structure for Binance Spot.
961
+ Supports both FULL and MINI response types.
962
+ """
963
+
964
+ symbol: str # Symbol name
965
+ openPrice: str # Opening price
966
+ highPrice: str # Highest price
967
+ lowPrice: str # Lowest price
968
+ lastPrice: str # Last price
969
+ volume: str # Total trade volume (base asset)
970
+ quoteVolume: str # Total trade volume (quote asset)
971
+ openTime: int # Start of ticker interval
972
+ closeTime: int # End of ticker interval
973
+ firstId: int # First trade ID
974
+ lastId: int # Last trade ID
975
+ count: int # Total trade count
976
+
977
+ # FULL response additional fields
978
+ priceChange: str | None = None # Price change
979
+ priceChangePercent: str | None = None # Price change percentage
980
+ weightedAvgPrice: str | None = None # Weighted average price
981
+ prevClosePrice: str | None = None # Previous close price
982
+ lastQty: str | None = None # Last quantity
983
+ bidPrice: str | None = None # Best bid price
984
+ bidQty: str | None = None # Best bid quantity
985
+ askPrice: str | None = None # Best ask price
986
+ askQty: str | None = None # Best ask quantity
987
+
988
+
989
+ class BinanceWsOrderResponseResult(msgspec.Struct, frozen=True):
990
+ orderId: int
991
+ symbol: str
992
+ clientOrderId: str
993
+
994
+
995
+ class BinanceWsOrderResponseError(msgspec.Struct, frozen=True):
996
+ code: int
997
+ msg: str
998
+
999
+ @property
1000
+ def format_str(self) -> str:
1001
+ return f"code={self.code} error={self.msg}"
1002
+
1003
+
1004
+ class BinanceWsOrderResponse(msgspec.Struct, frozen=True):
1005
+ id: str
1006
+ status: int
1007
+ result: BinanceWsOrderResponseResult | None = None
1008
+ error: BinanceWsOrderResponseError | None = None
1009
+
1010
+ @property
1011
+ def is_success(self) -> bool:
1012
+ return self.status == 200
1013
+
1014
+ @property
1015
+ def is_failed(self) -> bool:
1016
+ return self.status != 200
1017
+
1018
+
1019
+ class BinanceDepthSnapshotData(msgspec.Struct):
1020
+ lastUpdateId: int
1021
+ bids: list[BinanceOrderBookDelta]
1022
+ asks: list[BinanceOrderBookDelta]
1023
+
1024
+
1025
+ class BinanceOrderBook:
1026
+ """Local order book state manager for Binance full diff depth stream."""
1027
+
1028
+ def __init__(self):
1029
+ self.bids: Dict[float, float] = {}
1030
+ self.asks: Dict[float, float] = {}
1031
+ self.last_update_id: int = 0
1032
+ self.ready: bool = False
1033
+ self.buffer: list = []
1034
+
1035
+ def apply_snapshot(self, snapshot: BinanceDepthSnapshotData) -> None:
1036
+ self.bids = {float(d.price): float(d.size) for d in snapshot.bids}
1037
+ self.asks = {float(d.price): float(d.size) for d in snapshot.asks}
1038
+ self.last_update_id = snapshot.lastUpdateId
1039
+
1040
+ def apply_delta(self, data: "BinanceFuturesOrderBookData") -> None:
1041
+ for b in data.b:
1042
+ price = float(b.price)
1043
+ size = float(b.size)
1044
+ if size == 0.0:
1045
+ self.bids.pop(price, None)
1046
+ else:
1047
+ self.bids[price] = size
1048
+ for a in data.a:
1049
+ price = float(a.price)
1050
+ size = float(a.size)
1051
+ if size == 0.0:
1052
+ self.asks.pop(price, None)
1053
+ else:
1054
+ self.asks[price] = size
1055
+ self.last_update_id = data.u
1056
+
1057
+ def get_orderbook(self) -> dict:
1058
+ bids = sorted(self.bids.items(), reverse=True)
1059
+ asks = sorted(self.asks.items())
1060
+ return {
1061
+ "bids": [BookOrderData(price=p, size=s) for p, s in bids],
1062
+ "asks": [BookOrderData(price=p, size=s) for p, s in asks],
1063
+ }