quantplay 2.0.91__tar.gz → 2.0.92__tar.gz

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 (65) hide show
  1. {quantplay-2.0.91 → quantplay-2.0.92}/PKG-INFO +26 -1
  2. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/motilal.py +16 -31
  3. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/noren.py +0 -16
  4. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/xts.py +99 -43
  5. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/xts_utils/Connect.py +266 -408
  6. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/wrapper/aws/s3.py +6 -1
  7. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay.egg-info/PKG-INFO +26 -1
  8. {quantplay-2.0.91 → quantplay-2.0.92}/setup.py +1 -1
  9. {quantplay-2.0.91 → quantplay-2.0.92}/README.md +0 -0
  10. {quantplay-2.0.91 → quantplay-2.0.92}/pyproject.toml +0 -0
  11. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/__init__.py +0 -0
  12. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/__init__.py +0 -0
  13. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/aliceblue.py +0 -0
  14. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/angelone.py +0 -0
  15. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/auto_login/__init__.py +0 -0
  16. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/auto_login/aliceblue.py +0 -0
  17. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/broker_factory.py +0 -0
  18. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/dhan.py +0 -0
  19. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/finvasia_utils/__init__.py +0 -0
  20. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
  21. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/five_paisa.py +0 -0
  22. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/flattrade.py +0 -0
  23. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/ft_utils/__init__.py +0 -0
  24. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  25. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/ft_utils/ft_noren.py +0 -0
  26. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/generics/__init__.py +0 -0
  27. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/generics/broker.py +0 -0
  28. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/iifl_xts.py +0 -0
  29. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/kite_utils.py +0 -0
  30. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/kotak.py +0 -0
  31. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/shoonya.py +0 -0
  32. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/uplink/__init__.py +0 -0
  33. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/uplink/uplink_utils.py +0 -0
  34. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/upstox.py +0 -0
  35. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/xts_utils/Exception.py +0 -0
  36. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
  37. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/xts_utils/__init__.py +0 -0
  38. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/broker/zerodha.py +1 -1
  39. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/exception/__init__.py +0 -0
  40. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/exception/exceptions.py +0 -0
  41. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/model/__init__.py +0 -0
  42. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/model/broker.py +0 -0
  43. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/model/generics.py +0 -0
  44. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/model/instrument_data.py +0 -0
  45. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/model/order_event.py +0 -0
  46. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/py.typed +0 -0
  47. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/utils/__init__.py +0 -0
  48. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/utils/caching.py +0 -0
  49. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/utils/constant.py +0 -0
  50. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/utils/exchange.py +0 -0
  51. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/utils/number_utils.py +0 -0
  52. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/utils/pickle_utils.py +0 -0
  53. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/utils/selenium_utils.py +0 -0
  54. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/wrapper/__init__.py +0 -0
  55. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay/wrapper/aws/__init__.py +0 -0
  56. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay.egg-info/SOURCES.txt +0 -0
  57. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay.egg-info/dependency_links.txt +0 -0
  58. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay.egg-info/requires.txt +0 -0
  59. {quantplay-2.0.91 → quantplay-2.0.92}/quantplay.egg-info/top_level.txt +0 -0
  60. {quantplay-2.0.91 → quantplay-2.0.92}/setup.cfg +0 -0
  61. {quantplay-2.0.91 → quantplay-2.0.92}/tests/__init__.py +0 -0
  62. {quantplay-2.0.91 → quantplay-2.0.92}/tests/conftest.py +0 -0
  63. {quantplay-2.0.91 → quantplay-2.0.92}/tests/wrapper/__init__.py +0 -0
  64. {quantplay-2.0.91 → quantplay-2.0.92}/tests/wrapper/aws/__init__.py +0 -0
  65. {quantplay-2.0.91 → quantplay-2.0.92}/tests/wrapper/aws/s3_test.py +0 -0
@@ -1,11 +1,36 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantplay
3
- Version: 2.0.91
3
+ Version: 2.0.92
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
7
7
  Author-email:
8
8
  License: MIT
9
+ Requires-Dist: setuptools
10
+ Requires-Dist: path
11
+ Requires-Dist: pyotp
12
+ Requires-Dist: retrying
13
+ Requires-Dist: boto3
14
+ Requires-Dist: numpy
15
+ Requires-Dist: websocket-client
16
+ Requires-Dist: smartapi-python
17
+ Requires-Dist: logzero
18
+ Requires-Dist: selenium
19
+ Requires-Dist: requests
20
+ Requires-Dist: pandas
21
+ Requires-Dist: pyarrow
22
+ Requires-Dist: polars
23
+ Requires-Dist: kiteconnect
24
+ Requires-Dist: pya3
25
+ Requires-Dist: py5paisa
26
+ Requires-Dist: upstox-python-sdk
27
+ Requires-Dist: undetected-chromedriver
28
+ Requires-Dist: cachetools
29
+ Requires-Dist: py_vollib
30
+ Requires-Dist: python-engineio
31
+ Requires-Dist: python-socketio
32
+ Requires-Dist: six
33
+ Requires-Dist: dhanhq
9
34
 
10
35
  # Quantplay Alpha playground
11
36
 
@@ -285,53 +285,38 @@ class Motilal(Broker):
285
285
  Constants.logger.info(f"[GET_LTP_RESPONSE] response {response}")
286
286
  return response["data"]["ltp"] / 100.0
287
287
 
288
- def add_existing_order_details(self, order_to_modify: Dict[str, str]):
289
- order_id = order_to_modify["order_id"]
288
+ def modify_price(
289
+ self,
290
+ order_id: str,
291
+ price: float,
292
+ trigger_price: float | None = None,
293
+ order_type: OrderTypeType | None = None,
294
+ ):
290
295
  orders = self.orders()
291
296
  orders = orders.filter(pl.col("order_id") == order_id)
292
297
 
293
298
  if len(orders) != 1:
294
- raise InvalidArgumentException(
295
- f"Invalid modify request, order_id {order_id} not found"
299
+ Constants.logger.error(
300
+ "[ORDER_NOT_FOUND] invalid modify request for {}".format(order_id)
296
301
  )
302
+ return
297
303
 
298
304
  order = orders.to_dicts()[0]
299
305
  order["last_modified_time"] = str(order["last_modified_time"])
300
306
 
301
- if "price" in order_to_modify:
302
- order["price"] = order_to_modify["price"]
303
- if (
304
- "trigger_price" in order_to_modify
305
- and order_to_modify["trigger_price"] is not None # type:ignore
306
- ):
307
- order["trigger_price"] = order_to_modify["trigger_price"]
307
+ order["price"] = price
308
+ if trigger_price is not None:
309
+ order["trigger_price"] = trigger_price
308
310
 
309
- if "order_type" in order_to_modify and order_to_modify["order_type"] == "SL":
311
+ if order["order_type"] == "SL":
310
312
  order["order_type"] = "STOPLOSS"
311
313
 
312
- return order
313
-
314
- def modify_price(
315
- self,
316
- order_id: str,
317
- price: float,
318
- trigger_price: float | None = None,
319
- order_type: OrderTypeType | None = None,
320
- ):
321
- order_to_modify = {
322
- "order_id": order_id,
323
- "price": price,
324
- "trigger_price": trigger_price,
325
- "order_type": order_type,
326
- }
327
-
328
- self.modify_order(order_to_modify) # type: ignore
314
+ print(order)
315
+ self.modify_order(order) # type: ignore
329
316
 
330
317
  # TODO
331
318
  def modify_order(self, order: Any) -> str:
332
319
  order = copy.deepcopy(order) # type:ignore
333
- order = self.add_existing_order_details(order)
334
-
335
320
  data = {
336
321
  "uniqueorderid": order["order_id"],
337
322
  "newordertype": order["order_type"].upper(),
@@ -250,11 +250,6 @@ class Noren(Broker):
250
250
  f"[PLACE_ORDER_FAILED] {exception_message}"
251
251
  )
252
252
 
253
- @retry(
254
- wait_exponential_multiplier=3000,
255
- wait_exponential_max=10000,
256
- stop_max_attempt_number=3,
257
- )
258
253
  def ltp(self, exchange: ExchangeType, tradingsymbol: str):
259
254
  tradingsymbol = self.get_symbol(tradingsymbol, exchange)
260
255
 
@@ -380,11 +375,6 @@ class Noren(Broker):
380
375
 
381
376
  return response
382
377
 
383
- @retry(
384
- wait_exponential_multiplier=3000,
385
- wait_exponential_max=10000,
386
- stop_max_attempt_number=3,
387
- )
388
378
  def holdings(self):
389
379
  holdings = self.invoke_noren_api(self.api.get_holdings)
390
380
  if holdings is None or len(holdings) == 0:
@@ -695,12 +685,6 @@ class Noren(Broker):
695
685
  traceback.print_exc()
696
686
  raise RetryableException("Failed to Receive Data from broker. Retrying Again")
697
687
 
698
- @retry(
699
- wait_exponential_multiplier=1000,
700
- wait_exponential_max=10000,
701
- stop_max_attempt_number=3,
702
- retry_on_exception=retry_exception,
703
- )
704
688
  def margins(self) -> MarginsResponse:
705
689
  api_margins = self.invoke_noren_api(self.api.get_limits)
706
690
 
@@ -12,6 +12,12 @@ from retrying import retry # type: ignore
12
12
 
13
13
  from quantplay.broker.generics.broker import Broker
14
14
  from quantplay.broker.xts_utils.Connect import XTSConnect
15
+ from quantplay.broker.xts_utils.Exception import (
16
+ XTSDataException,
17
+ XTSGeneralException,
18
+ XTSNetworkException,
19
+ XTSTokenException,
20
+ )
15
21
  from quantplay.broker.xts_utils.InteractiveSocketClient import OrderSocket_io
16
22
  from quantplay.exception.exceptions import (
17
23
  BrokerException,
@@ -76,8 +82,11 @@ class XTS(Broker):
76
82
  self.load_instrument()
77
83
 
78
84
  def set_wrapper(self, serialized_wrapper: str, serialized_md_wrapper: str):
79
- self.wrapper = pickle.loads(codecs.decode(serialized_wrapper.encode(), "base64"))
80
- self.md_wrapper = pickle.loads(
85
+ self.wrapper: XTSConnect = pickle.loads(
86
+ codecs.decode(serialized_wrapper.encode(), "base64")
87
+ )
88
+
89
+ self.md_wrapper: XTSConnect = pickle.loads(
81
90
  codecs.decode(serialized_md_wrapper.encode(), "base64")
82
91
  )
83
92
 
@@ -101,29 +110,34 @@ class XTS(Broker):
101
110
 
102
111
  ins_type = instrument["instrument_type"]
103
112
  name = instrument["name"]
113
+
104
114
  if ins_type in ["CE", "PE"]:
105
115
  expiry = datetime.strftime(
106
116
  datetime.strptime(str(instrument["expiry"]), "%Y-%m-%d"),
107
117
  "%d%b%Y",
108
118
  ).upper()
109
119
  strike = str(instrument["strike"]).rstrip("0")
120
+
110
121
  if strike[-1] == ".":
111
122
  strike = strike[:-1]
123
+
112
124
  instrument["broker_symbol"] = f"{name} {expiry} {ins_type} {strike}"
125
+
113
126
  elif ins_type == "FUT":
114
127
  expiry = datetime.strftime(
115
128
  datetime.strptime(str(instrument["expiry"]), "%Y-%m-%d"),
116
129
  "%d%b%Y",
117
130
  ).upper()
118
131
  instrument["broker_symbol"] = f"{name} {expiry}"
132
+
119
133
  else:
120
134
  instrument["broker_symbol"] = tradingsymbol
121
135
 
122
- # TODO: Types
123
136
  self.symbol_data[f"{exchange}:{tradingsymbol}"] = instrument # type: ignore
124
137
 
125
138
  PickleUtils.save_data(self.symbol_data, "xts_instruments")
126
139
  Constants.logger.info("[LOADING_INSTRUMENTS] loading data from server")
140
+
127
141
  self.initialize_broker_symbol_map()
128
142
 
129
143
  def login(self, api_key: str, api_secret: str, md_api_key: str, md_api_secret: str):
@@ -133,48 +147,53 @@ class XTS(Broker):
133
147
  secretKey=api_secret,
134
148
  root=self.root_url,
135
149
  )
136
- xt_core_response = self.wrapper.interactive_login()
150
+ xt_core_response = self.invoke_xts_api(self.wrapper.interactive_login)
151
+
137
152
  self.md_wrapper = XTSConnect(
138
153
  apiKey=md_api_key,
139
154
  secretKey=md_api_secret,
140
155
  root=self.root_url,
141
156
  )
142
- md_response = self.md_wrapper.marketdata_login()
157
+ md_response = self.invoke_xts_api(self.md_wrapper.marketdata_login)
158
+
143
159
  if "type" not in xt_core_response or xt_core_response["type"] != "success":
144
160
  print(f"api login response {xt_core_response}")
145
161
  raise TokenException("Api key credentials are incorrect")
162
+
146
163
  if "type" not in md_response or md_response["type"] != "success":
147
164
  print(f"market data login response {md_response}")
148
165
  raise TokenException("Market data api credentials are invalid")
166
+
149
167
  self.ClientID = xt_core_response["result"]["userID"]
168
+
150
169
  except TokenException:
151
170
  raise
171
+
152
172
  except Exception:
153
173
  raise InvalidArgumentException("Invalid api key/secret")
154
174
 
155
175
  def handle_exception(self, response: Dict[str, Any]):
156
176
  if "data" in response and "description" in response["data"]:
157
177
  data = response["data"]
178
+
158
179
  if "max limit" in data["description"].lower():
159
180
  user_id = self.profile()["user_id"]
160
181
  print("Rate limit problem")
161
182
  raise RetryableException(f"{user_id}: Request limit exceeded")
183
+
162
184
  if (
163
185
  "description" in response
164
186
  and "Authorization not found" in response["description"]
165
187
  ):
166
188
  raise TokenException(response["description"])
189
+
167
190
  if "type" in response and response["type"] == "error":
168
191
  raise Exception(f"[XTS_Error]: {response['description']}")
169
192
 
170
- @retry(
171
- wait_exponential_multiplier=3000,
172
- wait_exponential_max=10000,
173
- stop_max_attempt_number=3,
174
- retry_on_exception=retry_exception,
175
- )
176
193
  def margins(self) -> MarginsResponse:
177
- api_response = self.wrapper.get_balance(clientID=self.ClientID)
194
+ api_response = self.invoke_xts_api(
195
+ self.wrapper.get_balance, clientID=self.ClientID
196
+ )
178
197
  self.handle_exception(api_response)
179
198
 
180
199
  if not api_response:
@@ -194,14 +213,10 @@ class XTS(Broker):
194
213
  "cash": 0,
195
214
  }
196
215
 
197
- @retry(
198
- wait_exponential_multiplier=3000,
199
- wait_exponential_max=10000,
200
- stop_max_attempt_number=3,
201
- retry_on_exception=retry_exception,
202
- )
203
216
  def profile(self) -> UserBrokerProfileResponse:
204
- api_response = self.wrapper.get_profile(self.ClientID)
217
+ api_response = self.invoke_xts_api(
218
+ self.wrapper.get_profile, clientID=self.ClientID
219
+ )
205
220
  self.handle_exception(api_response)
206
221
  api_response = api_response["result"]
207
222
 
@@ -213,14 +228,10 @@ class XTS(Broker):
213
228
 
214
229
  return response
215
230
 
216
- @retry(
217
- wait_exponential_multiplier=3000,
218
- wait_exponential_max=10000,
219
- stop_max_attempt_number=3,
220
- retry_on_exception=retry_exception,
221
- )
222
231
  def orders(self, tag: str | None = None, add_ltp: bool = True) -> pl.DataFrame:
223
- api_response = self.wrapper.get_order_book(self.ClientID)
232
+ api_response = self.invoke_xts_api(
233
+ self.wrapper.get_order_book, clientID=self.ClientID
234
+ )
224
235
  self.handle_exception(api_response)
225
236
 
226
237
  api_response = api_response["result"]
@@ -345,22 +356,13 @@ class XTS(Broker):
345
356
 
346
357
  return orders_df[list(self.orders_schema.keys())].cast(self.orders_schema)
347
358
 
348
- @retry(
349
- wait_exponential_multiplier=3000,
350
- wait_exponential_max=10000,
351
- stop_max_attempt_number=3,
352
- )
353
359
  def holdings(self):
354
360
  return pl.DataFrame(schema=self.holidings_schema)
355
361
 
356
- @retry(
357
- wait_exponential_multiplier=3000,
358
- wait_exponential_max=10000,
359
- stop_max_attempt_number=3,
360
- retry_on_exception=retry_exception,
361
- )
362
362
  def positions(self, drop_cnc: bool = True) -> pl.DataFrame:
363
- api_response = self.wrapper.get_position_daywise(self.ClientID)
363
+ api_response = self.invoke_xts_api(
364
+ self.wrapper.get_position_daywise, clientID=self.ClientID
365
+ )
364
366
  self.handle_exception(api_response)
365
367
 
366
368
  api_response = api_response["result"]["positionList"]
@@ -478,7 +480,9 @@ class XTS(Broker):
478
480
  }
479
481
  for x in symbols
480
482
  ]
481
- api_response = self.md_wrapper.get_quote(
483
+
484
+ api_response = self.invoke_xts_api(
485
+ self.md_wrapper.get_quote,
482
486
  Instruments=instruments,
483
487
  xtsMessageCode=1512,
484
488
  publishFormat="JSON",
@@ -486,6 +490,7 @@ class XTS(Broker):
486
490
 
487
491
  if "type" in api_response and api_response["type"] == "error":
488
492
  raise TokenException(api_response["description"])
493
+
489
494
  api_response = api_response["result"]
490
495
 
491
496
  ltp_json = api_response["listQuotes"]
@@ -541,7 +546,8 @@ class XTS(Broker):
541
546
  "", # TODO
542
547
  )
543
548
 
544
- api_response = self.md_wrapper.get_quote(
549
+ api_response = self.invoke_xts_api(
550
+ self.md_wrapper.get_quote,
545
551
  Instruments=[
546
552
  {
547
553
  "exchangeSegment": exchange_code,
@@ -561,6 +567,7 @@ class XTS(Broker):
561
567
 
562
568
  try:
563
569
  ltp_json = api_response["listQuotes"][0]
570
+
564
571
  except IndexError as e:
565
572
  print(api_response, e)
566
573
  raise BrokerException("Broker Provided Invalid Response")
@@ -593,7 +600,8 @@ class XTS(Broker):
593
600
  if tag is None:
594
601
  tag = ""
595
602
 
596
- api_response = self.wrapper.place_order(
603
+ api_response = self.invoke_xts_api(
604
+ self.wrapper.place_order,
597
605
  exchangeSegment=exchange_name,
598
606
  exchangeInstrumentID=exchange_token,
599
607
  orderType=xts_order_type,
@@ -626,7 +634,8 @@ class XTS(Broker):
626
634
 
627
635
  tag = order_data["tag"]
628
636
 
629
- api_response = self.wrapper.cancel_order(
637
+ api_response = self.invoke_xts_api(
638
+ self.wrapper.cancel_order,
630
639
  appOrderID=int(order_id),
631
640
  clientID=order_data["user_id"],
632
641
  orderUniqueIdentifier=tag,
@@ -678,7 +687,8 @@ class XTS(Broker):
678
687
  time_in_force = "DAY"
679
688
  disclosed_quantity = 0
680
689
 
681
- api_response = self.wrapper.modify_order(
690
+ api_response = self.invoke_xts_api(
691
+ self.wrapper.modify_order,
682
692
  appOrderID=int(order_id),
683
693
  modifiedTimeInForce=time_in_force,
684
694
  modifiedDisclosedQuantity=disclosed_quantity,
@@ -806,3 +816,49 @@ class XTS(Broker):
806
816
  except Exception as e:
807
817
  print(e)
808
818
  Constants.logger.error("[ORDER_UPDATE_PROCESSING_FAILED] {}".format(e))
819
+
820
+ @retry(
821
+ wait_exponential_multiplier=3000,
822
+ wait_exponential_max=10000,
823
+ stop_max_attempt_number=3,
824
+ retry_on_exception=retry_exception,
825
+ )
826
+ def invoke_xts_api(self, fn: Any, *args: Any, **kwargs: Any) -> Dict[str, Any]:
827
+ try:
828
+ response = fn(*args, **kwargs)
829
+
830
+ if "data" in response and "description" in response["data"]:
831
+ data = response["data"]
832
+
833
+ if "max limit" in data["description"].lower():
834
+ user_id = self.profile()["user_id"]
835
+ print("Rate limit problem")
836
+ raise RetryableException(f"{user_id}: Request limit exceeded")
837
+
838
+ if (
839
+ "description" in response
840
+ and "Authorization not found" in response["description"]
841
+ ):
842
+ raise TokenException(response["description"])
843
+
844
+ if "type" in response and response["type"] == "error":
845
+ raise Exception(f"[XTS_Error]: {response['description']}")
846
+
847
+ return response
848
+
849
+ except XTSTokenException as e:
850
+ raise TokenException(str(e))
851
+
852
+ except (TokenException, RetryableException):
853
+ raise
854
+
855
+ except (
856
+ XTSGeneralException,
857
+ XTSDataException,
858
+ XTSNetworkException,
859
+ ) as e:
860
+ raise BrokerException(str(e))
861
+
862
+ except Exception:
863
+ traceback.print_exc()
864
+ raise