quantplay 2.0.164__tar.gz → 2.0.166__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 (70) hide show
  1. {quantplay-2.0.164 → quantplay-2.0.166}/PKG-INFO +1 -1
  2. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/broker_factory.py +2 -1
  3. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/kotak.py +40 -40
  4. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/noren.py +6 -3
  5. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/shoonya.py +1 -1
  6. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay.egg-info/PKG-INFO +1 -1
  7. {quantplay-2.0.164 → quantplay-2.0.166}/setup.py +1 -1
  8. {quantplay-2.0.164 → quantplay-2.0.166}/README.md +0 -0
  9. {quantplay-2.0.164 → quantplay-2.0.166}/pyproject.toml +0 -0
  10. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/__init__.py +0 -0
  11. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/__init__.py +0 -0
  12. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/aliceblue.py +0 -0
  13. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/angelone.py +0 -0
  14. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/auto_login/__init__.py +0 -0
  15. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/auto_login/aliceblue.py +0 -0
  16. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/breeze/__init__.py +0 -0
  17. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/breeze/breeze_utils.py +0 -0
  18. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/dhan.py +0 -0
  19. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/finvasia_utils/__init__.py +0 -0
  20. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
  21. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/five_paisa.py +0 -0
  22. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/flattrade.py +0 -0
  23. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/ft_utils/__init__.py +0 -0
  24. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  25. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/ft_utils/ft_noren.py +0 -0
  26. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/generics/__init__.py +0 -0
  27. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/generics/broker.py +0 -0
  28. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/icici_direct.py +0 -0
  29. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/iifl_xts.py +0 -0
  30. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/jainam_xts.py +0 -0
  31. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/kite_utils.py +0 -0
  32. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/motilal.py +0 -0
  33. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/uplink/__init__.py +0 -0
  34. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/uplink/uplink_utils.py +0 -0
  35. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/upstox.py +0 -0
  36. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/xts.py +0 -0
  37. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/xts_utils/Connect.py +0 -0
  38. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/xts_utils/Exception.py +0 -0
  39. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
  40. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/xts_utils/__init__.py +0 -0
  41. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/broker/zerodha.py +0 -0
  42. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/exception/__init__.py +0 -0
  43. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/exception/exceptions.py +0 -0
  44. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/model/__init__.py +0 -0
  45. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/model/broker.py +0 -0
  46. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/model/broker_response.py +0 -0
  47. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/model/generics.py +0 -0
  48. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/model/instrument_data.py +0 -0
  49. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/model/order_event.py +0 -0
  50. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/py.typed +0 -0
  51. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/utils/__init__.py +0 -0
  52. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/utils/caching.py +0 -0
  53. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/utils/constant.py +0 -0
  54. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/utils/exchange.py +0 -0
  55. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/utils/number_utils.py +0 -0
  56. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/utils/pickle_utils.py +0 -0
  57. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/utils/selenium_utils.py +0 -0
  58. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/wrapper/__init__.py +0 -0
  59. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/wrapper/aws/__init__.py +0 -0
  60. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay/wrapper/aws/s3.py +0 -0
  61. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay.egg-info/SOURCES.txt +0 -0
  62. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay.egg-info/dependency_links.txt +0 -0
  63. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay.egg-info/requires.txt +0 -0
  64. {quantplay-2.0.164 → quantplay-2.0.166}/quantplay.egg-info/top_level.txt +0 -0
  65. {quantplay-2.0.164 → quantplay-2.0.166}/setup.cfg +0 -0
  66. {quantplay-2.0.164 → quantplay-2.0.166}/tests/__init__.py +0 -0
  67. {quantplay-2.0.164 → quantplay-2.0.166}/tests/conftest.py +0 -0
  68. {quantplay-2.0.164 → quantplay-2.0.166}/tests/wrapper/__init__.py +0 -0
  69. {quantplay-2.0.164 → quantplay-2.0.166}/tests/wrapper/aws/__init__.py +0 -0
  70. {quantplay-2.0.164 → quantplay-2.0.166}/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.164
3
+ Version: 2.0.166
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -188,7 +188,7 @@ class BrokerFactory:
188
188
  consumer_secret=broker_data["consumer_secret"],
189
189
  mobilenumber=broker_data["mobilenumber"],
190
190
  password=broker_data["password"],
191
- mpin=broker_data["mpin"],
191
+ otp=broker_data.get("otp"),
192
192
  load_instrument=False,
193
193
  )
194
194
 
@@ -387,6 +387,7 @@ class BrokerFactory:
387
387
  elif broker == Broker.KOTAK:
388
388
  broker_client = Kotak(
389
389
  configuration=broker_data["configuration"],
390
+ otp=broker_data.get("otp"),
390
391
  load_instrument=load_instrument,
391
392
  )
392
393
  elif broker == Broker.ZERODHA:
@@ -7,6 +7,7 @@ from urllib.parse import urlencode
7
7
  import polars as pl
8
8
  import requests
9
9
  import urllib
10
+ import jwt
10
11
 
11
12
  from quantplay.broker.generics.broker import Broker
12
13
  from quantplay.model.broker import (
@@ -44,13 +45,13 @@ class Kotak(Broker):
44
45
  consumer_secret: str | None = None,
45
46
  mobilenumber: str | None = None,
46
47
  password: str | None = None,
47
- mpin: str | None = None,
48
+ otp: str | None = None,
48
49
  configuration: dict[str, str] | None = None,
49
50
  load_instrument: bool = True,
50
- ):
51
+ ) -> None:
51
52
  super().__init__()
52
53
 
53
- self.configuration: dict[str, str] = {
54
+ self.configuration: dict[str, str | None] = {
54
55
  "fin_key": "X6Nk8cQhUgGmJ2vBdWw4sfzrz4L5En",
55
56
  }
56
57
 
@@ -60,14 +61,17 @@ class Kotak(Broker):
60
61
  "bearer_token": configuration["bearer_token"],
61
62
  "view_token": configuration["view_token"],
62
63
  "sid": configuration["sid"],
63
- "edit_token": configuration["edit_token"],
64
- "edit_sid": configuration["edit_sid"],
65
- "edit_rid": configuration["edit_rid"],
66
- "serverId": configuration["serverId"],
64
+ "edit_token": configuration.get("edit_token"),
65
+ "edit_sid": configuration.get("edit_sid"),
66
+ "edit_rid": configuration.get("edit_rid"),
67
+ "serverId": configuration.get("serverId"),
67
68
  }
68
69
 
69
- elif consumer_key and consumer_secret and mobilenumber and password and mpin:
70
- self.login(consumer_key, consumer_secret, mobilenumber, password, mpin)
70
+ elif consumer_key and consumer_secret and mobilenumber and password:
71
+ self.login(consumer_key, consumer_secret, mobilenumber, password)
72
+
73
+ if otp:
74
+ self.verify_2fa(otp)
71
75
 
72
76
  if load_instrument:
73
77
  self.load_instrument()
@@ -96,8 +100,7 @@ class Kotak(Broker):
96
100
  consumer_secret: str,
97
101
  mobilenumber: str,
98
102
  password: str,
99
- mpin: str,
100
- ):
103
+ ) -> None:
101
104
  base64_string = str(consumer_key) + ":" + str(consumer_secret)
102
105
  base64_token = base64_string.encode("ascii")
103
106
 
@@ -132,7 +135,29 @@ class Kotak(Broker):
132
135
  self.configuration["view_token"] = view_token.get("data").get("token")
133
136
  self.configuration["sid"] = view_token.get("data").get("sid")
134
137
 
135
- view_token_resp = requests.post(
138
+ decode_jwt = jwt.decode( # type: ignore
139
+ self.configuration["view_token"], options={"verify_signature": False}
140
+ )
141
+ userid = decode_jwt.get("sub")
142
+ self.kotakUserId = userid
143
+
144
+ generate_otp_resp = requests.post(
145
+ url=f"{PROD_BASE_URL}login/1.0/login/otp/generate",
146
+ headers={"Authorization": "Bearer " + self.configuration["bearer_token"]},
147
+ data=json.dumps({"userId": userid, "sendEmail": True, "isWhitelisted": True}),
148
+ )
149
+
150
+ _generate_otp = json.loads(generate_otp_resp.text)
151
+
152
+ def verify_2fa(self, otp: str) -> None:
153
+ if (
154
+ self.configuration["bearer_token"] is None
155
+ or self.configuration["sid"] is None
156
+ or self.configuration["view_token"] is None
157
+ ):
158
+ raise InvalidArgumentException("Missing Params")
159
+
160
+ login_resp = requests.post(
136
161
  url=f"{PROD_BASE_URL}login/1.0/login/v2/validate",
137
162
  headers={
138
163
  "Authorization": "Bearer " + self.configuration["bearer_token"],
@@ -140,14 +165,9 @@ class Kotak(Broker):
140
165
  "Auth": self.configuration["view_token"],
141
166
  "Content-Type": "application/json",
142
167
  },
143
- data=json.dumps({"mobileNumber": mobilenumber, "password": password}),
168
+ data=json.dumps({"userId": self.kotakUserId, "otp": otp}),
144
169
  )
145
170
 
146
- login_resp = requests.post(
147
- url=f"{PROD_BASE_URL}login/1.0/login/v2/validate",
148
- headers={"Authorization": "Bearer " + self.configuration["bearer_token"]},
149
- data=json.dumps({"mobileNumber": mobilenumber, "mpin": mpin}),
150
- )
151
171
  edit_token_resp = json.loads(login_resp.text)
152
172
 
153
173
  if "error" not in edit_token_resp:
@@ -157,27 +177,7 @@ class Kotak(Broker):
157
177
  self.configuration["serverId"] = edit_token_resp.get("data").get("hsServerId")
158
178
  self.user_id = edit_token_resp.get("data").get("ucc")
159
179
 
160
- # decode_jwt = jwt.decode( # type: ignore
161
- # self.configuration["view_token"], options={"verify_signature": False}
162
- # )
163
- # userid = decode_jwt.get("sub")
164
- # self.kotakUserId = userid
165
-
166
- # generate_otp_resp = requests.post(
167
- # url=f"{PROD_BASE_URL}login/1.0/login/otp/generate",
168
- # headers={"Authorization": "Bearer " + self.configuration["bearer_token"]},
169
- # data=json.dumps({"userId": userid, "sendEmail": True, "isWhitelisted": True}),
170
- # )
171
-
172
- # generate_otp = json.loads(generate_otp_resp.text)
173
-
174
- def get_base64_token(self, consumer_key: str, consumer_secret: str):
175
- """The Base64 Token Generation.
176
- This function will generate the Base64 Token this will be used to generate the Bearer Token.
177
- Return the Token in a String Format
178
- """
179
-
180
- def order_history(self, order_id: str):
180
+ def order_history(self, order_id: str) -> pl.DataFrame:
181
181
  body = {"nOrdNo": order_id}
182
182
  order_history = self.request("order_history", body=body)["data"] # type:ignore
183
183
  return pl.DataFrame(order_history)
@@ -591,7 +591,7 @@ class Kotak(Broker):
591
591
  url = f"{PROD_BASE_URL}{url}"
592
592
 
593
593
  request_headers = {
594
- "Authorization": "Bearer " + self.configuration["bearer_token"],
594
+ "Authorization": f'Bearer {self.configuration["bearer_token"]}',
595
595
  "Sid": self.configuration["edit_sid"],
596
596
  "Auth": self.configuration["edit_token"],
597
597
  "neo-fin-key": self.configuration["fin_key"],
@@ -45,7 +45,7 @@ class Noren(Broker):
45
45
  self,
46
46
  load_instrument: bool = True,
47
47
  order_updates: Queue[OrderUpdateEvent] | None = None,
48
- ):
48
+ ) -> None:
49
49
  super().__init__()
50
50
 
51
51
  self.order_updates = order_updates
@@ -253,7 +253,7 @@ class Noren(Broker):
253
253
  f"[PLACE_ORDER_FAILED] {exception_message}"
254
254
  )
255
255
 
256
- def ltp(self, exchange: ExchangeType, tradingsymbol: str):
256
+ def ltp(self, exchange: ExchangeType, tradingsymbol: str) -> float:
257
257
  tradingsymbol = self.get_symbol(tradingsymbol, exchange)
258
258
 
259
259
  try:
@@ -288,7 +288,7 @@ class Noren(Broker):
288
288
  "lower_circuit": float(data["lc"]),
289
289
  }
290
290
 
291
- def order_history(self, order_id: str):
291
+ def order_history(self, order_id: str) -> dict[str, str | Any]:
292
292
  order_history = self.api.single_order_history(order_id)
293
293
 
294
294
  if order_history is None:
@@ -406,10 +406,12 @@ class Noren(Broker):
406
406
  )
407
407
  .alias("price")
408
408
  )
409
+ print(holdings_df)
409
410
 
410
411
  holdings_df = holdings_df.with_columns(
411
412
  pl.col("tradingsymbol").str.replace("-EQ", "").alias("tradingsymbol")
412
413
  )
414
+ print(holdings_df)
413
415
 
414
416
  holdings_df = holdings_df.with_columns(
415
417
  (pl.col("quantity") * pl.col("price")).alias("value"),
@@ -418,6 +420,7 @@ class Noren(Broker):
418
420
  (pl.col("quantity") * pl.col("price")).alias("current_value"),
419
421
  ((pl.col("price") / pl.col("average_price") - 1) * 100).alias("pct_change"),
420
422
  )
423
+ print(holdings_df)
421
424
 
422
425
  return holdings_df[list(self.holidings_schema.keys())].cast(self.holidings_schema)
423
426
 
@@ -25,7 +25,7 @@ class FinvAsia(Noren):
25
25
  vendor_code: str | None = None,
26
26
  user_token: str | None = None,
27
27
  load_instrument: bool = True,
28
- ):
28
+ ) -> None:
29
29
  super().__init__(order_updates=order_updates, load_instrument=load_instrument)
30
30
  self.api = FA_NorenApi(
31
31
  "https://api.shoonya.com/NorenWClientTP/",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantplay
3
- Version: 2.0.164
3
+ Version: 2.0.166
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.164",
24
+ version="2.0.166",
25
25
  setup_requires=["pytest-runner"],
26
26
  install_requires=requirements,
27
27
  tests_require=[],
File without changes
File without changes
File without changes