quantplay 2.1.128__tar.gz → 2.1.129__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 (90) hide show
  1. {quantplay-2.1.128 → quantplay-2.1.129}/PKG-INFO +1 -1
  2. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/jainam_xts.py +68 -0
  3. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/xts.py +11 -2
  4. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay.egg-info/PKG-INFO +1 -1
  5. {quantplay-2.1.128 → quantplay-2.1.129}/setup.py +1 -1
  6. {quantplay-2.1.128 → quantplay-2.1.129}/README.md +0 -0
  7. {quantplay-2.1.128 → quantplay-2.1.129}/pyproject.toml +0 -0
  8. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/__init__.py +0 -0
  9. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/__init__.py +0 -0
  10. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/aliceblue.py +0 -0
  11. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/aliceblue_utils/__init__.py +0 -0
  12. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/aliceblue_utils/aliceblue_oauth.py +0 -0
  13. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/aliceblue_v2.py +0 -0
  14. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/angelone.py +0 -0
  15. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/angelone_utils/__init__.py +0 -0
  16. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/angelone_utils/angeloneWS.py +0 -0
  17. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/auto_login/__init__.py +0 -0
  18. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/auto_login/aliceblue.py +0 -0
  19. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/breeze/__init__.py +0 -0
  20. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/breeze/breeze_utils.py +0 -0
  21. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/broker_factory.py +0 -0
  22. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/dhan.py +0 -0
  23. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/finvasia_utils/__init__.py +0 -0
  24. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
  25. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/finvasia_utils/finvasia_oauth.py +0 -0
  26. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/five_paisa.py +0 -0
  27. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/flattrade.py +0 -0
  28. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/ft_utils/__init__.py +0 -0
  29. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  30. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/ft_utils/ft_noren.py +0 -0
  31. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/generics/__init__.py +0 -0
  32. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/generics/broker.py +0 -0
  33. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/icici_direct.py +0 -0
  34. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/iifl_xts.py +0 -0
  35. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/kite_utils.py +0 -0
  36. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/kotak.py +0 -0
  37. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/kotak_utils/__init__.py +0 -0
  38. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/kotak_utils/kotak_ws.py +0 -0
  39. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/kotak_utils/kotak_ws_lib.py +0 -0
  40. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/motilal.py +0 -0
  41. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/noren.py +0 -0
  42. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/shoonya.py +0 -0
  43. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/uplink/__init__.py +0 -0
  44. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/uplink/uplink_utils.py +0 -0
  45. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/upstox.py +0 -0
  46. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/xts_utils/Connect.py +0 -0
  47. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/xts_utils/Exception.py +0 -0
  48. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
  49. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/xts_utils/__init__.py +0 -0
  50. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/xts_utils_v2/ConnectV2.py +0 -0
  51. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/xts_utils_v2/InteractiveSocketClientV2.py +0 -0
  52. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/xts_utils_v2/__init__.py +0 -0
  53. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/broker/zerodha.py +0 -0
  54. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/core/__init__.py +0 -0
  55. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/core/strategy.py +0 -0
  56. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/exception/__init__.py +0 -0
  57. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/exception/exceptions.py +0 -0
  58. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/indicator/__init__.py +0 -0
  59. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/indicator/iv.py +0 -0
  60. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/model/__init__.py +0 -0
  61. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/model/broker.py +0 -0
  62. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/model/broker_response.py +0 -0
  63. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/model/generics.py +0 -0
  64. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/model/instrument_data.py +0 -0
  65. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/model/order_event.py +0 -0
  66. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/py.typed +0 -0
  67. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/strategy/__init__.py +0 -0
  68. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/strategy/iv_spike.py +0 -0
  69. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/strategy/obuy.py +0 -0
  70. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/utils/__init__.py +0 -0
  71. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/utils/caching.py +0 -0
  72. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/utils/constant.py +0 -0
  73. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/utils/exchange.py +0 -0
  74. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/utils/number_utils.py +0 -0
  75. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/utils/pickle_utils.py +0 -0
  76. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/utils/selenium_utils.py +0 -0
  77. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/wrapper/__init__.py +0 -0
  78. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/wrapper/aws/__init__.py +0 -0
  79. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/wrapper/aws/s3.py +0 -0
  80. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay/wrapper/redis.py +0 -0
  81. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay.egg-info/SOURCES.txt +0 -0
  82. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay.egg-info/dependency_links.txt +0 -0
  83. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay.egg-info/requires.txt +0 -0
  84. {quantplay-2.1.128 → quantplay-2.1.129}/quantplay.egg-info/top_level.txt +0 -0
  85. {quantplay-2.1.128 → quantplay-2.1.129}/setup.cfg +0 -0
  86. {quantplay-2.1.128 → quantplay-2.1.129}/tests/__init__.py +0 -0
  87. {quantplay-2.1.128 → quantplay-2.1.129}/tests/conftest.py +0 -0
  88. {quantplay-2.1.128 → quantplay-2.1.129}/tests/wrapper/__init__.py +0 -0
  89. {quantplay-2.1.128 → quantplay-2.1.129}/tests/wrapper/aws/__init__.py +0 -0
  90. {quantplay-2.1.128 → quantplay-2.1.129}/tests/wrapper/aws/s3_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quantplay
3
- Version: 2.1.128
3
+ Version: 2.1.129
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -23,6 +23,34 @@ XTS_LOGIN_URL_MAP = {
23
23
  }
24
24
 
25
25
 
26
+ # XTS Type B vs Type C differences
27
+ # =================================
28
+ #
29
+ # TYPE B (smpb.jainam.in:4143)
30
+ # - dealer_login: isInvestorClient=False
31
+ # - self.ClientID is masked to "*****" after login
32
+ # - XTS accepts "*****" as clientID for place_order → orders go through
33
+ # - orders/positions use dealer endpoints (get_dealer_orderbook, etc.)
34
+ # with clientID=None, returning all sub-client orders
35
+ #
36
+ # TYPE C (smpc.jainam.in:14543)
37
+ # - dealer_login: isInvestorClient=False
38
+ # - self.ClientID is set to the DEALER ID from login (e.g. "JSR129A42")
39
+ # - XTS accepts clientID=dealer_id and returns "success" BUT the order
40
+ # is SILENTLY DROPPED — it never appears in any orderbook
41
+ # - get_order_book(clientID=dealer_id) returns "Supplied client not
42
+ # mapped under dealer"
43
+ # - place_order requires the SUB-CLIENT ID (e.g. "JSR129") which is
44
+ # the actual trading account mapped under the dealer
45
+ # - orders/positions work fine because they use dealer endpoints with
46
+ # clientID=None, which returns all sub-client orders
47
+ #
48
+ # FIX: For type C dealers, we discover the sub-client ID by fetching
49
+ # the dealer orderbook after login and extracting the ClientID from
50
+ # the most recent order. This is stored as self.dealer_client_id and
51
+ # used for place_order, modify_order, cancel_order instead of
52
+ # self.ClientID.
53
+ #
26
54
  class Jainam(XTS):
27
55
  def __init__(
28
56
  self,
@@ -38,6 +66,8 @@ class Jainam(XTS):
38
66
  XTS_type: Literal["A", "B", "C"] = "A",
39
67
  proxies: dict[str, str] | None = None,
40
68
  ) -> None:
69
+ self.XTS_type = XTS_type
70
+
41
71
  # XTS type C dealers route through the broker's own infra; an
42
72
  # outbound proxy is unnecessary and just adds latency/failure modes.
43
73
  if XTS_type == "C":
@@ -57,11 +87,49 @@ class Jainam(XTS):
57
87
  proxies=proxies,
58
88
  )
59
89
 
90
+ # Type B: mask to "*****" — XTS accepts it for place_order.
91
+ # Type C: keep the dealer ID for read operations, but discover
92
+ # the sub-client ID for write operations (see _discover_client).
60
93
  if is_dealer and XTS_type != "C":
61
94
  self.ClientID = "*****"
62
95
 
96
+ self.dealer_client_id: str | None = None
97
+ if is_dealer and XTS_type == "C":
98
+ self._discover_sub_client()
99
+
63
100
  self.ORDER_POLLING_INTERVAL = 5
64
101
 
102
+ @property
103
+ def order_client_id(self) -> str:
104
+ """Type C: use sub-client ID. Type B: use ***** (from self.ClientID)."""
105
+ if self.XTS_type == "C" and self.dealer_client_id:
106
+ return self.dealer_client_id
107
+ return self.ClientID
108
+
109
+ def _discover_sub_client(self) -> None:
110
+ """For type C dealers, discover the sub-client ID from the orderbook.
111
+
112
+ XTS type C silently drops orders placed with clientID=<dealer_id>.
113
+ The actual trading client (e.g. "JSR129") is a sub-account mapped
114
+ under the dealer. We find it by fetching the dealer orderbook and
115
+ extracting the ClientID from the most recent order.
116
+ """
117
+ try:
118
+ resp = self.wrapper.get_dealer_orderbook()
119
+ if (
120
+ resp.get("type") == "success"
121
+ and resp.get("result")
122
+ and len(resp["result"]) > 0
123
+ ):
124
+ # Get the most recent order's ClientID
125
+ latest = max(
126
+ resp["result"],
127
+ key=lambda x: x.get("AppOrderID", 0),
128
+ )
129
+ self.dealer_client_id = latest.get("ClientID")
130
+ except Exception:
131
+ pass # No orders yet or API error — fall back to dealer ID
132
+
65
133
  def login(
66
134
  self, api_key: str, api_secret: str, md_api_key: str, md_api_secret: str
67
135
  ) -> None:
@@ -178,6 +178,15 @@ class XTS(Broker):
178
178
 
179
179
  self.initialize_broker_symbol_map()
180
180
 
181
+ @property
182
+ def order_client_id(self) -> str:
183
+ """Client ID for write operations (place_order, modify_order).
184
+
185
+ For most brokers this is self.ClientID. Jainam type C overrides
186
+ this to return the sub-client ID instead of the dealer ID.
187
+ """
188
+ return self.ClientID
189
+
181
190
  def login(self, api_key: str, api_secret: str, md_api_key: str, md_api_secret: str):
182
191
  try:
183
192
  self.wrapper = XTSConnect(
@@ -672,7 +681,7 @@ class XTS(Broker):
672
681
  orderSide=transaction_type,
673
682
  productType=product,
674
683
  orderUniqueIdentifier=tag,
675
- clientID=self.ClientID,
684
+ clientID=self.order_client_id,
676
685
  )
677
686
  Constants.logger.info(f"[XTS_PLACE_ORDER_RESPONSE] {api_response}")
678
687
 
@@ -759,7 +768,7 @@ class XTS(Broker):
759
768
  modifiedProductType=product,
760
769
  modifiedStopPrice=trigger_price,
761
770
  orderUniqueIdentifier=tag,
762
- clientID=self.ClientID,
771
+ clientID=self.order_client_id,
763
772
  )
764
773
 
765
774
  if api_response["type"] == "error":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quantplay
3
- Version: 2.1.128
3
+ Version: 2.1.129
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.1.128",
24
+ version="2.1.129",
25
25
  install_requires=requirements,
26
26
  tests_require=[],
27
27
  packages=find_packages(),
File without changes
File without changes
File without changes