quantplay 2.0.41__tar.gz → 2.0.43__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 (66) hide show
  1. {quantplay-2.0.41 → quantplay-2.0.43}/PKG-INFO +26 -1
  2. {quantplay-2.0.41 → quantplay-2.0.43}/pyproject.toml +1 -1
  3. quantplay-2.0.43/quantplay/broker/__init__.py +25 -0
  4. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/aliceblue.py +13 -4
  5. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/angelone.py +6 -3
  6. {quantplay-2.0.41/quantplay/broker/generics → quantplay-2.0.43/quantplay/broker}/broker_factory.py +107 -69
  7. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/dhan.py +2 -35
  8. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/finvasia_utils/fa_noren.py +3 -2
  9. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/five_paisa.py +11 -15
  10. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/flattrade.py +3 -3
  11. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/ft_utils/ft_noren.py +3 -2
  12. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/motilal.py +16 -15
  13. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/noren.py +7 -3
  14. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/upstox.py +3 -3
  15. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/xts.py +1 -1
  16. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/xts_utils/Connect.py +1 -2
  17. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/xts_utils/InteractiveSocketClient.py +1 -0
  18. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/zerodha.py +1 -1
  19. quantplay-2.0.43/quantplay/exception/exceptions.py +100 -0
  20. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/model/instrument_data.py +2 -0
  21. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/wrapper/aws/s3.py +4 -3
  22. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay.egg-info/PKG-INFO +26 -1
  23. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay.egg-info/SOURCES.txt +1 -1
  24. {quantplay-2.0.41 → quantplay-2.0.43}/setup.py +1 -1
  25. quantplay-2.0.41/quantplay/exception/exceptions.py +0 -114
  26. quantplay-2.0.41/tests/wrapper/aws/__init__.py +0 -0
  27. {quantplay-2.0.41 → quantplay-2.0.43}/README.md +0 -0
  28. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/__init__.py +0 -0
  29. {quantplay-2.0.41/quantplay/broker → quantplay-2.0.43/quantplay/broker/auto_login}/__init__.py +0 -0
  30. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/auto_login/aliceblue.py +1 -1
  31. {quantplay-2.0.41/quantplay/broker/auto_login → quantplay-2.0.43/quantplay/broker/finvasia_utils}/__init__.py +0 -0
  32. {quantplay-2.0.41/quantplay/broker/finvasia_utils → quantplay-2.0.43/quantplay/broker/ft_utils}/__init__.py +0 -0
  33. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  34. {quantplay-2.0.41/quantplay/broker/ft_utils → quantplay-2.0.43/quantplay/broker/generics}/__init__.py +0 -0
  35. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/generics/broker.py +2 -2
  36. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/iifl_xts.py +0 -0
  37. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/kite_utils.py +0 -0
  38. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/shoonya.py +0 -0
  39. {quantplay-2.0.41/quantplay/broker/generics → quantplay-2.0.43/quantplay/broker/uplink}/__init__.py +0 -0
  40. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/uplink/uplink_utils.py +0 -0
  41. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/broker/xts_utils/Exception.py +0 -0
  42. {quantplay-2.0.41/quantplay/broker/uplink → quantplay-2.0.43/quantplay/broker/xts_utils}/__init__.py +0 -0
  43. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/exception/__init__.py +0 -0
  44. {quantplay-2.0.41/quantplay/broker/xts_utils → quantplay-2.0.43/quantplay/model}/__init__.py +0 -0
  45. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/model/broker.py +0 -0
  46. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/model/generics.py +0 -0
  47. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/model/order_event.py +0 -0
  48. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/py.typed +0 -0
  49. {quantplay-2.0.41/quantplay/model → quantplay-2.0.43/quantplay/utils}/__init__.py +0 -0
  50. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/utils/caching.py +0 -0
  51. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/utils/constant.py +0 -0
  52. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/utils/exchange.py +0 -0
  53. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/utils/number_utils.py +0 -0
  54. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/utils/pickle_utils.py +1 -1
  55. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay/utils/selenium_utils.py +0 -0
  56. {quantplay-2.0.41/quantplay/utils → quantplay-2.0.43/quantplay/wrapper}/__init__.py +0 -0
  57. {quantplay-2.0.41/quantplay/wrapper → quantplay-2.0.43/quantplay/wrapper/aws}/__init__.py +0 -0
  58. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay.egg-info/dependency_links.txt +0 -0
  59. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay.egg-info/requires.txt +0 -0
  60. {quantplay-2.0.41 → quantplay-2.0.43}/quantplay.egg-info/top_level.txt +0 -0
  61. {quantplay-2.0.41 → quantplay-2.0.43}/setup.cfg +0 -0
  62. {quantplay-2.0.41/quantplay/wrapper/aws → quantplay-2.0.43/tests}/__init__.py +0 -0
  63. {quantplay-2.0.41 → quantplay-2.0.43}/tests/conftest.py +0 -0
  64. {quantplay-2.0.41/tests → quantplay-2.0.43/tests/wrapper}/__init__.py +0 -0
  65. {quantplay-2.0.41/tests/wrapper → quantplay-2.0.43/tests/wrapper/aws}/__init__.py +0 -0
  66. {quantplay-2.0.41 → quantplay-2.0.43}/tests/wrapper/aws/s3_test.py +0 -0
@@ -1,11 +1,36 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantplay
3
- Version: 2.0.41
3
+ Version: 2.0.43
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
7
7
  Author-email:
8
8
  License: MIT
9
+ Requires-Dist: setuptools
10
+ Requires-Dist: path
11
+ Requires-Dist: pyotp
12
+ Requires-Dist: retrying
13
+ Requires-Dist: boto3
14
+ Requires-Dist: numpy
15
+ Requires-Dist: websocket-client
16
+ Requires-Dist: smartapi-python
17
+ Requires-Dist: logzero
18
+ Requires-Dist: selenium
19
+ Requires-Dist: requests
20
+ Requires-Dist: pandas
21
+ Requires-Dist: pyarrow
22
+ Requires-Dist: polars
23
+ Requires-Dist: kiteconnect
24
+ Requires-Dist: pya3
25
+ Requires-Dist: py5paisa
26
+ Requires-Dist: upstox-python-sdk
27
+ Requires-Dist: undetected-chromedriver
28
+ Requires-Dist: cachetools
29
+ Requires-Dist: py_vollib
30
+ Requires-Dist: python-engineio
31
+ Requires-Dist: python-socketio
32
+ Requires-Dist: six
33
+ Requires-Dist: dhanhq
9
34
 
10
35
  # Quantplay Alpha playground
11
36
 
@@ -6,7 +6,7 @@ line-length = 90
6
6
 
7
7
  [tool.pyright]
8
8
  typeCheckingMode = "strict"
9
- pythonVersion = "3.12"
9
+ pythonVersion = "3.10"
10
10
  venvPath = "."
11
11
  venv = ".venv"
12
12
  reportUntypedFunctionDecorator="none"
@@ -0,0 +1,25 @@
1
+ from .aliceblue import Aliceblue
2
+ from .angelone import AngelOne
3
+ from .broker_factory import BrokerFactory
4
+ from .dhan import Dhan
5
+ from .five_paisa import FivePaisa
6
+ from .flattrade import FlatTrade
7
+ from .iifl_xts import IIFL
8
+ from .motilal import Motilal
9
+ from .shoonya import FinvAsia
10
+ from .upstox import Upstox
11
+ from .zerodha import Zerodha
12
+
13
+ __all__ = [
14
+ "Aliceblue",
15
+ "AngelOne",
16
+ "BrokerFactory",
17
+ "Dhan",
18
+ "FivePaisa",
19
+ "FlatTrade",
20
+ "FinvAsia",
21
+ "Motilal",
22
+ "Zerodha",
23
+ "Upstox",
24
+ "IIFL",
25
+ ]
@@ -1,17 +1,23 @@
1
1
  import codecs
2
2
  import copy
3
3
  import pickle
4
- from queue import Queue
5
4
  import traceback
5
+ from queue import Queue
6
6
  from typing import Any, Dict, Literal
7
7
 
8
8
  import polars as pl
9
9
  from pya3 import (
10
10
  Aliceblue as Alice,
11
+ )
12
+ from pya3 import (
11
13
  OrderType as AliceOrderType,
12
- TransactionType as AliceTransactionType,
14
+ )
15
+ from pya3 import (
13
16
  ProductType as AliceProductType,
14
17
  )
18
+ from pya3 import (
19
+ TransactionType as AliceTransactionType,
20
+ )
15
21
  from retrying import retry # type: ignore
16
22
 
17
23
  from quantplay.broker.generics.broker import Broker
@@ -50,8 +56,9 @@ class Aliceblue(Broker):
50
56
  api_key: str | None = None,
51
57
  order_updates: Queue[OrderUpdateEvent] | None = None,
52
58
  client: str | None = None,
59
+ load_instrument: bool = True,
53
60
  ):
54
- super(Aliceblue, self).__init__()
61
+ super().__init__()
55
62
  self.order_updates = order_updates
56
63
 
57
64
  try:
@@ -82,7 +89,9 @@ class Aliceblue(Broker):
82
89
  raise RetryableException(str(e))
83
90
 
84
91
  self.user_id = self.alice.user_id
85
- self.load_instrument()
92
+
93
+ if load_instrument:
94
+ self.load_instrument()
86
95
 
87
96
  def set_client(self, serialized_client: str):
88
97
  try:
@@ -1,16 +1,16 @@
1
1
  import binascii
2
2
  import copy
3
3
  import json
4
- from queue import Queue
5
4
  import traceback
5
+ from queue import Queue
6
6
  from typing import Any, Dict
7
7
 
8
- from SmartApi.smartExceptions import DataException # type: ignore
9
8
  import polars as pl
10
9
  import pyotp
11
10
  from requests.exceptions import ConnectionError, ConnectTimeout
12
11
  from retrying import retry # type: ignore
13
12
  from SmartApi import SmartConnect # type: ignore
13
+ from SmartApi.smartExceptions import DataException # type: ignore
14
14
 
15
15
  from quantplay.broker.generics.broker import Broker
16
16
  from quantplay.exception.exceptions import (
@@ -58,7 +58,7 @@ class AngelOne(Broker):
58
58
  access_token: str | None = None,
59
59
  load_instrument: bool = True,
60
60
  ):
61
- super(AngelOne, self).__init__()
61
+ super().__init__()
62
62
  self.order_updates = order_updates
63
63
 
64
64
  try:
@@ -73,6 +73,7 @@ class AngelOne(Broker):
73
73
  else:
74
74
  if totp is None:
75
75
  raise InvalidArgumentException("TOTP Key is Missing")
76
+
76
77
  self.wrapper = SmartConnect(api_key=api_key)
77
78
  response = self.invoke_angelone_api(
78
79
  self.wrapper.generateSession, # type: ignore
@@ -80,10 +81,12 @@ class AngelOne(Broker):
80
81
  password=mpin,
81
82
  totp=pyotp.TOTP(totp).now(),
82
83
  )
84
+
83
85
  if response["status"] is False:
84
86
  if "message" in response:
85
87
  raise InvalidArgumentException(response["message"])
86
88
  raise InvalidArgumentException("Invalid API credentials")
89
+
87
90
  token_data = self.invoke_angelone_api(
88
91
  self.wrapper.generateToken, # type: ignore
89
92
  refresh_token=self.wrapper.refresh_token, # type: ignore
@@ -5,7 +5,6 @@ from typing import Any, Dict
5
5
 
6
6
  from quantplay.broker.aliceblue import Aliceblue
7
7
  from quantplay.broker.angelone import AngelOne
8
-
9
8
  from quantplay.broker.five_paisa import FivePaisa
10
9
  from quantplay.broker.flattrade import FlatTrade
11
10
  from quantplay.broker.iifl_xts import IIFL as IIFL_XTS
@@ -14,9 +13,8 @@ from quantplay.broker.shoonya import FinvAsia
14
13
  from quantplay.broker.upstox import Upstox
15
14
  from quantplay.broker.zerodha import Zerodha
16
15
  from quantplay.exception.exceptions import InvalidArgumentException
17
-
18
- from quantplay.utils.pickle_utils import PickleUtils
19
16
  from quantplay.utils.caching import InstrumentCache
17
+ from quantplay.utils.pickle_utils import PickleUtils
20
18
 
21
19
  BrokerType = (
22
20
  Aliceblue
@@ -58,62 +56,47 @@ class BrokerFactory:
58
56
  Broker.UPSTOX: "upstox_instruments",
59
57
  Broker.FIVEPAISA_OPENAPI: "5paisa_instruments",
60
58
  }
59
+ broker_required_args = {
60
+ Broker.ZERODHA: set(["user_id", "zerodha_wrapper"]),
61
+ Broker.FINVASIA: set(["user_id", "user_token"]),
62
+ Broker.FLATTRADE: set(["user_id", "user_token"]),
63
+ Broker.IIFL_XTS: set(["user_id", "wrapper", "md_wrapper"]),
64
+ Broker.MOTILAL: set(["user_id", "headers"]),
65
+ Broker.ALICEBLUE: set(["user_id", "client"]),
66
+ Broker.UPSTOX: set(["user_id", "access_token"]),
67
+ Broker.FIVEPAISA_OPENAPI: set(["user_id", "client"]),
68
+ Broker.ANGELONE: set(
69
+ [
70
+ "user_id",
71
+ "api_key",
72
+ "access_token",
73
+ "refresh_token",
74
+ "feed_token",
75
+ ]
76
+ ),
77
+ }
61
78
 
62
79
  def __init__(self):
63
80
  self.client_broker_data: Dict[str, BrokerType] = {}
64
81
 
65
82
  def get_broker_key(self, username: str, broker_name: str) -> str:
66
- return "{}:{}".format(username, broker_name)
67
-
68
- def set_broker_instruments(self, broker_name: str, broker: BrokerType) -> None:
69
- symbol_data_key = f"{broker_name}_instruments"
70
- quantplay_symbol_key = f"{broker_name}_qplay_symbols"
71
- broker_symbol_key = f"{broker_name}_broker_symbols"
83
+ return f"{username}:{broker_name}"
72
84
 
73
- symbol_data = instrument_cache.get(symbol_data_key)
74
- quantplay_symbol_map = instrument_cache.get(quantplay_symbol_key)
75
- broker_symbol_map = instrument_cache.get(broker_symbol_key)
76
-
77
- if symbol_data is not None:
78
- broker.symbol_data = symbol_data
79
-
80
- if broker_name != "Zerodha":
81
- if quantplay_symbol_map is not None and broker_symbol_map is not None:
82
- broker.quantplay_symbol_map = quantplay_symbol_map
83
- broker.broker_symbol_map = broker_symbol_map
84
-
85
- else:
86
- broker.initialize_broker_symbol_map()
87
- instrument_cache.set(
88
- quantplay_symbol_key, broker.quantplay_symbol_map
89
- )
90
- instrument_cache.set(broker_symbol_key, broker.broker_symbol_map)
85
+ def validate_broker_args(self, broker_info: Dict[str, Any]):
86
+ broker = broker_info["broker"]
87
+ broker_data = broker_info["broker_data"]
91
88
 
92
- return
89
+ if broker not in self.broker_required_args.keys():
90
+ raise InvalidArgumentException(f"Unsupported Broker: '{broker}'")
93
91
 
94
- try:
95
- symbol_data = PickleUtils.load_data(
96
- BrokerFactory.broker_instruments_map[broker_name]
92
+ if not self.broker_required_args[broker].issubset(broker_data.keys()):
93
+ raise InvalidArgumentException(
94
+ f"Missing Arguments for {broker_info['username']}:{broker_info['nickname']} in broker '{broker}' -> {self.broker_required_args[broker].difference(broker_info.keys())}"
97
95
  )
98
- broker.symbol_data = symbol_data
99
-
100
- if broker_name != "Zerodha":
101
- broker.initialize_broker_symbol_map()
102
- instrument_cache.set(quantplay_symbol_key, broker.quantplay_symbol_map)
103
-
104
- instrument_cache.set(symbol_data_key, symbol_data)
105
-
106
- except Exception:
107
- traceback.print_exc()
108
-
109
- if broker_name != "Zerodha":
110
- broker.load_instrument(BrokerFactory.broker_instruments_map[broker_name])
111
- else:
112
- broker.initialize_symbol_data()
113
96
 
114
97
  def store_broker_client(
115
98
  self, broker_info: Dict[str, Any], load_instrument: bool = True
116
- ) -> None:
99
+ ) -> BrokerType | None:
117
100
  username = broker_info["username"]
118
101
  nickname = broker_info["nickname"]
119
102
 
@@ -125,9 +108,9 @@ class BrokerFactory:
125
108
  broker_client: BrokerType | None = None
126
109
 
127
110
  if broker == "Motilal":
128
- motial_headers = broker_data["headers"]
129
111
  broker_client = Motilal(
130
- headers=motial_headers, load_instrument=load_instrument
112
+ headers=broker_data["headers"],
113
+ load_instrument=load_instrument,
131
114
  )
132
115
 
133
116
  elif broker == "Zerodha":
@@ -147,31 +130,29 @@ class BrokerFactory:
147
130
  )
148
131
 
149
132
  elif broker == Broker.ALICEBLUE:
150
- broker_client = Aliceblue(client=broker_data["client"])
133
+ broker_client = Aliceblue(
134
+ client=broker_data["client"],
135
+ load_instrument=load_instrument,
136
+ )
151
137
 
152
138
  elif broker == Broker.UPSTOX:
153
139
  broker_client = Upstox(
154
140
  access_token=broker_data["access_token"],
155
141
  user_id=broker_data["user_id"],
142
+ load_instrument=load_instrument,
156
143
  )
157
144
 
158
145
  elif broker == Broker.FINVASIA:
159
- finvasia_data = broker_data
160
146
  broker_client = FinvAsia(
161
- order_updates=None,
162
- user_id=finvasia_data["user_id"],
163
- password=finvasia_data["password"],
164
- user_token=finvasia_data["user_token"],
147
+ user_id=broker_data["user_id"],
148
+ user_token=broker_data["user_token"],
165
149
  load_instrument=load_instrument,
166
150
  )
167
151
 
168
152
  elif broker == Broker.FLATTRADE:
169
- flattrade_data = broker_data
170
153
  broker_client = FlatTrade(
171
- order_updates=None,
172
- user_id=flattrade_data["user_id"],
173
- password=flattrade_data["password"],
174
- user_token=flattrade_data["user_token"],
154
+ user_id=broker_data["user_id"],
155
+ user_token=broker_data["user_token"],
175
156
  load_instrument=load_instrument,
176
157
  )
177
158
 
@@ -181,22 +162,30 @@ class BrokerFactory:
181
162
  load_instrument=load_instrument,
182
163
  )
183
164
 
184
- self.client_broker_data[broker_key] = broker_client
185
-
186
165
  elif broker == Broker.IIFL_XTS:
187
- iifl_xts_data = broker_data
188
166
  broker_client = IIFL_XTS(
189
167
  wrapper=broker_data["wrapper"],
190
168
  md_wrapper=broker_data["md_wrapper"],
191
- client_id=iifl_xts_data["user_id"],
169
+ client_id=broker_data["user_id"],
192
170
  load_instrument=load_instrument,
193
171
  )
194
172
 
195
173
  else:
196
- raise InvalidArgumentException(f"Broker {broker} not supported")
174
+ raise InvalidArgumentException(f"Broker '{broker}' not supported")
175
+
176
+ if not load_instrument:
177
+ broker_client = self.set_broker_instruments(
178
+ broker_name=broker, broker=broker_client
179
+ )
180
+
181
+ broker_client.username = broker_info["username"]
182
+ broker_client.nickname = broker_info["nickname"]
183
+ broker_client.broker_name = broker_info["broker"]
184
+ broker_client.user_id = broker_data["user_id"]
197
185
 
198
186
  self.client_broker_data[broker_key] = broker_client
199
- self.set_broker_instruments(broker_name=broker, broker=broker_client)
187
+
188
+ return broker_client
200
189
 
201
190
  def get_broker_client(self, broker_info: Dict[str, Any]) -> BrokerType:
202
191
  username = broker_info["username"]
@@ -207,13 +196,62 @@ class BrokerFactory:
207
196
  if broker_key in self.client_broker_data:
208
197
  return self.client_broker_data[broker_key]
209
198
 
210
- self.store_broker_client(broker_info, load_instrument=False)
199
+ self.validate_broker_args(broker_info)
200
+ broker_client = self.store_broker_client(broker_info, load_instrument=False)
211
201
 
212
- if broker_key in self.client_broker_data:
213
- return self.client_broker_data[broker_key]
202
+ if broker_client is not None:
203
+ return broker_client
214
204
  else:
215
205
  raise InvalidArgumentException("Invalid broker API configuration")
216
206
 
207
+ def set_broker_instruments(self, broker_name: str, broker: BrokerType) -> BrokerType:
208
+ symbol_data_key = f"{broker_name}_instruments"
209
+ quantplay_symbol_key = f"{broker_name}_qplay_symbols"
210
+ broker_symbol_key = f"{broker_name}_broker_symbols"
211
+
212
+ symbol_data = instrument_cache.get(symbol_data_key)
213
+ quantplay_symbol_map = instrument_cache.get(quantplay_symbol_key)
214
+ broker_symbol_map = instrument_cache.get(broker_symbol_key)
215
+
216
+ if symbol_data is not None:
217
+ broker.symbol_data = symbol_data
218
+
219
+ if broker_name != "Zerodha":
220
+ if quantplay_symbol_map is not None and broker_symbol_map is not None:
221
+ broker.quantplay_symbol_map = quantplay_symbol_map
222
+ broker.broker_symbol_map = broker_symbol_map
223
+
224
+ else:
225
+ broker.initialize_broker_symbol_map()
226
+ instrument_cache.set(
227
+ quantplay_symbol_key, broker.quantplay_symbol_map
228
+ )
229
+ instrument_cache.set(broker_symbol_key, broker.broker_symbol_map)
230
+
231
+ return broker
232
+
233
+ try:
234
+ symbol_data = PickleUtils.load_data(
235
+ BrokerFactory.broker_instruments_map[broker_name]
236
+ )
237
+ broker.symbol_data = symbol_data
238
+
239
+ if broker_name != "Zerodha":
240
+ broker.initialize_broker_symbol_map()
241
+ instrument_cache.set(quantplay_symbol_key, broker.quantplay_symbol_map)
242
+
243
+ instrument_cache.set(symbol_data_key, symbol_data)
244
+
245
+ except Exception:
246
+ traceback.print_exc()
247
+
248
+ if broker_name != "Zerodha":
249
+ broker.load_instrument(BrokerFactory.broker_instruments_map[broker_name])
250
+ else:
251
+ broker.initialize_symbol_data()
252
+
253
+ return broker
254
+
217
255
  def clear_instrument_cache(self, broker: str) -> None:
218
256
  symbol_data_key = f"{broker}_instruments"
219
257
  instrument_cache.delete(symbol_data_key)
@@ -4,8 +4,7 @@ import traceback
4
4
  from typing import Any, Dict, Hashable, List
5
5
 
6
6
  import polars as pl
7
- from kiteconnect import KiteConnect, KiteTicker # type: ignore
8
- from kiteconnect.exceptions import TokenException # type: ignore
7
+ from dhanhq import dhanhq # type:ignore
9
8
  from retrying import retry # type: ignore
10
9
 
11
10
  from quantplay.broker.generics.broker import Broker
@@ -15,7 +14,6 @@ from quantplay.exception.exceptions import (
15
14
  RetryableException,
16
15
  retry_exception,
17
16
  )
18
- from quantplay.exception.exceptions import TokenException as QuantplayTokenException
19
17
  from quantplay.model.broker import (
20
18
  ExchangeType,
21
19
  )
@@ -27,11 +25,11 @@ from quantplay.model.generics import (
27
25
  )
28
26
  from quantplay.utils.constant import Constants, OrderType
29
27
  from quantplay.utils.pickle_utils import InstrumentData, PickleUtils
30
- from dhanhq import dhanhq # type:ignore
31
28
 
32
29
 
33
30
  class Dhan(Broker):
34
31
  def __init__(self):
32
+ super().__init__()
35
33
  self.dhan = dhanhq(
36
34
  client_id="1102866282",
37
35
  access_token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJkaGFuIiwicGFydG5lcklkIjoiIiwiZXhwIjoxNzIzODgxNjgxLCJ0b2tlbkNvbnN1bWVyVHlwZSI6IlNFTEYiLCJ3ZWJob29rVXJsIjoiIiwiZGhhbkNsaWVudElkIjoiMTEwMjg2NjI4MiJ9.0dNR4gOdIQ3KeaAokEwbRt6v_6ESn73r6yOL9-7lzphVCAmP-pahgK6OIOxVUExBJa0SaxX0TNX7Vk0RBQ-lxQ",
@@ -41,8 +39,6 @@ class Dhan(Broker):
41
39
  access_token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJkaGFuIiwicGFydG5lcklkIjoiIiwiZXhwIjoxNzIxMzc3ODM5LCJ0b2tlbkNvbnN1bWVyVHlwZSI6IlNFTEYiLCJ3ZWJob29rVXJsIjoiIiwiZGhhbkNsaWVudElkIjoiMTEwMDc5OTExNiJ9.ykd4NYsnl7s1UegkUUY9tbP4OxxjqtskGi8JK0lyC9bRRPQRyxDv022JyDIl6crdFsQXfG7-6BsipPYxOtLR8g",
42
40
  )
43
41
 
44
- super(Dhan, self).__init__()
45
-
46
42
  def set_wrapper(self, serialized_wrapper: str):
47
43
  self.wrapper = pickle.loads(codecs.decode(serialized_wrapper.encode(), "base64"))
48
44
 
@@ -69,33 +65,6 @@ class Dhan(Broker):
69
65
  def get_username(self):
70
66
  return self.username
71
67
 
72
- def on_ticks(self, kws: KiteTicker, ticks: Any):
73
- """Callback on live ticks"""
74
- # logger.info("[TEST_TICK] {}".format(ticks))
75
- pass
76
-
77
- def on_order_update(self, kws: KiteTicker, data: Any):
78
- """Callback on order update"""
79
- Constants.logger.info(f"[UPDATE_RECEIVED] {data}")
80
-
81
- if self.order_updates is None:
82
- raise Exception("Event Queue Not Initalised")
83
-
84
- self.order_updates.put(data)
85
-
86
- def on_connect(self, kws: KiteTicker, response: Any):
87
- """Callback on successfull connect"""
88
- kws.subscribe([256265]) # type: ignore
89
- kws.set_mode(kws.MODE_FULL, [256265]) # type: ignore
90
-
91
- def stream_order_data(self):
92
- kite_ticker = KiteTicker(self.wrapper.api_key, self.wrapper.access_token)
93
- kite_ticker.on_order_update = self.on_order_update # type:ignore
94
- kite_ticker.on_ticks = self.on_ticks # type:ignore
95
- kite_ticker.on_connect = self.on_connect # type:ignore
96
-
97
- kite_ticker.connect(threaded=True) # type: ignore
98
-
99
68
  @retry(
100
69
  wait_exponential_multiplier=3000,
101
70
  wait_exponential_max=10000,
@@ -135,8 +104,6 @@ class Dhan(Broker):
135
104
  )
136
105
 
137
106
  return api_response[key]["last_price"]
138
- except TokenException:
139
- raise QuantplayTokenException("Zerodha token expired")
140
107
  except Exception as e:
141
108
  exception_message = "GetLtp call failed for [{}] with error [{}]".format(
142
109
  tradingsymbol, str(e)
@@ -8,11 +8,12 @@ import urllib.parse
8
8
  from datetime import datetime as dt
9
9
  from time import sleep
10
10
  from typing import Any, Callable, Dict, List, Literal, TypedDict
11
- from quantplay.model.generics import NorenTypes
12
- from quantplay.model.generics import ExchangeType
11
+
13
12
  import requests
14
13
  import websocket
15
14
 
15
+ from quantplay.model.generics import ExchangeType, NorenTypes
16
+
16
17
  logger = logging.getLogger(__name__)
17
18
 
18
19
 
@@ -49,6 +49,7 @@ class FivePaisa(Broker):
49
49
  client: str | None = None,
50
50
  load_instrument: bool = True,
51
51
  ):
52
+ super().__init__()
52
53
  self.broker_name = "FivePaisa_OpenAPI"
53
54
  try:
54
55
  if client:
@@ -96,7 +97,6 @@ class FivePaisa(Broker):
96
97
 
97
98
  if load_instrument:
98
99
  self.load_instrument()
99
- super(FivePaisa, self).__init__()
100
100
 
101
101
  def get_exchange(self, exchange: ExchangeType) -> Any:
102
102
  return exchange
@@ -170,16 +170,14 @@ class FivePaisa(Broker):
170
170
  def add_exchange(self, data: pl.DataFrame):
171
171
  return data.with_columns(
172
172
  pl.lit(None).alias("exchange"),
173
+ ).with_columns(
173
174
  pl.when((pl.col("Exch").eq("N")) & (pl.col("ExchType").eq("D")))
174
175
  .then(pl.lit("NFO"))
175
- .alias("exchange"),
176
- pl.when((pl.col("Exch").eq("N")) & (pl.col("ExchType").eq("C")))
176
+ .when((pl.col("Exch").eq("N")) & (pl.col("ExchType").eq("C")))
177
177
  .then(pl.lit("NFO"))
178
- .alias("exchange"),
179
- pl.when((pl.col("Exch").eq("B")) & (pl.col("ExchType").eq("D")))
178
+ .when((pl.col("Exch").eq("B")) & (pl.col("ExchType").eq("D")))
180
179
  .then(pl.lit("NFO"))
181
- .alias("exchange"),
182
- pl.when((pl.col("Exch").eq("B")) & (pl.col("ExchType").eq("C")))
180
+ .when((pl.col("Exch").eq("B")) & (pl.col("ExchType").eq("C")))
183
181
  .then(pl.lit("NFO"))
184
182
  .alias("exchange"),
185
183
  )
@@ -280,8 +278,7 @@ class FivePaisa(Broker):
280
278
  ).alias("pnl"),
281
279
  )
282
280
 
283
- self.add_exchange(positions)
284
-
281
+ positions = self.add_exchange(positions)
285
282
  positions = positions.with_columns(
286
283
  pl.when(pl.col("exchange").is_in(["NFO", "BFO"]))
287
284
  .then(pl.col("tradingsymbol").str.split(" ").list.get(-2))
@@ -322,8 +319,7 @@ class FivePaisa(Broker):
322
319
  return pl.DataFrame(schema=self.orders_schema)
323
320
 
324
321
  orders = pl.from_dicts(orders)
325
-
326
- self.add_exchange(orders)
322
+ orders = self.add_exchange(orders)
327
323
 
328
324
  orders = orders.rename(
329
325
  {
@@ -386,12 +382,12 @@ class FivePaisa(Broker):
386
382
  )
387
383
  .with_columns(
388
384
  pl.when(pl.col("status").str.to_lowercase().str.contains("rejected"))
389
- .then(OrderStatus.rejected)
385
+ .then(pl.lit(OrderStatus.rejected))
390
386
  .otherwise(pl.col("status"))
391
387
  .alias("status"),
392
388
  pl.when(
393
- pl.col("product")
394
- == "CNC" & (pl.col("exchange").is_in(["NFO", "BFO"]))
389
+ (pl.col("product").eq("CNC"))
390
+ & (pl.col("exchange").is_in(["NFO", "BFO"]))
395
391
  )
396
392
  .then(pl.lit("NRML"))
397
393
  .otherwise(pl.col("product"))
@@ -399,7 +395,7 @@ class FivePaisa(Broker):
399
395
  )
400
396
  .with_columns(
401
397
  pl.when((pl.col("status") == "OPEN") & (pl.col("order_type") == "SL"))
402
- .then(OrderStatus.trigger_pending)
398
+ .then(pl.lit(OrderStatus.trigger_pending))
403
399
  .otherwise(pl.col("status"))
404
400
  .alias("status")
405
401
  )
@@ -81,9 +81,9 @@ class FlatTrade(Noren):
81
81
  "request_code": reqCode,
82
82
  "api_secret": hashlib.sha256(secret_code.encode()).hexdigest(),
83
83
  }
84
- url3 = "https://authapi.flattrade.in/trade/apitoken"
84
+ url = "https://authapi.flattrade.in/trade/apitoken"
85
85
 
86
- res3 = requests.post(url3, json=payload)
87
- token = res3.json()["token"]
86
+ res = requests.post(url, json=payload)
87
+ token = res.json()["token"]
88
88
 
89
89
  return token
@@ -8,11 +8,12 @@ import urllib.parse
8
8
  from datetime import datetime as dt
9
9
  from time import sleep
10
10
  from typing import Any, Callable, Dict, List, Literal, TypedDict
11
- from quantplay.model.generics import NorenTypes
12
- from quantplay.model.generics import ExchangeType
11
+
13
12
  import requests
14
13
  import websocket
15
14
 
15
+ from quantplay.model.generics import ExchangeType, NorenTypes
16
+
16
17
  logger = logging.getLogger(__name__)
17
18
 
18
19