quantplay 2.0.32__tar.gz → 2.0.33__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 (72) hide show
  1. {quantplay-2.0.32 → quantplay-2.0.33}/PKG-INFO +1 -1
  2. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/aliceblue.py +5 -4
  3. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/angelone.py +4 -1
  4. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/auto_login/aliceblue.py +0 -2
  5. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/finvasia_utils/fa_noren.py +16 -10
  6. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/ft_utils/flattrade_utils.py +9 -1
  7. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/ft_utils/ft_noren.py +19 -13
  8. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/generics/broker.py +83 -68
  9. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/kite_utils.py +0 -2
  10. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/motilal.py +17 -16
  11. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/noren.py +2 -3
  12. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/uplink/uplink_utils.py +0 -1
  13. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/upstox.py +5 -5
  14. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/xts.py +14 -12
  15. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/xts_utils/Connect.py +52 -44
  16. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/zerodha.py +5 -4
  17. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/model/broker.py +19 -0
  18. quantplay-2.0.33/quantplay/model/instrument_data.py +16 -0
  19. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/utils/pickle_utils.py +3 -2
  20. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/utils/selenium_utils.py +1 -1
  21. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/wrapper/aws/s3.py +3 -6
  22. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay.egg-info/PKG-INFO +1 -1
  23. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay.egg-info/SOURCES.txt +1 -11
  24. {quantplay-2.0.32 → quantplay-2.0.33}/setup.py +1 -1
  25. quantplay-2.0.32/quantplay/strategies/options/__init__.py +0 -0
  26. quantplay-2.0.32/quantplay/strategies/options/intraday/__init__.py +0 -0
  27. quantplay-2.0.32/quantplay/strategies/options/intraday/ladder.py +0 -65
  28. quantplay-2.0.32/quantplay/strategies/options/intraday/musk.py +0 -72
  29. quantplay-2.0.32/quantplay/strategies/options/intraday/short_straddle.py +0 -10
  30. quantplay-2.0.32/quantplay/utils/__init__.py +0 -0
  31. quantplay-2.0.32/quantplay/wrapper/__init__.py +0 -0
  32. quantplay-2.0.32/quantplay/wrapper/aws/__init__.py +0 -0
  33. quantplay-2.0.32/tests/__init__.py +0 -0
  34. quantplay-2.0.32/tests/wrapper/__init__.py +0 -0
  35. quantplay-2.0.32/tests/wrapper/aws/__init__.py +0 -0
  36. {quantplay-2.0.32 → quantplay-2.0.33}/README.md +0 -0
  37. {quantplay-2.0.32 → quantplay-2.0.33}/pyproject.toml +0 -0
  38. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/__init__.py +0 -0
  39. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/__init__.py +0 -0
  40. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/auto_login/__init__.py +0 -0
  41. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/finvasia_utils/__init__.py +0 -0
  42. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/five_paisa.py +0 -0
  43. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/flattrade.py +0 -0
  44. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/ft_utils/__init__.py +0 -0
  45. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/generics/__init__.py +0 -0
  46. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/iifl_xts.py +0 -0
  47. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/shoonya.py +0 -0
  48. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/uplink/__init__.py +0 -0
  49. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/xts_utils/Exception.py +0 -0
  50. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
  51. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/broker/xts_utils/__init__.py +0 -0
  52. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/exception/__init__.py +0 -0
  53. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/exception/exceptions.py +0 -0
  54. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/model/__init__.py +0 -0
  55. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/model/generics.py +0 -0
  56. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/model/order_event.py +0 -0
  57. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/py.typed +0 -0
  58. {quantplay-2.0.32/quantplay/strategies → quantplay-2.0.33/quantplay/utils}/__init__.py +0 -0
  59. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/utils/constant.py +0 -0
  60. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/utils/exchange.py +0 -0
  61. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay/utils/number_utils.py +0 -0
  62. {quantplay-2.0.32/quantplay/strategies/equities → quantplay-2.0.33/quantplay/wrapper}/__init__.py +0 -0
  63. {quantplay-2.0.32/quantplay/strategies/equities/intraday → quantplay-2.0.33/quantplay/wrapper/aws}/__init__.py +0 -0
  64. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay.egg-info/dependency_links.txt +0 -0
  65. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay.egg-info/requires.txt +0 -0
  66. {quantplay-2.0.32 → quantplay-2.0.33}/quantplay.egg-info/top_level.txt +0 -0
  67. {quantplay-2.0.32 → quantplay-2.0.33}/setup.cfg +0 -0
  68. {quantplay-2.0.32/quantplay/strategies/equities/overnight → quantplay-2.0.33/tests}/__init__.py +0 -0
  69. {quantplay-2.0.32 → quantplay-2.0.33}/tests/conftest.py +0 -0
  70. {quantplay-2.0.32/quantplay/strategies/futures → quantplay-2.0.33/tests/wrapper}/__init__.py +0 -0
  71. {quantplay-2.0.32/quantplay/strategies/futures/overnight → quantplay-2.0.33/tests/wrapper/aws}/__init__.py +0 -0
  72. {quantplay-2.0.32 → quantplay-2.0.33}/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.32
3
+ Version: 2.0.33
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -110,15 +110,16 @@ class Aliceblue(Broker):
110
110
  Constants.logger.info("[LOADING_INSTRUMENTS] loading data from cache")
111
111
  except Exception:
112
112
  self.instrument_data = S3Utils.read_csv(
113
- "quantplay-market-data",
114
- "symbol_data/aliceblue_instruments.csv",
115
- read_from_local=False,
113
+ "quantplay-market-data", "symbol_data/aliceblue_instruments.csv"
116
114
  )
117
115
  self.initialize_symbol_data(save_as="aliceblue_instruments")
118
116
 
119
117
  self.initialize_broker_symbol_map()
120
118
 
121
- def get_transaction_type(self, transaction_type: Literal["BUY", "SELL"]):
119
+ def get_transaction_type(
120
+ self,
121
+ transaction_type: Literal["BUY", "SELL", "B", "S"],
122
+ ):
122
123
  if (
123
124
  transaction_type == "BUY"
124
125
  or transaction_type == TransactionType.Buy.value
@@ -7,6 +7,7 @@ from queue import Queue
7
7
  import traceback
8
8
  from typing import Callable, Dict
9
9
 
10
+ from SmartApi.smartExceptions import DataException
10
11
  import polars as pl
11
12
  import pyotp
12
13
  from requests.exceptions import ConnectionError, ConnectTimeout
@@ -118,7 +119,6 @@ class AngelOne(Broker):
118
119
  self.instrument_data = S3Utils.read_csv(
119
120
  "quantplay-market-data",
120
121
  "symbol_data/angelone_instruments.csv",
121
- read_from_local=False,
122
122
  )
123
123
  self.initialize_symbol_data(save_as="angelone_instruments")
124
124
 
@@ -576,6 +576,9 @@ class AngelOne(Broker):
576
576
  return response
577
577
  except (TokenException, InvalidArgumentException):
578
578
  raise
579
+ except DataException as e:
580
+ # TODO: Catch and Check for Others Exceptions
581
+ raise BrokerException(str(e))
579
582
  except Exception:
580
583
  traceback.print_exc()
581
584
  raise RetryableException("Failed to fetch user profile")
@@ -79,8 +79,6 @@ class AliceblueLogin:
79
79
  try:
80
80
  driver = Selenium().get_browser(headless=True)
81
81
 
82
- # TODO api should be fetched from configuration
83
-
84
82
  driver.get("https://ant.aliceblueonline.com/")
85
83
  AliceblueLogin.click_on_login(driver)
86
84
  AliceblueLogin.enter_user_id(driver, user_id)
@@ -7,7 +7,7 @@ import time
7
7
  import urllib.parse
8
8
  from datetime import datetime as dt
9
9
  from time import sleep
10
- from typing import Literal
10
+ from typing import Dict, Literal, TypedDict
11
11
 
12
12
  import requests
13
13
  import websocket
@@ -55,20 +55,26 @@ class BuyorSell:
55
55
  Sell = "S"
56
56
 
57
57
 
58
- def reportmsg(msg):
58
+ def reportmsg(msg: str):
59
59
  logger.debug(msg)
60
60
 
61
61
 
62
- def reporterror(msg):
62
+ def reporterror(msg: str):
63
63
  logger.error(msg)
64
64
 
65
65
 
66
- def reportinfo(msg):
66
+ def reportinfo(msg: str):
67
67
  logger.info(msg)
68
68
 
69
69
 
70
+ class FAServiceConfig(TypedDict):
71
+ host: str
72
+ routes: Dict[str, str]
73
+ websocket_endpoint: str
74
+
75
+
70
76
  class FA_NorenApi:
71
- __service_config = {
77
+ __service_config: FAServiceConfig = {
72
78
  "host": "http://wsapihost/",
73
79
  "routes": {
74
80
  "authorize": "/QuickAuth",
@@ -123,18 +129,18 @@ class FA_NorenApi:
123
129
 
124
130
  while not self.__stop_event.is_set():
125
131
  try:
126
- self.__websocket.run_forever(ping_interval=3, ping_payload='{"t":"h"}')
132
+ self.__websocket.run_forever(ping_interval=3, ping_payload='{"t":"h"}') # type: ignore
127
133
  except Exception:
128
134
  pass
129
135
 
130
136
  sleep(0.1)
131
137
 
132
- def __ws_send(self, *args, **kwargs):
138
+ def __ws_send(self, data: str | bytes):
133
139
  while not self.__websocket_connected or self.__websocket is None:
134
140
  sleep(0.05)
135
141
 
136
142
  with self.__ws_mutex:
137
- ret = self.__websocket.send(*args, **kwargs)
143
+ ret = self.__websocket.send(data)
138
144
 
139
145
  return ret
140
146
 
@@ -235,7 +241,7 @@ class FA_NorenApi:
235
241
 
236
242
  self.__stop_event.set()
237
243
  self.__websocket_connected = False
238
- self.__websocket.close()
244
+ self.__websocket.close() # type: ignore
239
245
  self.__ws_thread.join()
240
246
 
241
247
  def login(
@@ -941,7 +947,7 @@ class FA_NorenApi:
941
947
 
942
948
  headers = {"Content-Type": "application/json; charset=utf-8"}
943
949
  res = requests.post(url, data=payload, headers=headers)
944
- reportmsg(res)
950
+ reportmsg(str(res))
945
951
 
946
952
  if res.status_code != 200:
947
953
  return None
@@ -12,6 +12,7 @@ from quantplay.exception.exceptions import (
12
12
  WrongLibrarySetup,
13
13
  retry_exception,
14
14
  )
15
+ from quantplay.utils.constant import Constants
15
16
  from quantplay.utils.selenium_utils import Selenium
16
17
 
17
18
 
@@ -56,7 +57,14 @@ class FlatTradeUtils:
56
57
  time.sleep(2)
57
58
 
58
59
  url = driver.current_url
59
- request_token = url.split("code=")[1].split("&")[0]
60
+
61
+ try:
62
+ # TODO: IndexError: list index out of range
63
+ request_token = url.split("code=")[1].split("&")[0]
64
+ except Exception as e:
65
+ Constants.logger.error(f"Flattrade Selenium Error for {url}")
66
+ traceback.print_exc()
67
+ raise e
60
68
 
61
69
  driver.close()
62
70
 
@@ -7,7 +7,7 @@ import time
7
7
  import urllib.parse
8
8
  from datetime import datetime as dt
9
9
  from time import sleep
10
- from typing import Literal
10
+ from typing import Dict, Literal, TypedDict
11
11
 
12
12
  import requests
13
13
  import websocket
@@ -55,20 +55,26 @@ class BuyorSell:
55
55
  Sell = "S"
56
56
 
57
57
 
58
- def reportmsg(msg):
58
+ def reportmsg(msg: str):
59
59
  logger.debug(msg)
60
60
 
61
61
 
62
- def reporterror(msg):
62
+ def reporterror(msg: str):
63
63
  logger.error(msg)
64
64
 
65
65
 
66
- def reportinfo(msg):
66
+ def reportinfo(msg: str):
67
67
  logger.info(msg)
68
68
 
69
69
 
70
+ class FTServiceConfig(TypedDict):
71
+ host: str
72
+ routes: Dict[str, str]
73
+ websocket_endpoint: str
74
+
75
+
70
76
  class FT_NorenApi:
71
- __service_config = {
77
+ __service_config: FTServiceConfig = {
72
78
  "host": "http://wsapihost/",
73
79
  "routes": {
74
80
  "authorize": "/QuickAuth",
@@ -102,7 +108,7 @@ class FT_NorenApi:
102
108
  "websocket_endpoint": "wss://wsendpoint/",
103
109
  }
104
110
 
105
- def __init__(self, host, websocket_endpoint):
111
+ def __init__(self, host: str, websocket_endpoint: str):
106
112
  self.__service_config["host"] = host
107
113
  self.__service_config["websocket_endpoint"] = websocket_endpoint
108
114
 
@@ -121,18 +127,18 @@ class FT_NorenApi:
121
127
 
122
128
  while not self.__stop_event.is_set():
123
129
  try:
124
- self.__websocket.run_forever(ping_interval=3, ping_payload='{"t":"h"}')
130
+ self.__websocket.run_forever(ping_interval=3, ping_payload='{"t":"h"}') # type: ignore
125
131
  except Exception:
126
132
  pass
127
133
 
128
134
  sleep(0.1)
129
135
 
130
- def __ws_send(self, *args, **kwargs):
136
+ def __ws_send(self, data: bytes | str):
131
137
  while not self.__websocket_connected or self.__websocket is None:
132
138
  sleep(0.05)
133
139
 
134
140
  with self.__ws_mutex:
135
- ret = self.__websocket.send(*args, **kwargs)
141
+ ret = self.__websocket.send(data)
136
142
  return ret
137
143
 
138
144
  def __on_close_callback(self, wsapp, close_status_code, close_msg):
@@ -232,7 +238,7 @@ class FT_NorenApi:
232
238
 
233
239
  self.__stop_event.set()
234
240
  self.__websocket_connected = False
235
- self.__websocket.close()
241
+ self.__websocket.close() # type: ignore
236
242
  self.__ws_thread.join()
237
243
 
238
244
  def login(
@@ -336,7 +342,7 @@ class FT_NorenApi:
336
342
 
337
343
  return resDict
338
344
 
339
- def subscribe(self, instrument, feed_type=FeedType.TOUCHLINE):
345
+ def subscribe(self, instrument, feed_type: int = FeedType.TOUCHLINE):
340
346
  values = {}
341
347
 
342
348
  if feed_type == FeedType.TOUCHLINE:
@@ -355,7 +361,7 @@ class FT_NorenApi:
355
361
 
356
362
  self.__ws_send(data)
357
363
 
358
- def unsubscribe(self, instrument, feed_type=FeedType.TOUCHLINE):
364
+ def unsubscribe(self, instrument, feed_type: int = FeedType.TOUCHLINE):
359
365
  values = {}
360
366
 
361
367
  if feed_type == FeedType.TOUCHLINE:
@@ -934,7 +940,7 @@ class FT_NorenApi:
934
940
 
935
941
  headers = {"Content-Type": "application/json; charset=utf-8"}
936
942
  res = requests.post(url, data=payload, headers=headers)
937
- reportmsg(res)
943
+ reportmsg(str(res))
938
944
 
939
945
  if res.status_code != 200:
940
946
  return None
@@ -30,10 +30,10 @@ from quantplay.exception.exceptions import (
30
30
  )
31
31
  from quantplay.model.broker import (
32
32
  ExchangeType,
33
- ModifyOrderRequest,
34
33
  UserBrokerProfileResponse,
35
34
  )
36
35
  from quantplay.model.generics import ProductType, TransactionType, OrderTypeType
36
+ from quantplay.model.instrument_data import InstrumentDataType
37
37
  from quantplay.model.order_event import OrderUpdateEvent
38
38
  from quantplay.utils.constant import Constants
39
39
  from quantplay.utils.exchange import Market as MarketConstants
@@ -158,15 +158,16 @@ class Broker:
158
158
  raise StaleDataFound(f"Couldn't find symbol data for [{exchange}:{symbol}]")
159
159
 
160
160
  def initialize_symbol_data(self, save_as: str | None = None) -> None:
161
- instruments = self.instrument_data
162
- instruments = instruments.to_dict("records")
163
- self.symbol_data = {}
161
+ instruments_df = self.instrument_data
162
+ instruments: List[InstrumentDataType] = instruments_df.to_dict("records") # type: ignore
163
+
164
+ self.symbol_data: Dict[str, InstrumentDataType] = {}
164
165
  for instrument in instruments:
165
166
  exchange = instrument["exchange"]
166
167
  tradingsymbol = instrument["broker_symbol"]
167
168
 
168
169
  instrument_data = copy.deepcopy(instrument)
169
- self.symbol_data["{}:{}".format(exchange, tradingsymbol)] = instrument_data
170
+ self.symbol_data[f"{exchange}:{tradingsymbol}"] = instrument_data
170
171
 
171
172
  if save_as:
172
173
  PickleUtils.save_data(self.symbol_data, save_as)
@@ -202,13 +203,12 @@ class Broker:
202
203
  self.instrument_data = S3Utils.read_csv(
203
204
  "quantplay-market-data",
204
205
  f"symbol_data/{file_name}.csv",
205
- read_from_local=False,
206
206
  )
207
207
  self.initialize_symbol_data(save_as=file_name)
208
208
 
209
209
  self.initialize_broker_symbol_map()
210
210
 
211
- def round_to_tick(self, number):
211
+ def round_to_tick(self, number: int | float) -> float:
212
212
  return round(number * 20) / 20
213
213
 
214
214
  def get_user_id(self):
@@ -236,64 +236,66 @@ class Broker:
236
236
  seg_condition = [
237
237
  (
238
238
  (self.instrument_data["instrument"].str.contains("FUT"))
239
- & (self.instrument_data.instrument != "OPTFUT")
239
+ & (self.instrument_data["instrument"] != "OPTFUT")
240
240
  )
241
241
  ]
242
242
 
243
243
  tradingsymbol = [
244
- self.instrument_data.tradingsymbol
245
- + self.instrument_data.expiry_year
246
- + self.instrument_data.month
244
+ self.instrument_data["tradingsymbol"]
245
+ + self.instrument_data["expiry_year"]
246
+ + self.instrument_data["month"]
247
247
  + "FUT"
248
248
  ]
249
249
 
250
250
  self.instrument_data.loc[:, "tradingsymbol"] = np.select(
251
- seg_condition, tradingsymbol, default=self.instrument_data.tradingsymbol
251
+ seg_condition, tradingsymbol, default=self.instrument_data["tradingsymbol"]
252
252
  )
253
253
 
254
254
  def add_quantplay_opt_tradingsymbol(self):
255
255
  seg_condition = self.instrument_data["strike_price"] > 0
256
256
  weekly_option_condition = (
257
- self.instrument_data.expiry.dt.month
258
- == self.instrument_data.next_expiry.dt.month
259
- ) & (self.instrument_data.exchange == "NFO")
257
+ self.instrument_data["expiry"].dt.month
258
+ == self.instrument_data["next_expiry"].dt.month
259
+ ) & (self.instrument_data["exchange"] == "NFO")
260
260
  month_option_condition = (
261
- self.instrument_data.expiry.dt.month
262
- != self.instrument_data.next_expiry.dt.month
263
- ) | (self.instrument_data.exchange == "MCX")
261
+ self.instrument_data["expiry"].dt.month
262
+ != self.instrument_data["next_expiry"].dt.month
263
+ ) | (self.instrument_data["exchange"] == "MCX")
264
264
 
265
265
  self.instrument_data.loc[:, "tradingsymbol"] = np.where(
266
266
  seg_condition,
267
- self.instrument_data.tradingsymbol + self.instrument_data.expiry_year,
268
- self.instrument_data.tradingsymbol,
267
+ self.instrument_data["tradingsymbol"] + self.instrument_data["expiry_year"],
268
+ self.instrument_data["tradingsymbol"],
269
269
  )
270
270
 
271
271
  self.instrument_data.loc[:, "tradingsymbol"] = np.where(
272
272
  seg_condition & weekly_option_condition,
273
- self.instrument_data.tradingsymbol + self.instrument_data.week_option_prefix,
274
- self.instrument_data.tradingsymbol,
273
+ self.instrument_data["tradingsymbol"]
274
+ + self.instrument_data["week_option_prefix"],
275
+ self.instrument_data["tradingsymbol"],
275
276
  )
276
277
 
277
278
  self.instrument_data.loc[:, "tradingsymbol"] = np.where(
278
279
  seg_condition & month_option_condition,
279
- self.instrument_data.tradingsymbol + self.instrument_data.month,
280
- self.instrument_data.tradingsymbol,
280
+ self.instrument_data["tradingsymbol"] + self.instrument_data["month"],
281
+ self.instrument_data["tradingsymbol"],
281
282
  )
282
283
 
283
284
  self.instrument_data.loc[:, "tradingsymbol"] = np.where(
284
285
  seg_condition,
285
- self.instrument_data.tradingsymbol
286
- + self.instrument_data.strike_price.astype(float)
286
+ self.instrument_data["tradingsymbol"]
287
+ + self.instrument_data["strike_price"]
288
+ .astype(float)
287
289
  .astype(str)
288
290
  .str.split(".")
289
291
  .str[0],
290
- self.instrument_data.tradingsymbol,
292
+ self.instrument_data["tradingsymbol"],
291
293
  )
292
294
 
293
295
  self.instrument_data.loc[:, "tradingsymbol"] = np.where(
294
296
  seg_condition,
295
- self.instrument_data.tradingsymbol + self.instrument_data.option_type,
296
- self.instrument_data.tradingsymbol,
297
+ self.instrument_data["tradingsymbol"] + self.instrument_data["option_type"],
298
+ self.instrument_data["tradingsymbol"],
297
299
  )
298
300
 
299
301
  def get_df_from_zip(self, url: str):
@@ -308,11 +310,11 @@ class Broker:
308
310
  return pd.read_csv("/tmp/{}.csv".format(file_name))
309
311
 
310
312
  def initialize_expiry_fields(self):
311
- self.instrument_data.loc[:, "tradingsymbol"] = (
312
- self.instrument_data.instrument_symbol
313
- )
313
+ self.instrument_data.loc[:, "tradingsymbol"] = self.instrument_data[
314
+ "instrument_symbol"
315
+ ]
314
316
  self.instrument_data.loc[:, "expiry"] = pd.to_datetime(
315
- self.instrument_data.instrument_expiry
317
+ self.instrument_data["instrument_expiry"]
316
318
  )
317
319
 
318
320
  self.instrument_data.loc[:, "expiry_year"] = (
@@ -326,42 +328,42 @@ class Broker:
326
328
  self.instrument_data["expiry"].dt.strftime("%m").astype(float).astype(str)
327
329
  )
328
330
  self.instrument_data.loc[:, "month_number"] = np.where(
329
- self.instrument_data.month_number == "nan",
331
+ self.instrument_data["month_number"] == "nan",
330
332
  np.nan,
331
- self.instrument_data.month_number.str.split(".").str[0],
333
+ self.instrument_data["month_number"].str.split(".").str[0],
332
334
  )
333
335
 
334
336
  self.instrument_data.loc[:, "week_option_prefix"] = np.where(
335
- self.instrument_data.month_number.astype(float) >= 10,
336
- self.instrument_data.month.str[0]
337
+ self.instrument_data["month_number"].astype(float) >= 10,
338
+ self.instrument_data["month"].str[0]
337
339
  + self.instrument_data["expiry"].dt.strftime("%d").astype(str),
338
- self.instrument_data.month_number
340
+ self.instrument_data["month_number"]
339
341
  + self.instrument_data["expiry"].dt.strftime("%d").astype(str),
340
342
  )
341
343
 
342
- self.instrument_data.loc[:, "next_expiry"] = (
343
- self.instrument_data.expiry + pd.DateOffset(days=7)
344
- )
344
+ self.instrument_data.loc[:, "next_expiry"] = self.instrument_data[
345
+ "expiry"
346
+ ] + pd.DateOffset(days=7)
345
347
 
346
- @cached(cache=TTLCache(maxsize=1, ttl=2))
348
+ @cached(cache=TTLCache(maxsize=1, ttl=2)) # type: ignore
347
349
  def cached_orders(self) -> pl.DataFrame:
348
350
  return self.orders()
349
351
 
350
- @cached(cache=TTLCache(maxsize=1, ttl=2))
352
+ @cached(cache=TTLCache(maxsize=1, ttl=2)) # type: ignore
351
353
  def cached_positions(self) -> pl.DataFrame:
352
354
  return self.positions()
353
355
 
354
356
  def execute_order(
355
357
  self,
356
- tradingsymbol,
357
- exchange,
358
- quantity,
359
- order_type,
360
- transaction_type,
361
- stoploss,
362
- tag,
363
- product,
364
- price,
358
+ tradingsymbol: str,
359
+ exchange: ExchangeType,
360
+ quantity: int,
361
+ order_type: OrderTypeType,
362
+ transaction_type: TransactionType,
363
+ stoploss: float | None,
364
+ tag: str,
365
+ product: ProductType,
366
+ price: float,
365
367
  ):
366
368
  upper_circuit = None
367
369
  trade_price = copy.deepcopy(price)
@@ -396,6 +398,7 @@ class Broker:
396
398
  raise Exception("{} not supported for trading".format(exchange))
397
399
 
398
400
  sl_price = self.round_to_tick(price)
401
+
399
402
  else:
400
403
  raise Exception(
401
404
  "Invalid transaction_type {}".format(transaction_type)
@@ -427,7 +430,7 @@ class Broker:
427
430
  )
428
431
 
429
432
  if order_type == "MARKET":
430
- trade_price = 0
433
+ trade_price: float = 0
431
434
 
432
435
  response = self.place_order(
433
436
  tradingsymbol=tradingsymbol,
@@ -462,7 +465,7 @@ class Broker:
462
465
  def get_exchange(self, exchange):
463
466
  return exchange
464
467
 
465
- def live_data(self, exchange, tradingsymbol):
468
+ def live_data(self, exchange: ExchangeType, tradingsymbol: str):
466
469
  return {
467
470
  "ltp": self.ltp(exchange, tradingsymbol),
468
471
  "upper_circuit": None,
@@ -472,7 +475,13 @@ class Broker:
472
475
  def basket_margin(self, basket_orders) -> Dict[str, Any]:
473
476
  raise FeatureNotSupported("Margin calculator not supported by broker")
474
477
 
475
- def verify_rms_square_off(self, stoploss, target, keep_hedges=False, ticks=1):
478
+ def verify_rms_square_off(
479
+ self,
480
+ stoploss: float | None,
481
+ target: float | None,
482
+ keep_hedges: bool = False,
483
+ ticks: int = 1,
484
+ ):
476
485
  positions = self.positions()
477
486
  pnl = positions["pnl"].sum()
478
487
 
@@ -514,31 +523,37 @@ class Broker:
514
523
  def get_product(self, product):
515
524
  return product
516
525
 
517
- def get_lot_size(self, exchange, tradingsymbol):
526
+ def get_lot_size(self, exchange: ExchangeType, tradingsymbol: str):
518
527
  tradingsymbol = self.get_symbol(tradingsymbol, exchange=exchange)
519
- exchange = self.get_exchange(exchange)
520
- if exchange == "BSE" or exchange == "NSE":
528
+ broker_exchange = self.get_exchange(exchange)
529
+ if broker_exchange == "BSE" or broker_exchange == "NSE":
521
530
  return 1
522
531
  try:
523
532
  return int(
524
- self.symbol_data["{}:{}".format(exchange, tradingsymbol)]["lot_size"]
533
+ self.symbol_data["{}:{}".format(broker_exchange, tradingsymbol)][
534
+ "lot_size"
535
+ ]
525
536
  )
526
537
  except Exception as e:
527
538
  logger.error(
528
- f"[GET_LOT_SIZE] unable to get lot size for {exchange} {tradingsymbol}"
539
+ f"[GET_LOT_SIZE] unable to get lot size for {broker_exchange} {tradingsymbol}"
529
540
  )
530
541
  raise e
531
542
 
532
- def filter_orders(self, orders, tag=None, status=None):
543
+ def filter_orders(
544
+ self, orders: pd.DataFrame, tag: str | None = None, status: str | None = None
545
+ ):
533
546
  if tag:
534
- orders = orders[orders.tag == tag]
547
+ orders = orders[orders["tag"] == tag]
535
548
 
536
549
  if status:
537
- orders = orders[orders.status == status]
550
+ orders = orders[orders["status"] == status]
538
551
 
539
552
  return orders
540
553
 
541
- def option_symbol(self, underlying_symbol, expiry_date, strike_price, type):
554
+ def option_symbol(
555
+ self, underlying_symbol: str, expiry_date, strike_price: float, type
556
+ ):
542
557
  option_symbol = MarketConstants.INDEX_SYMBOL_TO_DERIVATIVE_SYMBOL_MAP[
543
558
  underlying_symbol
544
559
  ]
@@ -567,10 +582,10 @@ class Broker:
567
582
 
568
583
  def exit_all_trigger_orders(
569
584
  self,
570
- tag="ALL",
585
+ tag: str = "ALL",
571
586
  symbol_contains=None,
572
587
  order_timestamp=None,
573
- modify_sleep_time=10,
588
+ modify_sleep_time: float = 10,
574
589
  ):
575
590
  stoploss_orders = self.orders()
576
591
  stoploss_orders = stoploss_orders.filter(pl.col("status") == "TRIGGER PENDING")
@@ -1210,7 +1225,7 @@ class Broker:
1210
1225
  """
1211
1226
  raise NotImplementedError
1212
1227
 
1213
- def modify_order(self, order_to_modify: ModifyOrderRequest) -> str:
1228
+ def modify_order(self, order_to_modify) -> str:
1214
1229
  """Modifies Existing Order place on exchange
1215
1230
 
1216
1231
  Args:
@@ -1235,7 +1250,7 @@ class Broker:
1235
1250
  product: ProductType,
1236
1251
  price: float,
1237
1252
  trigger_price: float | None = None,
1238
- ) -> str:
1253
+ ) -> str | None:
1239
1254
  """Function for Place Order to exchange
1240
1255
 
1241
1256
  Args:
@@ -73,8 +73,6 @@ class KiteUtils:
73
73
  pyotp.TOTP(totp).now()
74
74
  driver = Selenium().get_browser()
75
75
 
76
- # TODO api should be fetched from configuration
77
-
78
76
  kite_url = "https://kite.trade/connect/login?api_key={}&v=3".format(api_key)
79
77
  print("Kite Url {}".format(kite_url))
80
78