quantplay 2.0.36__tar.gz → 2.0.38__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 (64) hide show
  1. {quantplay-2.0.36 → quantplay-2.0.38}/PKG-INFO +1 -1
  2. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/aliceblue.py +100 -72
  3. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/angelone.py +54 -53
  4. quantplay-2.0.38/quantplay/broker/dhan.py +477 -0
  5. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/finvasia_utils/fa_noren.py +104 -69
  6. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/five_paisa.py +53 -33
  7. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/ft_utils/ft_noren.py +104 -69
  8. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/generics/broker.py +146 -318
  9. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/iifl_xts.py +2 -2
  10. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/motilal.py +33 -101
  11. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/noren.py +39 -28
  12. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/upstox.py +80 -58
  13. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/xts.py +61 -46
  14. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/xts_utils/Connect.py +96 -94
  15. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/zerodha.py +86 -179
  16. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/model/broker.py +3 -13
  17. quantplay-2.0.38/quantplay/model/generics.py +78 -0
  18. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/model/instrument_data.py +2 -2
  19. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay.egg-info/PKG-INFO +1 -1
  20. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay.egg-info/SOURCES.txt +1 -1
  21. {quantplay-2.0.36 → quantplay-2.0.38}/setup.py +1 -1
  22. quantplay-2.0.36/quantplay/model/generics.py +0 -8
  23. quantplay-2.0.36/quantplay/model/xts.py +0 -7
  24. {quantplay-2.0.36 → quantplay-2.0.38}/README.md +0 -0
  25. {quantplay-2.0.36 → quantplay-2.0.38}/pyproject.toml +0 -0
  26. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/__init__.py +0 -0
  27. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/__init__.py +0 -0
  28. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/auto_login/__init__.py +0 -0
  29. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/auto_login/aliceblue.py +0 -0
  30. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/finvasia_utils/__init__.py +0 -0
  31. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/flattrade.py +0 -0
  32. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/ft_utils/__init__.py +0 -0
  33. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  34. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/generics/__init__.py +0 -0
  35. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/kite_utils.py +0 -0
  36. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/shoonya.py +0 -0
  37. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/uplink/__init__.py +0 -0
  38. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/uplink/uplink_utils.py +0 -0
  39. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/xts_utils/Exception.py +0 -0
  40. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
  41. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/broker/xts_utils/__init__.py +0 -0
  42. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/exception/__init__.py +0 -0
  43. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/exception/exceptions.py +0 -0
  44. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/model/__init__.py +0 -0
  45. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/model/order_event.py +0 -0
  46. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/py.typed +0 -0
  47. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/utils/__init__.py +0 -0
  48. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/utils/constant.py +0 -0
  49. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/utils/exchange.py +0 -0
  50. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/utils/number_utils.py +0 -0
  51. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/utils/pickle_utils.py +0 -0
  52. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/utils/selenium_utils.py +0 -0
  53. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/wrapper/__init__.py +0 -0
  54. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/wrapper/aws/__init__.py +0 -0
  55. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay/wrapper/aws/s3.py +0 -0
  56. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay.egg-info/dependency_links.txt +0 -0
  57. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay.egg-info/requires.txt +0 -0
  58. {quantplay-2.0.36 → quantplay-2.0.38}/quantplay.egg-info/top_level.txt +0 -0
  59. {quantplay-2.0.36 → quantplay-2.0.38}/setup.cfg +0 -0
  60. {quantplay-2.0.36 → quantplay-2.0.38}/tests/__init__.py +0 -0
  61. {quantplay-2.0.36 → quantplay-2.0.38}/tests/conftest.py +0 -0
  62. {quantplay-2.0.36 → quantplay-2.0.38}/tests/wrapper/__init__.py +0 -0
  63. {quantplay-2.0.36 → quantplay-2.0.38}/tests/wrapper/aws/__init__.py +0 -0
  64. {quantplay-2.0.36 → quantplay-2.0.38}/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.36
3
+ Version: 2.0.38
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -3,13 +3,16 @@ import copy
3
3
  import pickle
4
4
  from queue import Queue
5
5
  import traceback
6
- from typing import Any, Callable, Dict, Literal
6
+ from typing import Any, Dict, Literal
7
7
 
8
8
  import polars as pl
9
- from pya3 import Aliceblue as Alice
10
- from pya3 import OrderType as AliceOrderType
11
- from pya3 import ProductType, TransactionType
12
- from retrying import retry
9
+ from pya3 import (
10
+ Aliceblue as Alice,
11
+ OrderType as AliceOrderType,
12
+ TransactionType as AliceTransactionType,
13
+ ProductType as AliceProductType,
14
+ )
15
+ from retrying import retry # type: ignore
13
16
 
14
17
  from quantplay.broker.generics.broker import Broker
15
18
  from quantplay.exception.exceptions import (
@@ -20,7 +23,12 @@ from quantplay.exception.exceptions import (
20
23
  retry_exception,
21
24
  )
22
25
  from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
23
- from quantplay.model.generics import ExchangeType
26
+ from quantplay.model.generics import (
27
+ ExchangeType,
28
+ OrderTypeType,
29
+ ProductType,
30
+ TransactionType,
31
+ )
24
32
  from quantplay.model.order_event import OrderUpdateEvent
25
33
  from quantplay.utils.constant import Constants, OrderType
26
34
  from quantplay.utils.pickle_utils import InstrumentData
@@ -41,7 +49,7 @@ class Aliceblue(Broker):
41
49
  user_id: str | None = None,
42
50
  api_key: str | None = None,
43
51
  order_updates: Queue[OrderUpdateEvent] | None = None,
44
- client=None,
52
+ client: str | None = None,
45
53
  ):
46
54
  super(Aliceblue, self).__init__()
47
55
  self.order_updates = order_updates
@@ -60,37 +68,36 @@ class Aliceblue(Broker):
60
68
  )
61
69
  response = self.alice.get_session_id()
62
70
 
63
- if "sessionID" not in response or response["sessionID"] is None:
71
+ if response.get("sessionID") is None:
64
72
  if "emsg" in response:
65
73
  if response["emsg"].lower() == "invalid input":
66
74
  response["emsg"] = "Invalid broker credentials"
67
75
  raise InvalidArgumentException(response["emsg"])
68
76
  raise InvalidArgumentException(f"Invalid API Key {api_key}")
77
+
69
78
  except (InvalidArgumentException, TokenException):
70
79
  raise
80
+
71
81
  except Exception as e:
72
82
  raise RetryableException(str(e))
83
+
73
84
  self.user_id = self.alice.user_id
74
85
  self.load_instrument()
75
86
 
76
- def set_client(self, serialized_client):
87
+ def set_client(self, serialized_client: str):
77
88
  try:
78
- self.alice = pickle.loads(codecs.decode(serialized_client.encode(), "base64"))
89
+ self.alice: Alice = pickle.loads(
90
+ codecs.decode(serialized_client.encode(), "base64")
91
+ )
79
92
  except Exception:
80
93
  raise TokenException("Session expired")
81
94
 
82
- def set_attributes(self, response):
83
- self.email = response["email"]
84
- self.user_id = response["actid"]
85
- self.full_name = response["uname"]
86
- self.user_token = response["susertoken"]
87
-
88
- def get_quantplay_symbol(self, symbol):
95
+ def get_quantplay_symbol(self, symbol: str):
89
96
  if "-EQ" in symbol:
90
97
  return symbol.replace("-EQ", "")
91
98
  return symbol
92
99
 
93
- def get_symbol(self, symbol, exchange=None):
100
+ def get_symbol(self, symbol: str, exchange: ExchangeType | None = None):
94
101
  if exchange == "NSE":
95
102
  if "-EQ" not in symbol:
96
103
  return f"{symbol}-EQ"
@@ -118,55 +125,63 @@ class Aliceblue(Broker):
118
125
 
119
126
  def get_transaction_type(
120
127
  self,
121
- transaction_type: Literal["BUY", "SELL", "B", "S"],
128
+ transaction_type: Literal[
129
+ "BUY", "SELL", "B", "S", AliceTransactionType.Buy, AliceTransactionType.Sell
130
+ ],
122
131
  ):
123
132
  if (
124
133
  transaction_type == "BUY"
125
- or transaction_type == TransactionType.Buy.value
134
+ or transaction_type == AliceTransactionType.Buy
126
135
  or transaction_type == "B"
127
136
  ):
128
- return TransactionType.Buy
137
+ return AliceTransactionType.Buy
129
138
  elif (
130
139
  transaction_type == "SELL"
131
- or transaction_type == TransactionType.Sell.value
140
+ or transaction_type == AliceTransactionType.Sell
132
141
  or transaction_type == "S"
133
142
  ):
134
- return TransactionType.Sell
143
+ return AliceTransactionType.Sell
135
144
 
136
145
  raise InvalidArgumentException(
137
146
  f"transaction type {transaction_type} not supported for trading"
138
147
  )
139
148
 
140
- def get_order_type(self, order_type):
141
- if order_type == OrderType.market or order_type == AliceOrderType.Market.value:
149
+ def get_order_type(
150
+ self,
151
+ order_type: (
152
+ OrderTypeType
153
+ | Literal[
154
+ AliceOrderType.Market,
155
+ AliceOrderType.StopLossLimit,
156
+ AliceOrderType.StopLossMarket,
157
+ AliceOrderType.Limit,
158
+ ]
159
+ ),
160
+ ):
161
+ if order_type == OrderType.market or order_type == AliceOrderType.Market:
142
162
  return AliceOrderType.Market
143
- elif (
144
- order_type == OrderType.sl or order_type == AliceOrderType.StopLossLimit.value
145
- ):
163
+ elif order_type == OrderType.sl or order_type == AliceOrderType.StopLossLimit:
146
164
  return AliceOrderType.StopLossLimit
147
- elif (
148
- order_type == OrderType.slm
149
- or order_type == AliceOrderType.StopLossMarket.value
150
- ):
165
+ elif order_type == OrderType.slm or order_type == AliceOrderType.StopLossMarket:
151
166
  return AliceOrderType.StopLossMarket
152
- elif order_type == OrderType.limit or order_type == AliceOrderType.Limit.value:
167
+ elif order_type == OrderType.limit or order_type == AliceOrderType.Limit:
153
168
  return AliceOrderType.Limit
154
169
 
155
170
  return order_type
156
171
 
157
- def get_product(self, product):
172
+ def get_product(self, product: ProductType):
158
173
  if product == "NRML":
159
- return ProductType.Normal
174
+ return AliceProductType.Normal
160
175
  elif product == "CNC":
161
- return ProductType.Delivery
176
+ return AliceProductType.Delivery
162
177
  elif product == "MIS":
163
- return ProductType.Intraday
178
+ return AliceProductType.Intraday
164
179
  elif product in [
165
- ProductType.BracketOrder,
166
- ProductType.CoverOrder,
167
- ProductType.Delivery,
168
- ProductType.Normal,
169
- ProductType.Intraday,
180
+ AliceProductType.BracketOrder,
181
+ AliceProductType.CoverOrder,
182
+ AliceProductType.Delivery,
183
+ AliceProductType.Normal,
184
+ AliceProductType.Intraday,
170
185
  ]:
171
186
  return product
172
187
 
@@ -174,15 +189,15 @@ class Aliceblue(Broker):
174
189
 
175
190
  def place_order(
176
191
  self,
177
- tradingsymbol=None,
178
- exchange=None,
179
- quantity=None,
180
- order_type=None,
181
- transaction_type=None,
182
- tag=None,
183
- product=None,
184
- price=None,
185
- trigger_price=None,
192
+ tradingsymbol: str,
193
+ exchange: ExchangeType,
194
+ quantity: int,
195
+ order_type: OrderTypeType,
196
+ transaction_type: TransactionType,
197
+ tag: str | None,
198
+ product: ProductType,
199
+ price: float,
200
+ trigger_price: float | None = None,
186
201
  ):
187
202
  try:
188
203
  if trigger_price == 0:
@@ -190,8 +205,8 @@ class Aliceblue(Broker):
190
205
  if trigger_price is not None:
191
206
  trigger_price = float(trigger_price)
192
207
 
193
- order_type = self.get_order_type(order_type)
194
- product = self.get_product(product)
208
+ aliceblue_order_type = self.get_order_type(order_type)
209
+ aliceblue_product = self.get_product(product)
195
210
  tradingsymbol = self.get_symbol(tradingsymbol)
196
211
 
197
212
  instrument = self.alice.get_instrument_by_symbol(exchange, tradingsymbol)
@@ -199,9 +214,9 @@ class Aliceblue(Broker):
199
214
  response = self.invoke_aliceblue_api(
200
215
  self.alice.place_order,
201
216
  transaction_type=self.get_transaction_type(transaction_type),
202
- product_type=product,
217
+ product_type=aliceblue_product,
203
218
  instrument=instrument,
204
- order_type=order_type,
219
+ order_type=aliceblue_order_type,
205
220
  quantity=quantity,
206
221
  price=float(price),
207
222
  trigger_price=trigger_price,
@@ -237,12 +252,13 @@ class Aliceblue(Broker):
237
252
  wait_exponential_max=10000,
238
253
  stop_max_attempt_number=3,
239
254
  )
240
- def modify_order(self, order_to_modify: ModifyOrderRequest) -> str:
241
- data = copy.deepcopy(order_to_modify)
255
+ def modify_order(self, order: ModifyOrderRequest) -> str:
256
+ data = copy.deepcopy(order)
242
257
  order_id = data["order_id"]
243
258
  try:
244
259
  order_history = self.invoke_aliceblue_api(
245
- self.alice.get_order_history, nextorder=order_id
260
+ self.alice.get_order_history,
261
+ nextorder=order_id,
246
262
  )
247
263
 
248
264
  # TODO: None,str Raise
@@ -254,7 +270,12 @@ class Aliceblue(Broker):
254
270
  order_type = order_history["Prctype"]
255
271
  if "order_type" in data:
256
272
  order_type = data["order_type"]
257
- order_type = self.get_order_type(order_type)
273
+
274
+ aliceblue_order_type = (
275
+ self.get_order_type(order_type)
276
+ if order_type
277
+ else order_history["Prctype"]
278
+ )
258
279
 
259
280
  transaction_type = order_history["Trantype"]
260
281
  if "transaction_type" in data:
@@ -265,17 +286,17 @@ class Aliceblue(Broker):
265
286
  if "trigger_price" in data and data["trigger_price"] is not None:
266
287
  trigger_price = float(data["trigger_price"])
267
288
 
268
- self.alice.modify_order(
289
+ response = self.alice.modify_order(
269
290
  instrument=self.alice.get_instrument_by_token(exchange, token),
270
291
  transaction_type=transaction_type,
271
292
  order_id=order_id,
272
293
  product_type=product_type,
273
- order_type=order_type,
274
- price=float(data["price"]),
275
- trigger_price=trigger_price, # type: ignore
294
+ order_type=aliceblue_order_type,
295
+ price=float(data.get("price", 0)),
296
+ trigger_price=trigger_price,
276
297
  quantity=quantity,
277
298
  )
278
- logger.info("[MODIFY_ORDER_RESPONSE] [{order_id}] response [{response}]")
299
+ logger.info(f"[MODIFY_ORDER_RESPONSE] [{order_id}] response [{response}]")
279
300
  except Exception as e:
280
301
  print(traceback.print_exc())
281
302
  Constants.logger.error(
@@ -283,20 +304,27 @@ class Aliceblue(Broker):
283
304
  )
284
305
  return order_id
285
306
 
286
- def modify_price(self, order_id, price, trigger_price=None, order_type=None):
287
- data = {}
307
+ def modify_price(
308
+ self,
309
+ order_id: str,
310
+ price: float,
311
+ trigger_price: float | None = None,
312
+ order_type: OrderTypeType | None = None,
313
+ ):
314
+ data: ModifyOrderRequest = {
315
+ "order_id": order_id,
316
+ "price": price,
317
+ "order_type": order_type,
318
+ }
288
319
 
289
- data["order_id"] = order_id
290
- data["price"] = price
291
- data["order_type"] = order_type
292
320
  if trigger_price is not None and trigger_price > 0:
293
321
  data["trigger_price"] = trigger_price
294
322
  else:
295
323
  data["trigger_price"] = None
296
324
 
297
- self.modify_order(data) # type: ignore
325
+ self.modify_order(data)
298
326
 
299
- def cancel_order(self, order_id: str, variety=None) -> None:
327
+ def cancel_order(self, order_id: str, variety: str | None = None) -> None:
300
328
  self.invoke_aliceblue_api(self.alice.cancel_order, nestordernmbr=order_id)
301
329
 
302
330
  def profile(self):
@@ -573,7 +601,7 @@ class Aliceblue(Broker):
573
601
 
574
602
  return margins
575
603
 
576
- def invoke_aliceblue_api(self, fn: Callable, *args, **kwargs) -> Any:
604
+ def invoke_aliceblue_api(self, fn: Any, *args: Any, **kwargs: Any) -> Any:
577
605
  try:
578
606
  response = fn(*args, **kwargs)
579
607
 
@@ -1,18 +1,16 @@
1
1
  import binascii
2
- import codecs
3
2
  import copy
4
3
  import json
5
- import pickle
6
4
  from queue import Queue
7
5
  import traceback
8
- from typing import Any, Callable, Dict
6
+ from typing import Any, Dict
9
7
 
10
- from SmartApi.smartExceptions import DataException
8
+ from SmartApi.smartExceptions import DataException # type: ignore
11
9
  import polars as pl
12
10
  import pyotp
13
11
  from requests.exceptions import ConnectionError, ConnectTimeout
14
12
  from retrying import retry # type: ignore
15
- from SmartApi import SmartConnect
13
+ from SmartApi import SmartConnect # type: ignore
16
14
 
17
15
  from quantplay.broker.generics.broker import Broker
18
16
  from quantplay.exception.exceptions import (
@@ -25,6 +23,12 @@ from quantplay.exception.exceptions import (
25
23
  retry_exception,
26
24
  )
27
25
  from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
26
+ from quantplay.model.generics import (
27
+ ExchangeType,
28
+ OrderTypeType,
29
+ ProductType,
30
+ TransactionType,
31
+ )
28
32
  from quantplay.model.order_event import OrderUpdateEvent
29
33
  from quantplay.utils.constant import Constants, OrderType
30
34
  from quantplay.utils.exchange import Market as MarketConstants
@@ -71,7 +75,7 @@ class AngelOne(Broker):
71
75
  raise InvalidArgumentException("TOTP Key is Missing")
72
76
  self.wrapper = SmartConnect(api_key=api_key)
73
77
  response = self.invoke_angelone_api(
74
- self.wrapper.generateSession,
78
+ self.wrapper.generateSession, # type: ignore
75
79
  clientCode=user_id,
76
80
  password=mpin,
77
81
  totp=pyotp.TOTP(totp).now(),
@@ -81,32 +85,27 @@ class AngelOne(Broker):
81
85
  raise InvalidArgumentException(response["message"])
82
86
  raise InvalidArgumentException("Invalid API credentials")
83
87
  token_data = self.invoke_angelone_api(
84
- self.wrapper.generateToken, refresh_token=self.wrapper.refresh_token
88
+ self.wrapper.generateToken, # type: ignore
89
+ refresh_token=self.wrapper.refresh_token, # type: ignore
85
90
  )
86
91
  self.refresh_token = token_data["data"]["refreshToken"]
92
+
87
93
  except InvalidArgumentException:
88
94
  raise
95
+
89
96
  except binascii.Error:
90
97
  raise InvalidArgumentException("Invalid TOTP key provided")
98
+
91
99
  except Exception as e:
92
100
  print(e)
93
101
  raise RetryableException(str(e))
94
102
 
95
103
  self.user_id = user_id
96
- self.api_key = self.wrapper.api_key
104
+ self.api_key = self.wrapper.api_key # type: ignore
97
105
 
98
106
  if load_instrument:
99
107
  self.load_instrument()
100
108
 
101
- def set_wrapper(self, serialized_wrapper):
102
- self.wrapper: SmartConnect = pickle.loads(
103
- codecs.decode(serialized_wrapper.encode(), "base64")
104
- )
105
-
106
- def handle_exception(self, response):
107
- if "errorCode" in response and response["errorCode"] == "AG8001":
108
- raise TokenException(f"{self.user_id}: Invalid Token")
109
-
110
109
  def load_instrument(self, file_name: str | None = None) -> None:
111
110
  try:
112
111
  instrument_data_instance = InstrumentData.get_instance()
@@ -124,7 +123,7 @@ class AngelOne(Broker):
124
123
 
125
124
  self.initialize_broker_symbol_map()
126
125
 
127
- def get_symbol(self, symbol: str, exchange=None):
126
+ def get_symbol(self, symbol: str, exchange: ExchangeType | None = None):
128
127
  if exchange == "NSE":
129
128
  if symbol in ["NIFTY", "BANKNIFTY"]:
130
129
  return symbol
@@ -139,7 +138,7 @@ class AngelOne(Broker):
139
138
  return symbol
140
139
  return self.quantplay_symbol_map[symbol]
141
140
 
142
- def get_order_type(self, order_type):
141
+ def get_order_type(self, order_type: OrderTypeType | None):
143
142
  if order_type == OrderType.sl:
144
143
  return AngelOne.order_sl
145
144
  elif order_type == OrderType.slm:
@@ -147,7 +146,7 @@ class AngelOne(Broker):
147
146
 
148
147
  return order_type
149
148
 
150
- def get_product(self, product):
149
+ def get_product(self, product: ProductType):
151
150
  if product == "NRML":
152
151
  return "CARRYFORWARD"
153
152
  elif product == "CNC":
@@ -159,7 +158,7 @@ class AngelOne(Broker):
159
158
 
160
159
  raise InvalidArgumentException(f"Product {product} not supported for trading")
161
160
 
162
- def ltp(self, exchange, tradingsymbol: str) -> float:
161
+ def ltp(self, exchange: ExchangeType, tradingsymbol: str) -> float:
163
162
  if tradingsymbol in MarketConstants.INDEX_SYMBOL_TO_DERIVATIVE_SYMBOL_MAP:
164
163
  tradingsymbol = MarketConstants.INDEX_SYMBOL_TO_DERIVATIVE_SYMBOL_MAP[
165
164
  tradingsymbol
@@ -171,7 +170,7 @@ class AngelOne(Broker):
171
170
  symboltoken = symbol_data["token"]
172
171
 
173
172
  response = self.invoke_angelone_api(
174
- self.wrapper.ltpData,
173
+ self.wrapper.ltpData, # type: ignore
175
174
  exchange=exchange,
176
175
  tradingsymbol=tradingsymbol,
177
176
  symboltoken=symboltoken,
@@ -181,23 +180,23 @@ class AngelOne(Broker):
181
180
 
182
181
  def place_order(
183
182
  self,
184
- tradingsymbol=None,
185
- exchange=None,
186
- quantity=None,
187
- order_type=None,
188
- transaction_type=None,
189
- tag=None,
190
- product=None,
191
- price=None,
192
- trigger_price=None,
183
+ tradingsymbol: str,
184
+ exchange: ExchangeType,
185
+ quantity: int,
186
+ order_type: OrderTypeType,
187
+ transaction_type: TransactionType,
188
+ tag: str | None,
189
+ product: ProductType,
190
+ price: float,
191
+ trigger_price: float | None = None,
193
192
  ):
194
193
  order = {}
195
194
  try:
196
195
  if trigger_price == 0:
197
196
  trigger_price = None
198
197
 
199
- order_type = self.get_order_type(order_type)
200
- product = self.get_product(product)
198
+ angelone_order_type = self.get_order_type(order_type)
199
+ angelone_product = self.get_product(product)
201
200
  tradingsymbol = self.get_symbol(tradingsymbol, exchange=exchange)
202
201
 
203
202
  variety = "NORMAL"
@@ -211,11 +210,11 @@ class AngelOne(Broker):
211
210
  "transactiontype": transaction_type,
212
211
  "variety": variety,
213
212
  "tradingsymbol": tradingsymbol,
214
- "ordertype": order_type,
213
+ "ordertype": angelone_order_type,
215
214
  "triggerprice": trigger_price,
216
215
  "exchange": exchange,
217
216
  "symboltoken": symbol_token,
218
- "producttype": product,
217
+ "producttype": angelone_product,
219
218
  "price": price,
220
219
  "quantity": quantity,
221
220
  "duration": "DAY",
@@ -223,7 +222,7 @@ class AngelOne(Broker):
223
222
  }
224
223
 
225
224
  Constants.logger.info(f"[PLACING_ORDER] {json.dumps(order)}")
226
- return self.invoke_angelone_api(self.wrapper.placeOrder, orderparams=order)
225
+ return self.invoke_angelone_api(self.wrapper.placeOrder, orderparams=order) # type: ignore
227
226
 
228
227
  except (TimeoutError, ConnectTimeout):
229
228
  Constants.logger.info(f"[ANGELONE_REQUEST_TIMEOUT] {order}")
@@ -233,7 +232,7 @@ class AngelOne(Broker):
233
232
  Constants.logger.error(f"[PLACE_ORDER_FAILED] {e} {order}")
234
233
  raise QuantplayOrderPlacementException(str(e))
235
234
 
236
- def get_variety(self, variety):
235
+ def get_variety(self, variety: str):
237
236
  if variety == "regular":
238
237
  return "NORMAL"
239
238
  return variety
@@ -243,19 +242,19 @@ class AngelOne(Broker):
243
242
  wait_exponential_max=10000,
244
243
  stop_max_attempt_number=3,
245
244
  )
246
- def modify_order(self, order_to_modify: ModifyOrderRequest) -> str:
247
- data = copy.deepcopy(order_to_modify)
245
+ def modify_order(self, order: ModifyOrderRequest) -> str:
246
+ data = copy.deepcopy(order)
248
247
  order_id = str(data["order_id"])
249
248
  try:
250
249
  orders = self.orders()
251
250
  filtered_order = orders.filter(pl.col("order_id") == str(data["order_id"]))
252
- order = filtered_order.to_dicts()[0]
253
- quantity = order["quantity"]
254
- token = order["token"]
255
- exchange = order["exchange"]
256
- product = self.get_product(order["product"])
257
- variety = order["variety"]
258
- order_type = self.get_order_type(data["order_type"])
251
+ order_data = filtered_order.to_dicts()[0]
252
+ quantity = order_data["quantity"]
253
+ token = order_data["token"]
254
+ exchange = order_data["exchange"]
255
+ product = self.get_product(order_data["product"])
256
+ variety = order_data["variety"]
257
+ order_type = self.get_order_type(data.get("order_type"))
259
258
 
260
259
  if "trigger_price" not in data:
261
260
  data["trigger_price"] = None
@@ -268,7 +267,7 @@ class AngelOne(Broker):
268
267
  order_params = {
269
268
  "orderid": order_id,
270
269
  "variety": variety,
271
- "price": data["price"],
270
+ "price": data.get("price"),
272
271
  "triggerprice": data["trigger_price"],
273
272
  "producttype": product,
274
273
  "duration": "DAY",
@@ -277,13 +276,14 @@ class AngelOne(Broker):
277
276
  "ordertype": order_type,
278
277
  "exchange": exchange,
279
278
  "tradingsymbol": self.get_symbol(
280
- order["tradingsymbol"], exchange=exchange
279
+ order_data["tradingsymbol"], exchange=exchange
281
280
  ),
282
281
  }
283
282
 
284
283
  Constants.logger.info(f"Modifying order [{order_id}] params [{order_params}]")
285
284
  response = self.invoke_angelone_api(
286
- self.wrapper.modifyOrder, orderparams=order_params
285
+ self.wrapper.modifyOrder,
286
+ orderparams=order_params,
287
287
  )
288
288
  Constants.logger.info(f"[MODIFY_ORDER_RESPONSE] {response}")
289
289
  return order_id
@@ -294,8 +294,8 @@ class AngelOne(Broker):
294
294
  )
295
295
  raise
296
296
 
297
- def cancel_order(self, order_id, variety="NORMAL"):
298
- self.wrapper.cancelOrder(order_id=order_id, variety=variety)
297
+ def cancel_order(self, order_id: str, variety: str | None = "NORMAL"):
298
+ self.wrapper.cancelOrder(order_id=order_id, variety=variety) # type: ignore
299
299
 
300
300
  def holdings(self):
301
301
  holdings = self.invoke_angelone_api(self.wrapper.holding)
@@ -499,7 +499,8 @@ class AngelOne(Broker):
499
499
 
500
500
  def profile(self):
501
501
  profile_data = self.invoke_angelone_api(
502
- self.wrapper.getProfile, refreshToken=self.refresh_token
502
+ self.wrapper.getProfile, # type: ignore
503
+ refreshToken=self.refresh_token,
503
504
  )
504
505
 
505
506
  profile_data = profile_data["data"]
@@ -561,7 +562,7 @@ class AngelOne(Broker):
561
562
  stop_max_attempt_number=3,
562
563
  retry_on_exception=retry_exception,
563
564
  )
564
- def invoke_angelone_api(self, fn: Callable, *args, **kwargs) -> Any:
565
+ def invoke_angelone_api(self, fn: Any, *args: Any, **kwargs: Any) -> Any:
565
566
  try:
566
567
  response = fn(*args, **kwargs)
567
568
  if "errorCode" in response and response["errorCode"] == "AG8001":