quantplay 2.0.42__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.42 → quantplay-2.0.43}/PKG-INFO +26 -1
  2. {quantplay-2.0.42 → quantplay-2.0.43}/pyproject.toml +1 -1
  3. quantplay-2.0.43/quantplay/broker/__init__.py +25 -0
  4. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/aliceblue.py +13 -4
  5. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/angelone.py +6 -3
  6. {quantplay-2.0.42/quantplay/broker/generics → quantplay-2.0.43/quantplay/broker}/broker_factory.py +107 -69
  7. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/dhan.py +2 -35
  8. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/finvasia_utils/fa_noren.py +3 -2
  9. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/five_paisa.py +1 -1
  10. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/flattrade.py +3 -3
  11. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/ft_utils/ft_noren.py +3 -2
  12. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/motilal.py +16 -15
  13. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/noren.py +7 -3
  14. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/upstox.py +3 -3
  15. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/xts.py +1 -1
  16. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/xts_utils/Connect.py +1 -2
  17. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/xts_utils/InteractiveSocketClient.py +1 -0
  18. {quantplay-2.0.42 → 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.42 → quantplay-2.0.43}/quantplay/model/instrument_data.py +2 -0
  21. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/wrapper/aws/s3.py +4 -3
  22. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay.egg-info/PKG-INFO +26 -1
  23. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay.egg-info/SOURCES.txt +1 -1
  24. {quantplay-2.0.42 → quantplay-2.0.43}/setup.py +1 -1
  25. quantplay-2.0.42/quantplay/exception/exceptions.py +0 -114
  26. quantplay-2.0.42/tests/wrapper/aws/__init__.py +0 -0
  27. {quantplay-2.0.42 → quantplay-2.0.43}/README.md +0 -0
  28. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/__init__.py +0 -0
  29. {quantplay-2.0.42/quantplay/broker → quantplay-2.0.43/quantplay/broker/auto_login}/__init__.py +0 -0
  30. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/auto_login/aliceblue.py +1 -1
  31. {quantplay-2.0.42/quantplay/broker/auto_login → quantplay-2.0.43/quantplay/broker/finvasia_utils}/__init__.py +0 -0
  32. {quantplay-2.0.42/quantplay/broker/finvasia_utils → quantplay-2.0.43/quantplay/broker/ft_utils}/__init__.py +0 -0
  33. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  34. {quantplay-2.0.42/quantplay/broker/ft_utils → quantplay-2.0.43/quantplay/broker/generics}/__init__.py +0 -0
  35. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/generics/broker.py +2 -2
  36. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/iifl_xts.py +0 -0
  37. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/kite_utils.py +0 -0
  38. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/shoonya.py +0 -0
  39. {quantplay-2.0.42/quantplay/broker/generics → quantplay-2.0.43/quantplay/broker/uplink}/__init__.py +0 -0
  40. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/uplink/uplink_utils.py +0 -0
  41. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/broker/xts_utils/Exception.py +0 -0
  42. {quantplay-2.0.42/quantplay/broker/uplink → quantplay-2.0.43/quantplay/broker/xts_utils}/__init__.py +0 -0
  43. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/exception/__init__.py +0 -0
  44. {quantplay-2.0.42/quantplay/broker/xts_utils → quantplay-2.0.43/quantplay/model}/__init__.py +0 -0
  45. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/model/broker.py +0 -0
  46. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/model/generics.py +0 -0
  47. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/model/order_event.py +0 -0
  48. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/py.typed +0 -0
  49. {quantplay-2.0.42/quantplay/model → quantplay-2.0.43/quantplay/utils}/__init__.py +0 -0
  50. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/utils/caching.py +0 -0
  51. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/utils/constant.py +0 -0
  52. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/utils/exchange.py +0 -0
  53. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/utils/number_utils.py +0 -0
  54. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/utils/pickle_utils.py +1 -1
  55. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay/utils/selenium_utils.py +0 -0
  56. {quantplay-2.0.42/quantplay/utils → quantplay-2.0.43/quantplay/wrapper}/__init__.py +0 -0
  57. {quantplay-2.0.42/quantplay/wrapper → quantplay-2.0.43/quantplay/wrapper/aws}/__init__.py +0 -0
  58. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay.egg-info/dependency_links.txt +0 -0
  59. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay.egg-info/requires.txt +0 -0
  60. {quantplay-2.0.42 → quantplay-2.0.43}/quantplay.egg-info/top_level.txt +0 -0
  61. {quantplay-2.0.42 → quantplay-2.0.43}/setup.cfg +0 -0
  62. {quantplay-2.0.42/quantplay/wrapper/aws → quantplay-2.0.43/tests}/__init__.py +0 -0
  63. {quantplay-2.0.42 → quantplay-2.0.43}/tests/conftest.py +0 -0
  64. {quantplay-2.0.42/tests → quantplay-2.0.43/tests/wrapper}/__init__.py +0 -0
  65. {quantplay-2.0.42/tests/wrapper → quantplay-2.0.43/tests/wrapper/aws}/__init__.py +0 -0
  66. {quantplay-2.0.42 → 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.42
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
@@ -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
 
@@ -1,11 +1,23 @@
1
+ import binascii
1
2
  import copy
2
3
  import hashlib
4
+ import json
3
5
  from queue import Queue
4
6
  from typing import Any, Dict
5
- import requests
6
- import json
7
+
7
8
  import polars as pl
9
+ import pyotp
10
+ import requests
11
+ from retrying import retry # type: ignore
8
12
 
13
+ from quantplay.broker.generics.broker import Broker
14
+ from quantplay.exception.exceptions import (
15
+ InvalidArgumentException,
16
+ QuantplayOrderPlacementException,
17
+ RetryableException,
18
+ TokenException,
19
+ retry_exception,
20
+ )
9
21
  from quantplay.model.broker import UserBrokerProfileResponse
10
22
  from quantplay.model.generics import (
11
23
  ExchangeType,
@@ -15,18 +27,7 @@ from quantplay.model.generics import (
15
27
  )
16
28
  from quantplay.model.order_event import OrderUpdateEvent
17
29
  from quantplay.utils.constant import Constants, OrderType
18
- from quantplay.broker.generics.broker import Broker
19
- from quantplay.exception.exceptions import InvalidArgumentException
20
- import pyotp
21
- import binascii
22
30
  from quantplay.utils.pickle_utils import InstrumentData
23
- from quantplay.exception.exceptions import (
24
- QuantplayOrderPlacementException,
25
- TokenException,
26
- retry_exception,
27
- RetryableException,
28
- )
29
- from retrying import retry # type: ignore
30
31
  from quantplay.wrapper.aws.s3 import S3Utils
31
32
 
32
33
 
@@ -74,7 +75,7 @@ class Motilal(Broker):
74
75
  totp: str | None = None,
75
76
  order_updates: Queue[OrderUpdateEvent] | None = None,
76
77
  ):
77
- super(Motilal, self).__init__()
78
+ super().__init__()
78
79
  self.order_updates = order_updates
79
80
 
80
81
  self.instrument_data_by_exchange = {}
@@ -339,7 +340,7 @@ class Motilal(Broker):
339
340
  ).json()
340
341
  Constants.logger.info("[MODIFY_ORDER_RESPONSE] {}".format(response))
341
342
  except Exception as e:
342
- exception_message = f"[ORDER_MODIFICATION_FAILED] for {data["uniqueorderid"]} failed with exception {e}"
343
+ exception_message = f"[ORDER_MODIFICATION_FAILED] for {data['uniqueorderid']} failed with exception {e}"
343
344
  Constants.logger.error("{}".format(exception_message))
344
345
  return order["order_id"]
345
346
 
@@ -23,8 +23,12 @@ from quantplay.model.broker import (
23
23
  ModifyOrderRequest,
24
24
  UserBrokerProfileResponse,
25
25
  )
26
- from quantplay.model.generics import OrderTypeType, ProductType, TransactionType
27
- from quantplay.model.generics import NorenTypes
26
+ from quantplay.model.generics import (
27
+ NorenTypes,
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.pickle_utils import InstrumentData
@@ -39,7 +43,7 @@ class Noren(Broker):
39
43
  load_instrument: bool = True,
40
44
  order_updates: Queue[OrderUpdateEvent] | None = None,
41
45
  ):
42
- super(Noren, self).__init__()
46
+ super().__init__()
43
47
 
44
48
  self.order_updates = order_updates
45
49
 
@@ -49,6 +49,8 @@ class Upstox(Broker):
49
49
  redirect_url: str | None = None,
50
50
  load_instrument: bool = True,
51
51
  ):
52
+ super().__init__()
53
+
52
54
  try:
53
55
  if access_token:
54
56
  self.set_access_token(access_token)
@@ -83,8 +85,6 @@ class Upstox(Broker):
83
85
  if load_instrument:
84
86
  self.load_instrument()
85
87
 
86
- super(Upstox, self).__init__()
87
-
88
88
  def load_instrument(self, file_name: str | None = None) -> None:
89
89
  super().load_instrument("upstox_instruments")
90
90
 
@@ -192,7 +192,7 @@ class Upstox(Broker):
192
192
  )
193
193
 
194
194
  Constants.logger.info(
195
- f"Modifying order [{ order["order_id"]}] new price [{order.get("price")}]"
195
+ f"Modifying order [{ order['order_id']}] new price [{order.get('price')}]"
196
196
  )
197
197
  return order["order_id"]
198
198
 
@@ -47,7 +47,7 @@ class XTS(Broker):
47
47
  ClientID: str | None = None,
48
48
  load_instrument: bool = True,
49
49
  ):
50
- super(XTS, self).__init__()
50
+ super().__init__()
51
51
  self.order_updates: Queue[OrderUpdateEvent] | None = order_updates
52
52
  self.root_url = root_url
53
53
 
@@ -12,9 +12,8 @@ import traceback
12
12
  from typing import Any, Dict, List, Literal
13
13
 
14
14
  import requests
15
- import urllib3
16
15
  import requests.adapters
17
-
16
+ import urllib3
18
17
  from six.moves.urllib.parse import urljoin # type:ignore
19
18
 
20
19
  from quantplay.broker.xts_utils import Exception as ex
@@ -1,4 +1,5 @@
1
1
  from typing import Any, Dict, List, Literal
2
+
2
3
  import socketio # type: ignore
3
4
 
4
5
 
@@ -47,6 +47,7 @@ class Zerodha(Broker):
47
47
  totp: str | None = None,
48
48
  load_instrument: bool = True,
49
49
  ):
50
+ super().__init__()
50
51
  self.wrapper: KiteConnect
51
52
  try:
52
53
  if wrapper:
@@ -62,7 +63,6 @@ class Zerodha(Broker):
62
63
  if load_instrument:
63
64
  self.initialize_symbol_data()
64
65
  self.broker_symbol_map = {}
65
- super(Zerodha, self).__init__()
66
66
 
67
67
  def set_wrapper(self, serialized_wrapper: str):
68
68
  self.wrapper = pickle.loads(codecs.decode(serialized_wrapper.encode(), "base64"))
@@ -0,0 +1,100 @@
1
+ class InvalidArgumentException(Exception):
2
+ code = "400"
3
+
4
+ def __init__(self, message: str):
5
+ super().__init__(message)
6
+
7
+
8
+ class DataNotFoundException(Exception):
9
+ code = "404"
10
+
11
+ def __init__(self, message: str):
12
+ super().__init__(message)
13
+
14
+
15
+ class FeatureNotSupported(Exception):
16
+ code = "407"
17
+
18
+ def __init__(self, message: str):
19
+ super().__init__(message)
20
+
21
+
22
+ class AccessDeniedException(Exception):
23
+ code = "403"
24
+
25
+ def __init__(self, message: str):
26
+ super().__init__(message)
27
+
28
+
29
+ class RetryableException(Exception):
30
+ code = "409"
31
+
32
+ def __init__(self, message: str):
33
+ super().__init__(message)
34
+
35
+
36
+ def retry_on_access_denied(exc: Exception):
37
+ return isinstance(exc, AccessDeniedException)
38
+
39
+
40
+ def retry_exception(exc: Exception):
41
+ return isinstance(exc, RetryableException)
42
+
43
+
44
+ class StaleDataFound(Exception):
45
+ code = "101"
46
+
47
+ def __init__(self, message: str):
48
+ super().__init__(message)
49
+
50
+
51
+ class ServiceException(Exception):
52
+ code = "500"
53
+
54
+ def __init__(self, message: str):
55
+ super().__init__(message)
56
+
57
+
58
+ class StockNotListedOnExchange(Exception):
59
+ stocks = []
60
+
61
+ def __init__(self, message: str):
62
+ super().__init__(message)
63
+
64
+
65
+ class QuantplayOrderPlacementException(Exception):
66
+ def __init__(self, message: str):
67
+ super().__init__(message)
68
+
69
+
70
+ class StrategyInvocationException(Exception):
71
+ def __init__(self, message: str):
72
+ super().__init__(message)
73
+
74
+
75
+ class BrokerNotFoundException(Exception):
76
+ code = "404"
77
+
78
+ def __init__(self, message: str):
79
+ super().__init__(message)
80
+
81
+
82
+ class TokenException(Exception):
83
+ code = "404"
84
+
85
+ def __init__(self, message: str):
86
+ super().__init__(message)
87
+
88
+
89
+ class WrongLibrarySetup(Exception):
90
+ code = "501"
91
+
92
+ def __init__(self, message: str):
93
+ super().__init__(message)
94
+
95
+
96
+ class BrokerException(Exception):
97
+ code = "510"
98
+
99
+ def __init__(self, message: str):
100
+ super().__init__(message)
@@ -1,5 +1,7 @@
1
1
  from typing import TypedDict
2
+
2
3
  from typing_extensions import NotRequired
4
+
3
5
  from quantplay.model.generics import ExchangeType
4
6
 
5
7
 
@@ -1,11 +1,12 @@
1
+ import os
2
+ from threading import Lock
3
+
1
4
  import boto3
2
5
  import pandas as pd
3
- import os
4
6
  from boto3.s3.transfer import TransferConfig
5
- from threading import Lock
6
- from quantplay.utils.constant import Constants
7
7
  from retrying import retry # type: ignore
8
8
 
9
+ from quantplay.utils.constant import Constants
9
10
 
10
11
  lock = Lock()
11
12
 
@@ -1,11 +1,36 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantplay
3
- Version: 2.0.42
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
 
@@ -11,6 +11,7 @@ quantplay.egg-info/top_level.txt
11
11
  quantplay/broker/__init__.py
12
12
  quantplay/broker/aliceblue.py
13
13
  quantplay/broker/angelone.py
14
+ quantplay/broker/broker_factory.py
14
15
  quantplay/broker/dhan.py
15
16
  quantplay/broker/five_paisa.py
16
17
  quantplay/broker/flattrade.py
@@ -31,7 +32,6 @@ quantplay/broker/ft_utils/flattrade_utils.py
31
32
  quantplay/broker/ft_utils/ft_noren.py
32
33
  quantplay/broker/generics/__init__.py
33
34
  quantplay/broker/generics/broker.py
34
- quantplay/broker/generics/broker_factory.py
35
35
  quantplay/broker/uplink/__init__.py
36
36
  quantplay/broker/uplink/uplink_utils.py
37
37
  quantplay/broker/xts_utils/Connect.py
@@ -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.42",
24
+ version="2.0.43",
25
25
  setup_requires=["pytest-runner"],
26
26
  install_requires=requirements,
27
27
  tests_require=[],
@@ -1,114 +0,0 @@
1
- class InvalidArgumentException(Exception):
2
- code = "400"
3
-
4
- def __init__(self, message: str):
5
- # Call the base class constructor with the parameters it needs
6
- super(InvalidArgumentException, self).__init__(message)
7
-
8
-
9
- class DataNotFoundException(Exception):
10
- code = "404"
11
-
12
- def __init__(self, message: str):
13
- # Call the base class constructor with the parameters it needs
14
- super(DataNotFoundException, self).__init__(message)
15
-
16
-
17
- class FeatureNotSupported(Exception):
18
- code = "407"
19
-
20
- def __init__(self, message: str):
21
- # Call the base class constructor with the parameters it needs
22
- super(FeatureNotSupported, self).__init__(message)
23
-
24
-
25
- class AccessDeniedException(Exception):
26
- code = "403"
27
-
28
- def __init__(self, message: str):
29
- # Call the base class constructor with the parameters it needs
30
- super(AccessDeniedException, self).__init__(message)
31
-
32
-
33
- class RetryableException(Exception):
34
- code = "409"
35
-
36
- def __init__(self, message: str):
37
- # Call the base class constructor with the parameters it needs
38
- super(RetryableException, self).__init__(message)
39
-
40
-
41
- def retry_on_access_denied(exc: Exception):
42
- return isinstance(exc, AccessDeniedException)
43
-
44
-
45
- def retry_exception(exc: Exception):
46
- return isinstance(exc, RetryableException)
47
-
48
-
49
- class StaleDataFound(Exception):
50
- code = "101"
51
-
52
- def __init__(self, message: str):
53
- # Call the base class constructor with the parameters it needs
54
- super(StaleDataFound, self).__init__(message)
55
-
56
-
57
- class ServiceException(Exception):
58
- code = "500"
59
-
60
- def __init__(self, message: str):
61
- # Call the base class constructor with the parameters it needs
62
- super(ServiceException, self).__init__(message)
63
-
64
-
65
- class StockNotListedOnExchange(Exception):
66
- stocks = []
67
-
68
- def __init__(self, message: str):
69
- # Call the base class constructor with the parameters it needs
70
- super(StockNotListedOnExchange, self).__init__(message)
71
-
72
-
73
- class QuantplayOrderPlacementException(Exception):
74
- def __init__(self, message: str):
75
- # Call the base class constructor with the parameters it needs
76
- super(QuantplayOrderPlacementException, self).__init__(message)
77
-
78
-
79
- class StrategyInvocationException(Exception):
80
- def __init__(self, message: str):
81
- # Call the base class constructor with the parameters it needs
82
- super(StrategyInvocationException, self).__init__(message)
83
-
84
-
85
- class BrokerNotFoundException(Exception):
86
- code = "404"
87
-
88
- def __init__(self, message: str):
89
- # Call the base class constructor with the parameters it needs
90
- super(BrokerNotFoundException, self).__init__(message)
91
-
92
-
93
- class TokenException(Exception):
94
- code = "404"
95
-
96
- def __init__(self, message: str):
97
- # Call the base class constructor with the parameters it needs
98
- super(TokenException, self).__init__(message)
99
-
100
-
101
- class WrongLibrarySetup(Exception):
102
- code = "501"
103
-
104
- def __init__(self, message: str):
105
- # Call the base class constructor with the parameters it needs
106
- super(WrongLibrarySetup, self).__init__(message)
107
-
108
-
109
- class BrokerException(Exception):
110
- code = "510"
111
-
112
- def __init__(self, message: str):
113
- # Call the base class constructor with the parameters it needs
114
- super(BrokerException, self).__init__(message)
File without changes
File without changes
@@ -5,6 +5,7 @@ import traceback
5
5
  import pyotp
6
6
  from retrying import retry # type: ignore
7
7
  from selenium.common.exceptions import NoSuchElementException, WebDriverException
8
+ from selenium.webdriver import Chrome
8
9
 
9
10
  from quantplay.exception.exceptions import (
10
11
  BrokerException,
@@ -12,7 +13,6 @@ from quantplay.exception.exceptions import (
12
13
  RetryableException,
13
14
  )
14
15
  from quantplay.utils.selenium_utils import Selenium
15
- from selenium.webdriver import Chrome
16
16
 
17
17
 
18
18
  class AliceblueLogin:
@@ -1,4 +1,3 @@
1
- from abc import ABC, abstractmethod
2
1
  import copy
3
2
  import io
4
3
  import json
@@ -11,6 +10,7 @@ import threading
11
10
  import time
12
11
  import traceback
13
12
  import zipfile
13
+ from abc import ABC, abstractmethod
14
14
  from datetime import datetime, timedelta
15
15
  from queue import Queue
16
16
  from threading import Lock
@@ -32,10 +32,10 @@ from quantplay.model.broker import (
32
32
  UserBrokerProfileResponse,
33
33
  )
34
34
  from quantplay.model.generics import (
35
+ OrderTypeType,
35
36
  ProductType,
36
37
  QuantplayOrder,
37
38
  TransactionType,
38
- OrderTypeType,
39
39
  )
40
40
  from quantplay.model.instrument_data import InstrumentDataType
41
41
  from quantplay.model.order_event import OrderUpdateEvent
@@ -1,6 +1,6 @@
1
1
  import pickle
2
- from typing import Any, Dict
3
2
  from threading import Lock
3
+ from typing import Any, Dict
4
4
 
5
5
  from quantplay.model.instrument_data import InstrumentDataType
6
6
 
File without changes
File without changes