wiz-trader 0.35.0__py3-none-any.whl → 0.36.0__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.
wiz_trader/__init__.py CHANGED
@@ -3,6 +3,6 @@
3
3
  from .quotes import QuotesClient
4
4
  from .apis import WizzerClient
5
5
 
6
- __version__ = "0.35.0"
6
+ __version__ = "0.36.0"
7
7
 
8
8
  __all__ = ["QuotesClient", "WizzerClient"]
@@ -28,15 +28,38 @@ class QuotesClient:
28
28
  log_level (str): Logging level. Options: "error", "info", "debug".
29
29
  on_tick (Callable): Callback for tick messages (type='ticks' or no type field).
30
30
  on_stats (Callable): Callback for stats/greeks messages (type='greeks').
31
+ on_order (Callable): Callback for order events (type='order').
32
+ on_trade (Callable): Callback for trade events (type='trade').
33
+ on_position (Callable): Callback for position events (type='position').
34
+ on_holding (Callable): Callback for holding events (type='holding').
31
35
  on_connect (Callable): Callback when connection is established.
32
36
  on_close (Callable): Callback when connection is closed.
33
37
  on_error (Callable): Callback for errors.
34
38
 
35
39
  Message Routing:
36
- - Messages with type='ticks' are routed to on_tick callback
37
- - Messages with type='greeks' are routed to on_stats callback
40
+ - Legacy messages with type='ticks' are routed to on_tick callback
41
+ - Legacy messages with type='greeks' are routed to on_stats callback
42
+ - Event messages with type='order' are routed to on_order callback
43
+ - Event messages with type='trade' are routed to on_trade callback
44
+ - Event messages with type='position' are routed to on_position callback
45
+ - Event messages with type='holding' are routed to on_holding callback
38
46
  - Messages without type field are routed to on_tick for backward compatibility
39
47
  - Messages are silently dropped if the appropriate handler is not registered
48
+
49
+ Message Structure Support:
50
+ - Legacy Format: {type: "ticks", ...data} or {...data} (no type)
51
+ - New Event Format: {type: "position", data: {...actualData}} - automatically normalized
52
+ - All handlers receive flattened message structure with type preserved at root level
53
+
54
+ Event Handler Signature:
55
+ All event handlers follow the same signature: handler(ws: QuotesClient, event_data: dict)
56
+
57
+ Example:
58
+ def on_order_event(ws, order):
59
+ print(f"Order {order['id']}: {order['status']}")
60
+
61
+ client.on_order = on_order_event
62
+ client.connect()
40
63
  """
41
64
 
42
65
  ACTION_SUBSCRIBE = "subscribe"
@@ -89,6 +112,12 @@ class QuotesClient:
89
112
  self.on_connect: Optional[Callable[[Any], None]] = None
90
113
  self.on_close: Optional[Callable[[Any, Optional[int], Optional[str]], None]] = None
91
114
  self.on_error: Optional[Callable[[Any, Exception], None]] = None
115
+
116
+ # Event callbacks for account events
117
+ self.on_order: Optional[Callable[[Any, dict], None]] = None
118
+ self.on_trade: Optional[Callable[[Any, dict], None]] = None
119
+ self.on_position: Optional[Callable[[Any, dict], None]] = None
120
+ self.on_holding: Optional[Callable[[Any, dict], None]] = None
92
121
 
93
122
  logger.debug("Initialized QuotesClient with URL: %s", self.url)
94
123
 
@@ -96,6 +125,40 @@ class QuotesClient:
96
125
  for i in range(0, len(data), chunk_size):
97
126
  yield data[i:i + chunk_size]
98
127
 
128
+ def _normalize_message(self, raw_message: dict) -> dict:
129
+ """
130
+ Normalize message structure to handle both legacy and new formats.
131
+
132
+ Legacy Format (Ticks/Greeks): {type: "ticks", ...data} or {...data} (no type)
133
+ New Format (Events): {type: "position", data: {...actualData}}
134
+
135
+ Returns: Flattened message with type preserved at root level
136
+ """
137
+ try:
138
+ # Check if message has both 'type' and 'data' fields (new format)
139
+ if 'type' in raw_message and 'data' in raw_message:
140
+ # New format: Extract type, merge data into root level
141
+ message_type = raw_message['type']
142
+ data = raw_message['data']
143
+ if isinstance(data, dict):
144
+ # Create flattened message with type preserved
145
+ normalized = {'type': message_type}
146
+ normalized.update(data)
147
+ logger.debug("Normalized new format message: type=%s", message_type)
148
+ return normalized
149
+ else:
150
+ # Data is not a dict, keep original structure
151
+ logger.debug("Data field is not a dict, keeping original structure")
152
+ return raw_message
153
+ else:
154
+ # Legacy format: Use as-is (either has type only or no type)
155
+ logger.debug("Legacy format message detected")
156
+ return raw_message
157
+
158
+ except Exception as e:
159
+ logger.debug("Error normalizing message: %s, using original", e)
160
+ return raw_message
161
+
99
162
  async def _connect_with_backoff(self) -> None:
100
163
  backoff = self._backoff_base
101
164
 
@@ -174,24 +237,67 @@ class QuotesClient:
174
237
  if not chunk:
175
238
  continue
176
239
  try:
177
- data = json.loads(chunk)
240
+ raw_data = json.loads(chunk)
241
+ # Normalize message structure
242
+ data = self._normalize_message(raw_data)
178
243
  # Route based on message type
179
244
  message_type = data.get('type')
180
245
 
181
246
  if message_type == 'greeks':
182
247
  if self.on_stats:
183
- self.on_stats(self, data)
248
+ try:
249
+ self.on_stats(self, data)
250
+ except Exception as e:
251
+ logger.debug("Error in on_stats handler: %s", e)
184
252
  else:
185
253
  logger.debug("Received greeks message but no on_stats handler registered")
186
254
  elif message_type == 'ticks':
187
255
  if self.on_tick:
188
- self.on_tick(self, data)
256
+ try:
257
+ self.on_tick(self, data)
258
+ except Exception as e:
259
+ logger.debug("Error in on_tick handler: %s", e)
189
260
  else:
190
261
  logger.debug("Received ticks message but no on_tick handler registered")
262
+ elif message_type == 'order':
263
+ if self.on_order:
264
+ try:
265
+ self.on_order(self, data)
266
+ except Exception as e:
267
+ logger.debug("Error in on_order handler: %s", e)
268
+ else:
269
+ logger.debug("Received order event but no on_order handler registered")
270
+ elif message_type == 'trade':
271
+ if self.on_trade:
272
+ try:
273
+ self.on_trade(self, data)
274
+ except Exception as e:
275
+ logger.debug("Error in on_trade handler: %s", e)
276
+ else:
277
+ logger.debug("Received trade event but no on_trade handler registered")
278
+ elif message_type == 'position':
279
+ if self.on_position:
280
+ try:
281
+ self.on_position(self, data)
282
+ except Exception as e:
283
+ logger.debug("Error in on_position handler: %s", e)
284
+ else:
285
+ logger.debug("Received position event but no on_position handler registered")
286
+ elif message_type == 'holding':
287
+ if self.on_holding:
288
+ try:
289
+ self.on_holding(self, data)
290
+ except Exception as e:
291
+ logger.debug("Error in on_holding handler: %s", e)
292
+ else:
293
+ logger.debug("Received holding event but no on_holding handler registered")
191
294
  else:
192
295
  # No type field - send to on_tick for backward compatibility
193
296
  if self.on_tick:
194
- self.on_tick(self, data)
297
+ try:
298
+ self.on_tick(self, data)
299
+ except Exception as e:
300
+ logger.debug("Error in on_tick handler: %s", e)
195
301
  else:
196
302
  logger.debug("Received message without type field and no on_tick handler registered")
197
303
  except json.JSONDecodeError as e:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wiz_trader
3
- Version: 0.35.0
3
+ Version: 0.36.0
4
4
  Summary: A Python SDK for connecting to the Wizzer.
5
5
  Home-page: https://bitbucket.org/wizzer-tech/quotes_sdk.git
6
6
  Author: Pawan Wagh
@@ -38,6 +38,7 @@ Dynamic: requires-python
38
38
  - [Callbacks](#callbacks)
39
39
  - [Subscribing to Instruments](#subscribing-to-instruments)
40
40
  - [Unsubscribing from Instruments](#unsubscribing-from-instruments)
41
+ - [Account Events](#account-events)
41
42
  - [Handling WebSocket Connection](#handling-websocket-connection)
42
43
  - [Complete Examples](#quotes-client-examples)
43
44
  5. [Wizzer Client](#wizzer-client)
@@ -253,6 +254,347 @@ ws.unsubscribe(["NSE:RELIANCE:2885"])
253
254
  - Can be called multiple times for different instrument sets
254
255
  - No callback fired for unsubscribed instruments
255
256
 
257
+ ### Account Events
258
+
259
+ The QuotesClient now supports automatic reception of account-related events (orders, trades, positions, holdings) from the quotes server. These events are automatically pushed to SDK users via dedicated callback handlers based on the event type.
260
+
261
+ #### Event Handlers
262
+
263
+ Register event handlers to receive real-time updates for your account activity:
264
+
265
+ ```python
266
+ def on_order(ws, order):
267
+ print(f"Order event: {order}")
268
+
269
+ def on_trade(ws, trade):
270
+ print(f"Trade event: {trade}")
271
+
272
+ def on_position(ws, position):
273
+ print(f"Position event: {position}")
274
+
275
+ def on_holding(ws, holding):
276
+ print(f"Holding event: {holding}")
277
+
278
+ # Register event handlers
279
+ client.on_order = on_order
280
+ client.on_trade = on_trade
281
+ client.on_position = on_position
282
+ client.on_holding = on_holding
283
+ ```
284
+
285
+ #### Key Features
286
+
287
+ - **Automatic Event Reception**: No explicit subscription needed - events are automatically sent based on your JWT token's account ID and strategy ID
288
+ - **Optional Handlers**: Events are silently dropped if no handler is registered - you only receive what you need
289
+ - **Message Normalization**: The SDK automatically handles different message formats and delivers clean, flattened event data to your handlers
290
+ - **Error Resilience**: Handler exceptions are caught and logged without breaking the event flow
291
+ - **Backward Compatible**: Existing tick and Greeks functionality remains unchanged
292
+
293
+ #### Event Data Structure
294
+
295
+ All event handlers receive flattened event data with the event type preserved:
296
+
297
+ ```python
298
+ # Example order event data
299
+ {
300
+ "_id": "order_01k10np7weemkv812nx55bppw5",
301
+ "accountEntityType": "client",
302
+ "accountId": "user_01j9brznsffphvzqn9gzyj1frw",
303
+ "avgPrice": 72.65,
304
+ "broker": "wizzer",
305
+ "brokerOrderId": "dssorder_175344314711184",
306
+ "brokerTimestamp": "2025-07-25T11:32:28.147Z",
307
+ "cancelledQty": 0,
308
+ "completedAt": "2025-07-25T11:32:28.147Z",
309
+ "createdAt": "2025-07-25T11:32:27.722Z",
310
+ "disclosedQty": 0,
311
+ "exchange": "NSE",
312
+ "exchangeOrderId": "dssx_1753443147",
313
+ "exchangeToken": 11184,
314
+ "exchangeUpdateTimestamp": "2025-07-25T11:32:28.147Z",
315
+ "executionType": "regular",
316
+ "filledQty": 1,
317
+ "guid": "t0lVueivgBgcEh2k_BP",
318
+ "instrumentType": "EQLC",
319
+ "isDealer": false,
320
+ "isOrderModified": false,
321
+ "legs": [],
322
+ "marginUsed": 0,
323
+ "meta": {
324
+ "dss": {"orderId": "order_01k10np7weemkv812nx55bppw5"},
325
+ "source": "wizzer.dss",
326
+ "wizzer": {"mode": "paper_trading"}
327
+ },
328
+ "orderType": "MARKET",
329
+ "parentOrderId": "",
330
+ "pendingQty": 1,
331
+ "placedBy": "user_01j9brznsffphvzqn9gzyj1frw",
332
+ "price": 0,
333
+ "product": "CNC",
334
+ "qty": 1,
335
+ "remarks": "",
336
+ "segment": "NSECM",
337
+ "slPrice": 0,
338
+ "slTriggerPrice": 0,
339
+ "sqOffHoldingId": "",
340
+ "sqOffPositionId": "",
341
+ "status": "COMPLETED",
342
+ "stoploss": 0,
343
+ "stoplossOrderId": "",
344
+ "strategy": {
345
+ "id": "stgy_01jtn7t3erf8ss78spqy40k8en",
346
+ "identifier": "S-608377",
347
+ "name": "Test 1122"
348
+ },
349
+ "target": 0,
350
+ "targetOrderId": "",
351
+ "tradingSymbol": "IDFCFIRSTB",
352
+ "transactionType": "BUY",
353
+ "triggerId": "",
354
+ "triggerPrice": 0,
355
+ "updatedAt": "2025-07-25T11:32:28.254Z",
356
+ "userId": "user_01j9brznsffphvzqn9gzyj1frw",
357
+ "validity": "DAY",
358
+ "variety": "REGULAR"
359
+ }
360
+
361
+ # Example trade event data
362
+ {
363
+ "_id": "trade_01k10np8rqef793zr93ctqj0wt",
364
+ "accountId": "user_01j9brznsffphvzqn9gzyj1frw",
365
+ "avgPrice": 72.65,
366
+ "broker": "wizzer",
367
+ "brokerOrderId": "dssorder_175344314711184",
368
+ "createdAt": "2025-07-25T11:32:28.567Z",
369
+ "exchange": "NSE",
370
+ "exchangeOrderId": "dssx_1753443147",
371
+ "exchangeTimestamp": "2025-07-25T11:32:28.147Z",
372
+ "exchangeToken": 11184,
373
+ "isDividend": false,
374
+ "meta": {
375
+ "dss": {"orderId": "order_01k10np7weemkv812nx55bppw5"},
376
+ "source": "wizzer.dss",
377
+ "wizzer": {"mode": "paper_trading"}
378
+ },
379
+ "orderId": "order_01k10np7weemkv812nx55bppw5",
380
+ "orderType": "MARKET",
381
+ "parentOrderId": "",
382
+ "parentTradeId": "",
383
+ "product": "CNC",
384
+ "qty": 1,
385
+ "segment": "NSECM",
386
+ "strategy": {
387
+ "id": "stgy_01jtn7t3erf8ss78spqy40k8en",
388
+ "identifier": "S-608377",
389
+ "name": "Test 1122"
390
+ },
391
+ "tradeId": "dsstrade_50PccSfWvsCg-Cr5dQE",
392
+ "tradingSymbol": "IDFCFIRSTB",
393
+ "transactionType": "BUY",
394
+ "updatedAt": "2025-07-25T11:32:28.567Z",
395
+ "userId": "user_01j9brznsffphvzqn9gzyj1frw"
396
+ }
397
+
398
+ # Example position event data
399
+ {
400
+ "_id": "pos_01k10np8t7e0fs63q52hacbx8m",
401
+ "accountEntityType": "client",
402
+ "accountId": "user_01j9brznsffphvzqn9gzyj1frw",
403
+ "bep": 0,
404
+ "broker": "wizzer",
405
+ "buyAvgPrice": 72.65,
406
+ "buyOrders": ["order_01k10np7weemkv812nx55bppw5"],
407
+ "buyQty": 1,
408
+ "buyTrades": ["trade_01k10np8rqef793zr93ctqj0wt"],
409
+ "buyValue": 72.65,
410
+ "closePrice": 0,
411
+ "createdAt": "2025-07-25T11:32:28.614Z",
412
+ "exchange": "NSE",
413
+ "exchangeToken": 11184,
414
+ "instrumentType": "EQLC",
415
+ "lotSize": 1,
416
+ "meta": {
417
+ "source": "wizzer.dss",
418
+ "wizzer": {"mode": "paper_trading"}
419
+ },
420
+ "netQty": 1,
421
+ "pnlPercentage": 0,
422
+ "product": "CNC",
423
+ "realisedPnlToday": 0,
424
+ "segment": "NSECM",
425
+ "sellAvgPrice": 0,
426
+ "sellOrders": [],
427
+ "sellQty": 0,
428
+ "sellTrades": [],
429
+ "sellValue": 0,
430
+ "slPrice": null,
431
+ "slTriggerPrice": null,
432
+ "status": "open",
433
+ "stoploss": 0,
434
+ "strategy": {
435
+ "id": "stgy_01jtn7t3erf8ss78spqy40k8en",
436
+ "identifier": "S-608377",
437
+ "name": "Test 1122"
438
+ },
439
+ "target": 0,
440
+ "tradingSymbol": "IDFCFIRSTB",
441
+ "unrealisedPnlToday": 0,
442
+ "updatedAt": "2025-07-25T11:32:28.614Z",
443
+ "userId": "user_01j9brznsffphvzqn9gzyj1frw"
444
+ }
445
+
446
+ # Example holding event data
447
+ {
448
+ "_id": "holding_01k10np8t7e0fs63q52hacbx8m",
449
+ "accountEntityType": "client",
450
+ "accountId": "user_01j9brznsffphvzqn9gzyj1frw",
451
+ "bep": 0,
452
+ "broker": "wizzer",
453
+ "buyAvgPrice": 72.65,
454
+ "buyOrders": ["order_01k10np7weemkv812nx55bppw5"],
455
+ "buyQty": 1,
456
+ "buyTrades": ["trade_01k10np8rqef793zr93ctqj0wt"],
457
+ "buyValue": 72.65,
458
+ "closePrice": 0,
459
+ "createdAt": "2025-07-25T11:32:28.614Z",
460
+ "exchange": "NSE",
461
+ "exchangeToken": 11184,
462
+ "instrumentType": "EQLC",
463
+ "lotSize": 1,
464
+ "meta": {
465
+ "source": "wizzer.dss",
466
+ "wizzer": {"mode": "paper_trading"}
467
+ },
468
+ "netQty": 1,
469
+ "pnlPercentage": 0,
470
+ "product": "CNC",
471
+ "realisedPnlToday": 0,
472
+ "segment": "NSECM",
473
+ "sellAvgPrice": 0,
474
+ "sellOrders": [],
475
+ "sellQty": 0,
476
+ "sellTrades": [],
477
+ "sellValue": 0,
478
+ "slPrice": null,
479
+ "slTriggerPrice": null,
480
+ "status": "open",
481
+ "stoploss": 0,
482
+ "strategy": {
483
+ "id": "stgy_01jtn7t3erf8ss78spqy40k8en",
484
+ "identifier": "S-608377",
485
+ "name": "Test 1122"
486
+ },
487
+ "target": 0,
488
+ "tradingSymbol": "IDFCFIRSTB",
489
+ "unrealisedPnlToday": 0,
490
+ "updatedAt": "2025-07-25T11:32:28.614Z",
491
+ "userId": "user_01j9brznsffphvzqn9gzyj1frw"
492
+ }
493
+ ```
494
+
495
+ #### Complete Event Handling Example
496
+
497
+ ```python
498
+ from wiz_trader import QuotesClient
499
+
500
+ # Initialize client
501
+ client = QuotesClient(
502
+ base_url="wss://websocket-url/quotes",
503
+ token="your-jwt-token",
504
+ log_level="info"
505
+ )
506
+
507
+ def on_order(ws, order):
508
+ # React to order status changes
509
+ if order['status'] == ORDER_STATUS_COMPLETED:
510
+ print(f"Order {order['_id']} completed!")
511
+ elif order['status'] == ORDER_STATUS_REJECTED:
512
+ print(f"Order {order['_id']} rejected: {order.get('remarks', 'Unknown')}")
513
+
514
+ def on_trade(ws, trade):
515
+ print(f"Trade executed: {trade['qty']} x {trade['tradingSymbol']} @ {trade['avgPrice']}")
516
+
517
+ def on_position(ws, position):
518
+ print(f"Position update: {position['tradingSymbol']} = {position['netQty']} (PnL: {position.get('unrealisedPnlToday', 0)})")
519
+
520
+ def on_holding(ws, holding):
521
+ print(f"Holding update: {holding['tradingSymbol']} = {holding['netQty']}")
522
+
523
+ def on_connect(ws):
524
+ print("Connected! Ready to receive events.")
525
+ # Also subscribe to some ticks if needed
526
+ ws.subscribe(["NSE:SBIN:3045"], mode="ticks")
527
+
528
+ # Register all handlers
529
+ client.on_order = on_order
530
+ client.on_trade = on_trade
531
+ client.on_position = on_position
532
+ client.on_holding = on_holding
533
+ client.on_connect = on_connect
534
+
535
+ # Connect and receive events
536
+ client.connect()
537
+ ```
538
+
539
+ #### Event-Driven Trading Strategy Example
540
+
541
+ ```python
542
+ class EventDrivenStrategy:
543
+ def __init__(self):
544
+ self.orders = {}
545
+ self.positions = {}
546
+ self.pending_orders = set()
547
+
548
+ def on_order_event(self, ws, order):
549
+ order_id = order['_id']
550
+ self.orders[order_id] = order
551
+
552
+ # Track pending orders
553
+ if order['status'] == ORDER_STATUS_OPEN:
554
+ self.pending_orders.add(order_id)
555
+ elif order_id in self.pending_orders:
556
+ self.pending_orders.remove(order_id)
557
+
558
+ # Log order lifecycle
559
+ print(f"Order {order_id}: {order['status']}")
560
+
561
+ # React to rejections
562
+ if order['status'] == ORDER_STATUS_REJECTED:
563
+ print(f"Order rejected! Reason: {order.get('remarks', 'Unknown')}")
564
+ # Implement retry logic or alternative strategy
565
+
566
+ def on_position_event(self, ws, position):
567
+ symbol = position['tradingSymbol']
568
+ self.positions[symbol] = position
569
+
570
+ # Monitor position changes
571
+ print(f"Position {symbol}: Qty={position['netQty']}, PnL={position.get('unrealisedPnlToday', 0)}")
572
+
573
+ # Implement stop-loss or take-profit logic
574
+ pnl = position.get('unrealisedPnlToday', 0)
575
+ if pnl < -100: # Stop loss at -100
576
+ print(f"Stop loss triggered for {symbol}")
577
+ # Place exit order
578
+ elif pnl > 200: # Take profit at 200
579
+ print(f"Take profit triggered for {symbol}")
580
+ # Place exit order
581
+
582
+ def on_trade_event(self, ws, trade):
583
+ print(f"Trade executed: {trade['qty']} @ {trade['avgPrice']}")
584
+ # Update internal trade log, calculate VWAP, etc.
585
+
586
+ # Initialize strategy
587
+ strategy = EventDrivenStrategy()
588
+
589
+ # Set up client with strategy handlers
590
+ client = QuotesClient(base_url="wss://...", token="...")
591
+ client.on_order = strategy.on_order_event
592
+ client.on_position = strategy.on_position_event
593
+ client.on_trade = strategy.on_trade_event
594
+
595
+ client.connect()
596
+ ```
597
+
256
598
  ### Complete Examples
257
599
 
258
600
  #### Blocking Example
@@ -425,6 +767,7 @@ Available constants:
425
767
  - Transaction types: `TRANSACTION_TYPE_BUY`, `TRANSACTION_TYPE_SELL`
426
768
  - Product types: `PRODUCT_CNC`, `PRODUCT_MIS`, `PRODUCT_NRML`
427
769
  - Order types: `ORDER_TYPE_MARKET`, `ORDER_TYPE_LIMIT`, `ORDER_TYPE_SL`, `ORDER_TYPE_SLM`
770
+ - Order status: `ORDER_STATUS_OPEN`, `ORDER_STATUS_CANCELLED`, `ORDER_STATUS_REJECTED`, `ORDER_STATUS_PENDING`, `ORDER_STATUS_COMPLETED`
428
771
  - Validity types: `VALIDITY_DAY`, `VALIDITY_IOC`, `VALIDITY_GTT`
429
772
  - Variety types: `VARIETY_REGULAR`, `VARIETY_AMO`, `VARIETY_BO`, `VARIETY_CO`
430
773
  - Exchanges: `EXCHANGE_NSE`, `EXCHANGE_BSE`, `EXCHANGE_WZR`
@@ -0,0 +1,9 @@
1
+ wiz_trader/__init__.py,sha256=hOpsoebZsI_XebFP-JQ-CenvIShBGtVDsJhl72ARJxU,183
2
+ wiz_trader/apis/__init__.py,sha256=6sUr1nzmplNdld0zryMrQSt0jHT2GhOiFYgKKVHzk8U,133
3
+ wiz_trader/apis/client.py,sha256=znwlyDIHbaiQuDqxp7pn1NPiiYB99oA74JWt4AiLkBg,80088
4
+ wiz_trader/quotes/__init__.py,sha256=RF9g9CNP6bVWlmCh_ad8krm3-EWOIuVfLp0-H9fAeEM,108
5
+ wiz_trader/quotes/client.py,sha256=cAGaysLCljZilYgX8Sf3V88F6dWlcewJf6TMOpSKb7I,20862
6
+ wiz_trader-0.36.0.dist-info/METADATA,sha256=AYUF296FcogkDFjLk5WDhVeAaGvH1PhO8Gyl1g4aH3Q,155156
7
+ wiz_trader-0.36.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ wiz_trader-0.36.0.dist-info/top_level.txt,sha256=lnYS_g8LlA6ryKYnvY8xIQ6K2K-xzOsd-99AWgnW6VY,11
9
+ wiz_trader-0.36.0.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- wiz_trader/__init__.py,sha256=mvDJsObXpYGcnLwfpMITtZeAouMb_YHNW0Tqse0V0bg,183
2
- wiz_trader/apis/__init__.py,sha256=6sUr1nzmplNdld0zryMrQSt0jHT2GhOiFYgKKVHzk8U,133
3
- wiz_trader/apis/client.py,sha256=znwlyDIHbaiQuDqxp7pn1NPiiYB99oA74JWt4AiLkBg,80088
4
- wiz_trader/quotes/__init__.py,sha256=RF9g9CNP6bVWlmCh_ad8krm3-EWOIuVfLp0-H9fAeEM,108
5
- wiz_trader/quotes/client.py,sha256=aZ5LVlrj0mKfgHgFxERmk2HDZraB6RMaormTOMlqWZc,14915
6
- wiz_trader-0.35.0.dist-info/METADATA,sha256=0aBskcZN4xpphpCtQMO9oAYIjwgboe9nmcpcywuKrXg,144695
7
- wiz_trader-0.35.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- wiz_trader-0.35.0.dist-info/top_level.txt,sha256=lnYS_g8LlA6ryKYnvY8xIQ6K2K-xzOsd-99AWgnW6VY,11
9
- wiz_trader-0.35.0.dist-info/RECORD,,