quantplay 2.0.85__tar.gz → 2.0.90__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.85 → quantplay-2.0.90}/PKG-INFO +1 -1
  2. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/aliceblue.py +10 -11
  3. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/angelone.py +21 -26
  4. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/dhan.py +14 -9
  5. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/finvasia_utils/fa_noren.py +3 -0
  6. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/five_paisa.py +9 -14
  7. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/ft_utils/ft_noren.py +5 -0
  8. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/generics/broker.py +2 -1
  9. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/kotak.py +9 -4
  10. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/motilal.py +12 -13
  11. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/noren.py +11 -25
  12. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/upstox.py +5 -17
  13. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/xts.py +10 -8
  14. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/zerodha.py +19 -15
  15. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/model/broker.py +7 -0
  16. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay.egg-info/PKG-INFO +1 -1
  17. {quantplay-2.0.85 → quantplay-2.0.90}/setup.py +1 -1
  18. {quantplay-2.0.85 → quantplay-2.0.90}/README.md +0 -0
  19. {quantplay-2.0.85 → quantplay-2.0.90}/pyproject.toml +0 -0
  20. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/__init__.py +0 -0
  21. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/__init__.py +0 -0
  22. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/auto_login/__init__.py +0 -0
  23. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/auto_login/aliceblue.py +0 -0
  24. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/broker_factory.py +0 -0
  25. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/finvasia_utils/__init__.py +0 -0
  26. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/flattrade.py +0 -0
  27. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/ft_utils/__init__.py +0 -0
  28. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  29. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/generics/__init__.py +0 -0
  30. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/iifl_xts.py +0 -0
  31. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/kite_utils.py +0 -0
  32. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/shoonya.py +0 -0
  33. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/uplink/__init__.py +0 -0
  34. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/uplink/uplink_utils.py +0 -0
  35. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/xts_utils/Connect.py +0 -0
  36. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/xts_utils/Exception.py +0 -0
  37. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
  38. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/broker/xts_utils/__init__.py +0 -0
  39. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/exception/__init__.py +0 -0
  40. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/exception/exceptions.py +0 -0
  41. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/model/__init__.py +0 -0
  42. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/model/generics.py +0 -0
  43. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/model/instrument_data.py +0 -0
  44. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/model/order_event.py +0 -0
  45. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/py.typed +0 -0
  46. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/utils/__init__.py +0 -0
  47. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/utils/caching.py +0 -0
  48. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/utils/constant.py +0 -0
  49. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/utils/exchange.py +0 -0
  50. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/utils/number_utils.py +0 -0
  51. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/utils/pickle_utils.py +0 -0
  52. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/utils/selenium_utils.py +0 -0
  53. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/wrapper/__init__.py +0 -0
  54. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/wrapper/aws/__init__.py +0 -0
  55. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay/wrapper/aws/s3.py +0 -0
  56. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay.egg-info/SOURCES.txt +0 -0
  57. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay.egg-info/dependency_links.txt +0 -0
  58. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay.egg-info/requires.txt +0 -0
  59. {quantplay-2.0.85 → quantplay-2.0.90}/quantplay.egg-info/top_level.txt +0 -0
  60. {quantplay-2.0.85 → quantplay-2.0.90}/setup.cfg +0 -0
  61. {quantplay-2.0.85 → quantplay-2.0.90}/tests/__init__.py +0 -0
  62. {quantplay-2.0.85 → quantplay-2.0.90}/tests/conftest.py +0 -0
  63. {quantplay-2.0.85 → quantplay-2.0.90}/tests/wrapper/__init__.py +0 -0
  64. {quantplay-2.0.85 → quantplay-2.0.90}/tests/wrapper/aws/__init__.py +0 -0
  65. {quantplay-2.0.85 → quantplay-2.0.90}/tests/wrapper/aws/s3_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantplay
3
- Version: 2.0.85
3
+ Version: 2.0.90
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -3,7 +3,7 @@ import copy
3
3
  import pickle
4
4
  import traceback
5
5
  from queue import Queue
6
- from typing import Any, Dict, Literal
6
+ from typing import Any, Literal
7
7
 
8
8
  import polars as pl
9
9
  from pya3 import (
@@ -28,7 +28,11 @@ from quantplay.exception.exceptions import (
28
28
  TokenException,
29
29
  retry_exception,
30
30
  )
31
- from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
31
+ from quantplay.model.broker import (
32
+ MarginsResponse,
33
+ ModifyOrderRequest,
34
+ UserBrokerProfileResponse,
35
+ )
32
36
  from quantplay.model.generics import (
33
37
  ExchangeType,
34
38
  OrderTypeType,
@@ -596,29 +600,24 @@ class Aliceblue(Broker):
596
600
 
597
601
  return orders_df[list(self.orders_schema.keys())].cast(self.orders_schema)
598
602
 
599
- def margins(self) -> Dict[str, float]:
603
+ def margins(self) -> MarginsResponse:
600
604
  margins = self.invoke_aliceblue_api(self.alice.get_balance)
601
605
  if margins is None:
602
606
  return {
603
607
  "margin_used": 0.0,
604
608
  "total_balance": 0.0,
605
609
  "margin_available": 0.0,
610
+ "cash": 0,
606
611
  }
607
612
 
608
613
  margins = [a for a in margins if a["segment"] == "ALL"][0]
609
614
 
610
- response = {
615
+ return {
611
616
  "margin_used": float(margins["debits"]),
612
617
  "total_balance": float(margins["credits"]),
613
618
  "margin_available": float(margins["net"]),
619
+ "cash": 0,
614
620
  }
615
- return response
616
-
617
- def account_summary(self):
618
- margins = self.margins()
619
- margins["pnl"] = float(self.positions()["pnl"].sum())
620
-
621
- return margins
622
621
 
623
622
  def invoke_aliceblue_api(self, fn: Any, *args: Any, **kwargs: Any) -> Any:
624
623
  try:
@@ -3,7 +3,7 @@ import copy
3
3
  import json
4
4
  import traceback
5
5
  from queue import Queue
6
- from typing import Any, Dict
6
+ from typing import Any
7
7
 
8
8
  import logzero # type: ignore
9
9
  import polars as pl
@@ -23,7 +23,11 @@ from quantplay.exception.exceptions import (
23
23
  TokenException,
24
24
  retry_exception,
25
25
  )
26
- from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
26
+ from quantplay.model.broker import (
27
+ MarginsResponse,
28
+ ModifyOrderRequest,
29
+ UserBrokerProfileResponse,
30
+ )
27
31
  from quantplay.model.generics import (
28
32
  ExchangeType,
29
33
  OrderTypeType,
@@ -521,22 +525,31 @@ class AngelOne(Broker):
521
525
 
522
526
  return response
523
527
 
524
- def margins(self) -> Dict[str, float]:
528
+ def margins(self) -> MarginsResponse:
525
529
  api_margins = self.invoke_angelone_api(self.wrapper.rmsLimit)
526
530
 
527
531
  if "data" in api_margins and api_margins["data"] is None:
528
532
  if "errorcode" in api_margins and api_margins["errorcode"] == "AB1004":
529
533
  raise TokenException("Angelone server not not responding")
530
534
 
531
- return {"margin_used": 0.0, "margin_available": 0.0, "total_balance": 0.0}
535
+ return {
536
+ "margin_used": 0.0,
537
+ "margin_available": 0.0,
538
+ "total_balance": 0.0,
539
+ "cash": 0,
540
+ }
532
541
 
533
542
  api_margins = api_margins["data"]
534
543
 
535
544
  try:
536
- margins = {
537
- "margin_used": float(api_margins["net"]),
538
- "margin_available": float(api_margins["net"]),
539
- "total_balance": float(api_margins["net"]),
545
+ margin_used = float(api_margins["utiliseddebits"])
546
+ margin_available = float(api_margins["net"])
547
+
548
+ margins: MarginsResponse = {
549
+ "margin_used": margin_used,
550
+ "margin_available": margin_available,
551
+ "cash": float(api_margins["availablecash"]),
552
+ "total_balance": margin_used + margin_available,
540
553
  }
541
554
 
542
555
  return margins
@@ -547,24 +560,6 @@ class AngelOne(Broker):
547
560
  except Exception as e:
548
561
  raise RetryableException(f"Angelone: Failed to fetch margin {e}")
549
562
 
550
- def account_summary(self):
551
- pnl = 0
552
-
553
- margins = self.margins()
554
- positions = self.positions()
555
-
556
- if len(positions) > 0:
557
- pnl = positions["pnl"].sum()
558
-
559
- response = {
560
- "margin_used": margins["margin_used"],
561
- "total_balance": margins["total_balance"],
562
- "margin_available": margins["margin_available"],
563
- "pnl": pnl,
564
- }
565
-
566
- return response
567
-
568
563
  @retry(
569
564
  wait_exponential_multiplier=3000,
570
565
  wait_exponential_max=10000,
@@ -15,6 +15,7 @@ from quantplay.exception.exceptions import (
15
15
  )
16
16
  from quantplay.model.broker import (
17
17
  ExchangeType,
18
+ MarginsResponse,
18
19
  UserBrokerProfileResponse,
19
20
  )
20
21
  from quantplay.model.generics import (
@@ -340,7 +341,7 @@ class Dhan(Broker):
340
341
  .alias("product"),
341
342
  pl.when(pl.col("exchange") == "NSE_FNO")
342
343
  .then(pl.lit("NFO"))
343
- .when(pl.col("exchange") == "BSE_FO")
344
+ .when(pl.col("exchange") == "BSE_FNO")
344
345
  .then(pl.lit("BFO"))
345
346
  .when(pl.col("exchange") == "NSE_EQ")
346
347
  .then(pl.lit("NSE"))
@@ -422,16 +423,20 @@ class Dhan(Broker):
422
423
  traceback.print_exc()
423
424
  raise RetryableException("Failed to Receive Data from broker. Retrying Again")
424
425
 
425
- def margins(self) -> Dict[str, Any]:
426
+ def margins(self) -> MarginsResponse:
426
427
  response = self.invoke_dhan_api(self.dhan.get_fund_limits)
428
+ margin_used = 0
429
+ margin_available = 0
427
430
  if response:
428
- margins = {
429
- "margin_used": float(response["data"]["utilizedAmount"]),
430
- "margin_available": float(response["data"]["availabelBalance"]),
431
- }
432
-
433
- return margins
434
- return {}
431
+ margin_used = float(response["data"]["utilizedAmount"])
432
+ margin_available = float(response["data"]["availabelBalance"])
433
+
434
+ return {
435
+ "margin_available": margin_available,
436
+ "margin_used": margin_used,
437
+ "total_balance": margin_used + margin_available,
438
+ "cash": 0,
439
+ }
435
440
 
436
441
  def profile(self) -> UserBrokerProfileResponse:
437
442
  return {"user_id": self.dhan.client_id}
@@ -13,6 +13,7 @@ import requests
13
13
  import websocket
14
14
 
15
15
  from quantplay.model.generics import ExchangeType, NorenTypes
16
+ from quantplay.exception import TokenException
16
17
 
17
18
  logger = logging.getLogger(__name__)
18
19
 
@@ -294,6 +295,8 @@ class FA_NorenApi:
294
295
 
295
296
  self.__username = userid
296
297
  self.__accountid = userid
298
+ if "stat" in resDict and resDict["stat"].lower() == "not_ok":
299
+ raise TokenException(resDict["emsg"])
297
300
  self.__susertoken = resDict["susertoken"]
298
301
 
299
302
  return resDict
@@ -16,7 +16,11 @@ from quantplay.exception.exceptions import (
16
16
  TokenException,
17
17
  retry_exception,
18
18
  )
19
- from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
19
+ from quantplay.model.broker import (
20
+ MarginsResponse,
21
+ ModifyOrderRequest,
22
+ UserBrokerProfileResponse,
23
+ )
20
24
  from quantplay.model.generics import (
21
25
  ExchangeType,
22
26
  OrderTypeType,
@@ -528,7 +532,7 @@ class FivePaisa(Broker):
528
532
  stop_max_attempt_number=3,
529
533
  retry_on_exception=retry_exception,
530
534
  )
531
- def margins(self) -> Dict[str, float]:
535
+ def margins(self) -> MarginsResponse:
532
536
  margins = self.client.margin()
533
537
 
534
538
  if margins is None:
@@ -536,22 +540,13 @@ class FivePaisa(Broker):
536
540
 
537
541
  margins = margins[0]
538
542
 
539
- margins = {
543
+ return {
540
544
  "margin_used": margins["MarginUtilized"],
541
545
  "margin_available": margins["NetAvailableMargin"],
546
+ "total_balance": margins["NetAvailableMargin"] + margins["MarginUtilized"],
547
+ "cash": 0,
542
548
  }
543
549
 
544
- return margins
545
-
546
- def account_summary(self):
547
- margins = self.margins()
548
- response = {
549
- "margin_used": margins["margin_used"],
550
- "margin_available": margins["margin_available"],
551
- "pnl": float(self.positions()["pnl"].sum()),
552
- }
553
- return response
554
-
555
550
  def cancel_order(self, order_id: str, variety: str | None = None) -> None:
556
551
  raise NotImplementedError("Cancel Order Not Implementd")
557
552
 
@@ -12,6 +12,7 @@ from typing import Any, Callable, Dict, List, Literal, TypedDict
12
12
  import requests
13
13
  import websocket
14
14
 
15
+ from quantplay.exception.exceptions import TokenException
15
16
  from quantplay.model.generics import ExchangeType, NorenTypes
16
17
 
17
18
  logger = logging.getLogger(__name__)
@@ -291,6 +292,10 @@ class FT_NorenApi:
291
292
 
292
293
  self.__username = userid
293
294
  self.__accountid = userid
295
+
296
+ if "stat" in resDict and resDict["stat"].lower() == "not_ok":
297
+ raise TokenException(resDict["emsg"])
298
+
294
299
  self.__susertoken = resDict["susertoken"]
295
300
 
296
301
  return resDict
@@ -28,6 +28,7 @@ from quantplay.exception.exceptions import (
28
28
  )
29
29
  from quantplay.model.broker import (
30
30
  ExchangeType,
31
+ MarginsResponse,
31
32
  ModifyOrderRequest,
32
33
  UserBrokerProfileResponse,
33
34
  )
@@ -1045,7 +1046,7 @@ class Broker(ABC):
1045
1046
  ...
1046
1047
 
1047
1048
  @abstractmethod
1048
- def margins(self) -> Dict[str, float]:
1049
+ def margins(self) -> MarginsResponse:
1049
1050
  """Returns User Margin Summary"""
1050
1051
  ...
1051
1052
 
@@ -8,7 +8,11 @@ import polars as pl
8
8
  import requests
9
9
 
10
10
  from quantplay.broker.generics.broker import Broker
11
- from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
11
+ from quantplay.model.broker import (
12
+ MarginsResponse,
13
+ ModifyOrderRequest,
14
+ UserBrokerProfileResponse,
15
+ )
12
16
  from quantplay.model.generics import (
13
17
  ExchangeType,
14
18
  OrderTypeType,
@@ -179,16 +183,17 @@ class Kotak(Broker):
179
183
  def profile(self) -> UserBrokerProfileResponse:
180
184
  return {"user_id": self.user_id or ""}
181
185
 
182
- def margins(self) -> Dict[str, float]:
186
+ def margins(self) -> MarginsResponse:
183
187
  limits_resp = self.request(
184
188
  "limits", body={"seg": "ALL", "exch": "ALL", "prod": "ALL"}
185
189
  )
186
190
 
187
- margins = {
191
+ return {
188
192
  "margin_used": limits_resp["MarginUsed"],
189
193
  "margin_available": limits_resp["Net"],
194
+ "total_balance": limits_resp["MarginUsed"] + limits_resp["Net"],
195
+ "cash": 0,
190
196
  }
191
- return margins
192
197
 
193
198
  # **
194
199
  # ** POST/PUT Api's
@@ -18,7 +18,7 @@ from quantplay.exception.exceptions import (
18
18
  TokenException,
19
19
  retry_exception,
20
20
  )
21
- from quantplay.model.broker import UserBrokerProfileResponse
21
+ from quantplay.model.broker import MarginsResponse, UserBrokerProfileResponse
22
22
  from quantplay.model.generics import (
23
23
  ExchangeType,
24
24
  OrderTypeType,
@@ -380,19 +380,24 @@ class Motilal(Broker):
380
380
  )
381
381
  Constants.logger.error(exception_message)
382
382
 
383
- def margins(self) -> Dict[str, float]:
383
+ def margins(self) -> MarginsResponse:
384
384
  response = self.__post_request(self.margin_summary_url, {})
385
385
  margin_summary = response["data"]
386
-
387
- margins = {"margin_used": 0.0, "margin_available": 0.0}
386
+ margin_used = 0
387
+ margin_available = 0
388
388
  for margin_particular in margin_summary:
389
389
  if margin_particular["srno"] in [103]:
390
- margins["margin_available"] += margin_particular["amount"]
390
+ margin_available += margin_particular["amount"]
391
391
 
392
392
  if margin_particular["srno"] in [301, 321, 340, 360]:
393
- margins["margin_used"] += margin_particular["amount"]
393
+ margin_used += margin_particular["amount"]
394
394
 
395
- return margins
395
+ return {
396
+ "margin_available": margin_available,
397
+ "margin_used": margin_used,
398
+ "total_balance": margin_used + margin_available,
399
+ "cash": 0,
400
+ }
396
401
 
397
402
  def place_order(
398
403
  self,
@@ -454,12 +459,6 @@ class Motilal(Broker):
454
459
  exception_message = "Order placement failed with error [{}]".format(str(e))
455
460
  print(exception_message)
456
461
 
457
- def account_summary(self):
458
- response = self.margins()
459
- response["pnl"] = float(self.positions()["pnl"].sum()) # type: ignore
460
-
461
- return response
462
-
463
462
  @retry(
464
463
  wait_exponential_multiplier=3000,
465
464
  wait_exponential_max=10000,
@@ -20,6 +20,7 @@ from quantplay.exception.exceptions import (
20
20
  )
21
21
  from quantplay.model.broker import (
22
22
  ExchangeType,
23
+ MarginsResponse,
23
24
  ModifyOrderRequest,
24
25
  UserBrokerProfileResponse,
25
26
  )
@@ -700,7 +701,7 @@ class Noren(Broker):
700
701
  stop_max_attempt_number=3,
701
702
  retry_on_exception=retry_exception,
702
703
  )
703
- def margins(self) -> Dict[str, float]:
704
+ def margins(self) -> MarginsResponse:
704
705
  api_margins = self.invoke_noren_api(self.api.get_limits)
705
706
 
706
707
  if api_margins is None:
@@ -730,16 +731,17 @@ class Noren(Broker):
730
731
  - float(api_margins["margin_used"])
731
732
  )
732
733
 
733
- margins: Dict[str, float] = {}
734
- margins["margin_used"] = api_margins["margin_used"]
735
- margins["margin_available"] = margin_available
736
-
737
734
  try:
738
- margins["cash"] = float(api_margins["cash"])
735
+ cash = float(api_margins["cash"])
739
736
  except Exception:
740
- margins["cash"] = 0
737
+ cash = 0
741
738
 
742
- margins["total_balance"] = float(api_margins["cash"]) + float(holdings_val)
739
+ margins: MarginsResponse = {
740
+ "margin_used": api_margins["margin_used"],
741
+ "margin_available": margin_available,
742
+ "cash": cash,
743
+ "total_balance": float(cash) + float(holdings_val),
744
+ }
743
745
 
744
746
  return margins
745
747
 
@@ -747,20 +749,4 @@ class Noren(Broker):
747
749
  logger.error(f"[NOREN_MARGIN_ERROR] {e}")
748
750
  RetryableException("[NOREN] Failed to fetch account margin")
749
751
 
750
- return {}
751
-
752
- def account_summary(self):
753
- pnl = 0
754
- margins = self.margins()
755
- positions = self.positions()
756
-
757
- if len(positions) > 0:
758
- pnl = positions["pnl"].sum()
759
-
760
- response = {
761
- "margin_used": margins["margin_used"],
762
- "total_balance": margins["total_balance"],
763
- "margin_available": margins["margin_available"],
764
- "pnl": pnl,
765
- }
766
- return response
752
+ return {"margin_available": 0, "margin_used": 0, "total_balance": 0, "cash": 0}
@@ -22,6 +22,7 @@ from quantplay.exception.exceptions import (
22
22
  )
23
23
  from quantplay.model.broker import (
24
24
  ExchangeType,
25
+ MarginsResponse,
25
26
  ModifyOrderRequest,
26
27
  UserBrokerProfileResponse,
27
28
  )
@@ -556,7 +557,7 @@ class Upstox(Broker):
556
557
  stop_max_attempt_number=3,
557
558
  retry_on_exception=retry_exception,
558
559
  )
559
- def margins(self) -> Dict[str, float]:
560
+ def margins(self) -> MarginsResponse:
560
561
  api_instance = upstox_client.UserApi(self.api_client)
561
562
 
562
563
  segment = "SEC" # str | (optional)
@@ -580,25 +581,12 @@ class Upstox(Broker):
580
581
  "Exception when calling UserApi->get_user_fund_margin: %s\n" % e
581
582
  )
582
583
 
583
- margins = {
584
+ return {
584
585
  "margin_used": margin_used,
585
586
  "margin_available": margin_available,
587
+ "total_balance": margin_used + margin_available,
588
+ "cash": 0,
586
589
  }
587
- return margins
588
-
589
- @retry(
590
- wait_exponential_multiplier=3000,
591
- wait_exponential_max=10000,
592
- stop_max_attempt_number=3,
593
- )
594
- def account_summary(self):
595
- margins = self.margins()
596
- response = {
597
- "margin_used": margins["margin_used"],
598
- "margin_available": margins["margin_available"],
599
- "pnl": float(self.positions()["pnl"].sum()),
600
- }
601
- return response
602
590
 
603
591
  def stream_order_data(self):
604
592
  th = threading.Thread(target=self.between_callback, daemon=True)
@@ -22,6 +22,7 @@ from quantplay.exception.exceptions import (
22
22
  )
23
23
  from quantplay.model.broker import (
24
24
  ExchangeType,
25
+ MarginsResponse,
25
26
  ModifyOrderRequest,
26
27
  UserBrokerProfileResponse,
27
28
  )
@@ -172,7 +173,7 @@ class XTS(Broker):
172
173
  stop_max_attempt_number=3,
173
174
  retry_on_exception=retry_exception,
174
175
  )
175
- def margins(self) -> Dict[str, float]:
176
+ def margins(self) -> MarginsResponse:
176
177
  api_response = self.wrapper.get_balance(clientID=self.ClientID)
177
178
  self.handle_exception(api_response)
178
179
 
@@ -180,18 +181,19 @@ class XTS(Broker):
180
181
  return {
181
182
  "margin_used": 0,
182
183
  "margin_available": 0,
184
+ "total_balance": 0,
185
+ "cash": 0,
183
186
  }
184
187
  api_response = api_response["result"]["BalanceList"][0]["limitObject"]
188
+ margin_used = api_response["RMSSubLimits"]["marginUtilized"]
189
+ margin_available = api_response["RMSSubLimits"]["netMarginAvailable"]
185
190
  return {
186
- "margin_used": api_response["RMSSubLimits"]["marginUtilized"],
187
- "margin_available": api_response["RMSSubLimits"]["netMarginAvailable"],
191
+ "margin_used": margin_used,
192
+ "margin_available": margin_available,
193
+ "total_balance": margin_used + margin_available,
194
+ "cash": 0,
188
195
  }
189
196
 
190
- def account_summary(self):
191
- margins = self.margins()
192
- margins["pnl"] = float(self.positions()["pnl"].sum())
193
- return margins
194
-
195
197
  @retry(
196
198
  wait_exponential_multiplier=3000,
197
199
  wait_exponential_max=10000,
@@ -20,6 +20,7 @@ from quantplay.exception.exceptions import (
20
20
  from quantplay.exception.exceptions import TokenException as QuantplayTokenException
21
21
  from quantplay.model.broker import (
22
22
  ExchangeType,
23
+ MarginsResponse,
23
24
  ModifyOrderRequest,
24
25
  UserBrokerProfileResponse,
25
26
  )
@@ -380,7 +381,16 @@ class Zerodha(Broker):
380
381
  [self.get_token(x) for x in holdings_df["instrument_token"].to_list()],
381
382
  )
382
383
  )
384
+ if "collateral_quantity" in holdings_df.columns:
385
+ holdings_df = holdings_df.with_columns(
386
+ pl.col("collateral_quantity").alias("pledged_quantity")
387
+ )
388
+ else:
389
+ holdings_df = holdings_df.with_columns(pl.lit(0).alias("pledged_quantity"))
383
390
 
391
+ holdings_df = holdings_df.with_columns(
392
+ (pl.col("pledged_quantity") + pl.col("quantity")).alias("quantity")
393
+ )
384
394
  holdings_df = holdings_df.with_columns(
385
395
  (pl.col("quantity") * pl.col("price")).alias("value"),
386
396
  pl.lit(0).alias("pledged_quantity"),
@@ -521,15 +531,18 @@ class Zerodha(Broker):
521
531
  stop_max_attempt_number=3,
522
532
  retry_on_exception=retry_exception,
523
533
  )
524
- def margins(self) -> Dict[str, Any]:
534
+ def margins(self) -> MarginsResponse:
525
535
  try:
526
536
  margins = self.wrapper.margins()
527
-
528
- margins = {
529
- "margin_used": float(margins["equity"]["utilised"]["debits"]),
530
- "margin_available": float(margins["equity"]["net"]),
537
+ margin_used = float(margins["equity"]["utilised"]["debits"])
538
+ margin_available = float(margins["equity"]["net"])
539
+ response: MarginsResponse = {
540
+ "margin_used": margin_used,
541
+ "margin_available": margin_available,
542
+ "total_balance": margin_used + margin_available,
543
+ "cash": float(margins["equity"]["available"]["cash"]),
531
544
  }
532
- return margins
545
+ return response
533
546
 
534
547
  except TokenException as e:
535
548
  raise QuantplayTokenException(str(e))
@@ -554,15 +567,6 @@ class Zerodha(Broker):
554
567
  "gst": sum([a["charges"]["gst"]["total"] for a in charges]),
555
568
  }
556
569
 
557
- def account_summary(self):
558
- margins = self.margins()
559
- response = {
560
- "margin_used": margins["margin_used"],
561
- "margin_available": margins["margin_available"],
562
- "pnl": float(self.positions()["pnl"].sum()),
563
- }
564
- return response
565
-
566
570
  @retry(
567
571
  wait_exponential_multiplier=3000,
568
572
  wait_exponential_max=10000,
@@ -30,3 +30,10 @@ class UserBrokerProfileResponse(TypedDict):
30
30
  segments: NotRequired[ExchangeType]
31
31
  exchanges: NotRequired[ExchangeType]
32
32
  email: NotRequired[str]
33
+
34
+
35
+ class MarginsResponse(TypedDict):
36
+ total_balance: float
37
+ margin_available: float
38
+ margin_used: float
39
+ cash: float
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantplay
3
- Version: 2.0.85
3
+ Version: 2.0.90
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -21,7 +21,7 @@ requirements = [
21
21
  setup(
22
22
  name="quantplay",
23
23
  long_description=Path("README.md").read_text(),
24
- version="2.0.85",
24
+ version="2.0.90",
25
25
  setup_requires=["pytest-runner"],
26
26
  install_requires=requirements,
27
27
  tests_require=[],
File without changes
File without changes
File without changes
File without changes
File without changes