quantplay 2.1.65__tar.gz → 2.1.67__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.
- {quantplay-2.1.65 → quantplay-2.1.67}/PKG-INFO +1 -1
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/angelone_utils/angeloneWS.py +2 -1
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/broker_factory.py +2 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/kotak.py +141 -21
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/kotak_utils/kotak_ws.py +49 -15
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/kotak_utils/kotak_ws_lib.py +15 -8
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay.egg-info/PKG-INFO +1 -1
- {quantplay-2.1.65 → quantplay-2.1.67}/setup.py +1 -1
- {quantplay-2.1.65 → quantplay-2.1.67}/README.md +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/pyproject.toml +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/aliceblue.py +2 -2
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/angelone.py +1 -1
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/angelone_utils/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/auto_login/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/auto_login/aliceblue.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/breeze/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/breeze/breeze_utils.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/dhan.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/finvasia_utils/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/five_paisa.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/flattrade.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/ft_utils/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/ft_utils/ft_noren.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/generics/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/generics/broker.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/icici_direct.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/iifl_xts.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/jainam_xts.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/kite_utils.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/kotak_utils/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/motilal.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/noren.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/shoonya.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/uplink/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/uplink/uplink_utils.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/upstox.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/xts.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/xts_utils/Connect.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/xts_utils/Exception.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/xts_utils/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/xts_utils_v2/ConnectV2.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/xts_utils_v2/InteractiveSocketClientV2.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/xts_utils_v2/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/zerodha.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/core/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/core/strategy.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/exception/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/exception/exceptions.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/indicator/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/indicator/iv.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/model/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/model/broker.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/model/broker_response.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/model/generics.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/model/instrument_data.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/model/order_event.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/py.typed +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/strategy/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/strategy/iv_spike.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/strategy/obuy.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/utils/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/utils/caching.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/utils/constant.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/utils/exchange.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/utils/number_utils.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/utils/pickle_utils.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/utils/selenium_utils.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/wrapper/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/wrapper/aws/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/wrapper/aws/s3.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay/wrapper/redis.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay.egg-info/SOURCES.txt +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay.egg-info/dependency_links.txt +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay.egg-info/requires.txt +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/quantplay.egg-info/top_level.txt +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/setup.cfg +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/tests/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/tests/conftest.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/tests/wrapper/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/tests/wrapper/aws/__init__.py +0 -0
- {quantplay-2.1.65 → quantplay-2.1.67}/tests/wrapper/aws/s3_test.py +0 -0
|
@@ -187,6 +187,8 @@ class BrokerFactory:
|
|
|
187
187
|
consumer_secret=broker_data["consumer_secret"],
|
|
188
188
|
mobilenumber=broker_data["mobilenumber"],
|
|
189
189
|
password=broker_data["password"],
|
|
190
|
+
totp=broker_data.get("totp"),
|
|
191
|
+
mpin=broker_data.get("mpin"),
|
|
190
192
|
otp=broker_data.get("otp"),
|
|
191
193
|
load_instrument=False,
|
|
192
194
|
)
|
|
@@ -7,6 +7,7 @@ from urllib.parse import urlencode
|
|
|
7
7
|
|
|
8
8
|
import jwt
|
|
9
9
|
import polars as pl
|
|
10
|
+
import pyotp
|
|
10
11
|
import requests
|
|
11
12
|
import shortuuid # type:ignore
|
|
12
13
|
|
|
@@ -48,6 +49,8 @@ class Kotak(Broker):
|
|
|
48
49
|
consumer_secret: str | None = None,
|
|
49
50
|
mobilenumber: str | None = None,
|
|
50
51
|
password: str | None = None,
|
|
52
|
+
totp: str | None = None,
|
|
53
|
+
mpin: str | None = None,
|
|
51
54
|
otp: str | None = None,
|
|
52
55
|
configuration: dict[str, str] | None = None,
|
|
53
56
|
load_instrument: bool = True,
|
|
@@ -55,28 +58,39 @@ class Kotak(Broker):
|
|
|
55
58
|
) -> None:
|
|
56
59
|
super().__init__()
|
|
57
60
|
|
|
58
|
-
self.configuration: dict[str, str | None] = {
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
+
self.configuration: dict[str, str | None] = {}
|
|
62
|
+
self.version: Literal["NEW", "OLD"]
|
|
61
63
|
|
|
62
64
|
if configuration:
|
|
63
65
|
self.configuration = {
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
|
|
71
|
-
"edit_rid": configuration.get("edit_rid"),
|
|
72
|
-
"serverId": configuration.get("serverId"),
|
|
66
|
+
"Authorization": self.configuration.get(
|
|
67
|
+
"Authorization", f"Bearer {configuration.get('bearer_token')}"
|
|
68
|
+
),
|
|
69
|
+
"Sid": self.configuration.get("Sid", configuration.get("edit_sid")),
|
|
70
|
+
"Auth": self.configuration.get("Auth", configuration.get("edit_token")),
|
|
71
|
+
"serverId": self.configuration.get("serverId"),
|
|
72
|
+
**configuration,
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
if verify_config:
|
|
76
76
|
self.margins() # To Verify Configuration
|
|
77
77
|
|
|
78
78
|
elif consumer_key and consumer_secret and mobilenumber and password:
|
|
79
|
-
|
|
79
|
+
if totp and mpin:
|
|
80
|
+
self.login_v2(
|
|
81
|
+
consumer_key,
|
|
82
|
+
consumer_secret,
|
|
83
|
+
mobilenumber,
|
|
84
|
+
password,
|
|
85
|
+
user_id,
|
|
86
|
+
totp,
|
|
87
|
+
mpin,
|
|
88
|
+
)
|
|
89
|
+
self.version = "NEW"
|
|
90
|
+
|
|
91
|
+
else:
|
|
92
|
+
self.login(consumer_key, consumer_secret, mobilenumber, password)
|
|
93
|
+
self.version = "OLD"
|
|
80
94
|
|
|
81
95
|
if otp:
|
|
82
96
|
self.verify_2fa(otp)
|
|
@@ -106,6 +120,99 @@ class Kotak(Broker):
|
|
|
106
120
|
|
|
107
121
|
self.initialize_broker_symbol_map()
|
|
108
122
|
|
|
123
|
+
def login_v2(
|
|
124
|
+
self,
|
|
125
|
+
consumer_key: str,
|
|
126
|
+
consumer_secret: str,
|
|
127
|
+
mobilenumber: str,
|
|
128
|
+
password: str,
|
|
129
|
+
user_id: str,
|
|
130
|
+
totp: str,
|
|
131
|
+
mpin: str,
|
|
132
|
+
) -> None:
|
|
133
|
+
# *** Generate Authorization Token via converting consumer_key and consumer_secret into base64 ***
|
|
134
|
+
|
|
135
|
+
base64_string = str(consumer_key) + ":" + str(consumer_secret)
|
|
136
|
+
base64_token = base64_string.encode("ascii")
|
|
137
|
+
|
|
138
|
+
base64_bytes = base64.b64encode(base64_token)
|
|
139
|
+
final_base64_token = base64_bytes.decode("ascii")
|
|
140
|
+
|
|
141
|
+
# *** Generate Access Token ***
|
|
142
|
+
|
|
143
|
+
session_init = requests.post(
|
|
144
|
+
url=f"{SESSION_PROD_BASE_URL}oauth2/token",
|
|
145
|
+
headers={
|
|
146
|
+
"Authorization": "Basic " + final_base64_token,
|
|
147
|
+
"Content-Type": "application/json",
|
|
148
|
+
},
|
|
149
|
+
data=json.dumps({"grant_type": "client_credentials"}),
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
if not session_init.ok:
|
|
153
|
+
raise InvalidArgumentException(json.loads(session_init.content))
|
|
154
|
+
|
|
155
|
+
json_resp = json.loads(session_init.text)
|
|
156
|
+
self.configuration["Authorization"] = f"Bearer {json_resp.get('access_token')}"
|
|
157
|
+
|
|
158
|
+
# *** Generate View Token ***
|
|
159
|
+
|
|
160
|
+
view_token_resp = requests.post(
|
|
161
|
+
url=f"{PROD_BASE_URL}login/1.0/login/v6/totp/login",
|
|
162
|
+
headers={
|
|
163
|
+
"Authorization": self.configuration["Authorization"],
|
|
164
|
+
"neo-fin-key": "neotradeapi",
|
|
165
|
+
"Content-Type": "application/json",
|
|
166
|
+
},
|
|
167
|
+
data=json.dumps(
|
|
168
|
+
{
|
|
169
|
+
"mobileNumber": mobilenumber,
|
|
170
|
+
"ucc": user_id,
|
|
171
|
+
"totp": pyotp.TOTP(str(totp)).now(),
|
|
172
|
+
}
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
view_token = json.loads(view_token_resp.text)
|
|
176
|
+
|
|
177
|
+
view_token_val = view_token.get("data").get("token")
|
|
178
|
+
sid = view_token.get("data").get("sid")
|
|
179
|
+
|
|
180
|
+
# *** Generate Final Login Token ***
|
|
181
|
+
|
|
182
|
+
generate_otp_resp = requests.post(
|
|
183
|
+
url=f"{PROD_BASE_URL}login/1.0/login/v6/totp/validate",
|
|
184
|
+
headers={
|
|
185
|
+
"accept": "application/json",
|
|
186
|
+
"sid": sid,
|
|
187
|
+
"Auth": view_token_val,
|
|
188
|
+
"neo-fin-key": "neotradeapi",
|
|
189
|
+
"Content-Type": "application/json",
|
|
190
|
+
"Authorization": self.configuration["Authorization"],
|
|
191
|
+
},
|
|
192
|
+
data=json.dumps(
|
|
193
|
+
{
|
|
194
|
+
"mobileNumber": mobilenumber,
|
|
195
|
+
"mpin": mpin,
|
|
196
|
+
}
|
|
197
|
+
),
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
login_resp = json.loads(generate_otp_resp.text)["data"]
|
|
201
|
+
|
|
202
|
+
if login_resp["status"] != "success":
|
|
203
|
+
raise TokenException("Kotak Failed to Login")
|
|
204
|
+
|
|
205
|
+
self.configuration = {
|
|
206
|
+
"Authorization": self.configuration["Authorization"],
|
|
207
|
+
"Sid": login_resp["sid"],
|
|
208
|
+
"Auth": login_resp["token"],
|
|
209
|
+
"serverId": login_resp["hsServerId"],
|
|
210
|
+
"dataCenter": login_resp["dataCenter"],
|
|
211
|
+
# "ucc": login_resp["ucc"],
|
|
212
|
+
# "kId": login_resp["kId"],
|
|
213
|
+
# "kType": login_resp["kType"],
|
|
214
|
+
}
|
|
215
|
+
|
|
109
216
|
def login(
|
|
110
217
|
self,
|
|
111
218
|
consumer_key: str,
|
|
@@ -188,7 +295,16 @@ class Kotak(Broker):
|
|
|
188
295
|
self.configuration["edit_sid"] = edit_token_resp.get("data").get("sid")
|
|
189
296
|
self.configuration["edit_rid"] = edit_token_resp.get("data").get("rid")
|
|
190
297
|
self.configuration["serverId"] = edit_token_resp.get("data").get("hsServerId")
|
|
191
|
-
self.user_id = edit_token_resp.get("data").get("ucc")
|
|
298
|
+
# self.user_id = edit_token_resp.get("data").get("ucc")
|
|
299
|
+
|
|
300
|
+
self.configuration = {
|
|
301
|
+
"Authorization": self.configuration.get(
|
|
302
|
+
"Authorization", f"Bearer {self.configuration['bearer_token']}"
|
|
303
|
+
),
|
|
304
|
+
"Sid": self.configuration.get("Sid", self.configuration["edit_sid"]),
|
|
305
|
+
"Auth": self.configuration.get("Auth", self.configuration["edit_token"]),
|
|
306
|
+
"serverId": self.configuration["serverId"],
|
|
307
|
+
}
|
|
192
308
|
|
|
193
309
|
def order_history(self, order_id: str) -> pl.DataFrame:
|
|
194
310
|
body = {"nOrdNo": order_id}
|
|
@@ -770,10 +886,10 @@ class Kotak(Broker):
|
|
|
770
886
|
url = f"{PROD_BASE_URL}{url}"
|
|
771
887
|
|
|
772
888
|
request_headers = {
|
|
773
|
-
"Authorization":
|
|
774
|
-
"Sid": self.configuration["
|
|
775
|
-
"Auth": self.configuration["
|
|
776
|
-
"neo-fin-key":
|
|
889
|
+
"Authorization": self.configuration["Authorization"],
|
|
890
|
+
"Sid": self.configuration["Sid"],
|
|
891
|
+
"Auth": self.configuration["Auth"],
|
|
892
|
+
"neo-fin-key": "neotradeapi",
|
|
777
893
|
"Content-Type": content_type,
|
|
778
894
|
"accept": "application/json",
|
|
779
895
|
}
|
|
@@ -882,11 +998,15 @@ class Kotak(Broker):
|
|
|
882
998
|
if self.order_updates:
|
|
883
999
|
self.order_updates.put(quantplay_order)
|
|
884
1000
|
|
|
885
|
-
def stream_order_data(self):
|
|
1001
|
+
def stream_order_data(self) -> None:
|
|
886
1002
|
ws = NeoWebSocket(
|
|
887
|
-
sid=self.configuration.get("sid", ""),
|
|
888
|
-
token=self.configuration.get(
|
|
1003
|
+
sid=self.configuration.get("Sid", self.configuration.get("sid", "")),
|
|
1004
|
+
token=self.configuration.get(
|
|
1005
|
+
"Auth", self.configuration.get("edit_token", "")
|
|
1006
|
+
),
|
|
889
1007
|
server_id=self.configuration.get("serverId", ""),
|
|
1008
|
+
data_center=self.configuration.get("dataCenter"),
|
|
1009
|
+
version=self.version,
|
|
890
1010
|
)
|
|
891
1011
|
ws.on_message = self.event_handler_order_update
|
|
892
1012
|
ws.on_error = lambda x: print(f"[KOTAK_WS_ERROR]: {self.user_id} {x}")
|
|
@@ -2,29 +2,46 @@ import json
|
|
|
2
2
|
import threading
|
|
3
3
|
import time
|
|
4
4
|
from collections.abc import Callable
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any, Literal
|
|
6
6
|
|
|
7
7
|
from retrying import retry # type: ignore
|
|
8
8
|
|
|
9
9
|
from quantplay.broker.kotak_utils.kotak_ws_lib import HSIWebSocket
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
OLD_ORDER_FEED_URL = "wss://clhsi.kotaksecurities.com/realtime?sId={server_id}"
|
|
12
|
+
|
|
13
|
+
ORDER_FEED_URL = "wss://mis.kotaksecurities.com/realtime"
|
|
14
|
+
ORDER_FEED_URL_ADC = "wss://cis.kotaksecurities.com/realtime"
|
|
15
|
+
ORDER_FEED_URL_E21 = "wss://e21.kotaksecurities.com/realtime"
|
|
16
|
+
ORDER_FEED_URL_E22 = "wss://e22.kotaksecurities.com/realtime"
|
|
17
|
+
ORDER_FEED_URL_E41 = "wss://e41.kotaksecurities.com/realtime"
|
|
18
|
+
ORDER_FEED_URL_E43 = "wss://e43.kotaksecurities.com/realtime"
|
|
12
19
|
|
|
13
20
|
|
|
14
21
|
class NeoWebSocket:
|
|
15
|
-
def __init__(
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
sid: str | None,
|
|
25
|
+
token: str | None,
|
|
26
|
+
server_id: str | None,
|
|
27
|
+
data_center: str | None,
|
|
28
|
+
version: Literal["OLD", "NEW"],
|
|
29
|
+
) -> None:
|
|
16
30
|
self.hsiWebsocket = None
|
|
17
31
|
self.is_hsi_open = 0
|
|
18
32
|
self.sid = sid
|
|
19
33
|
self.access_token = token
|
|
20
34
|
self.server_id = server_id
|
|
35
|
+
self.version: Literal["OLD", "NEW"] = version
|
|
36
|
+
self.data_center = data_center
|
|
37
|
+
|
|
21
38
|
self.on_message: Callable[[Any], None] | None = None
|
|
22
39
|
self.on_error: Callable[[Any], None] | None = None
|
|
23
40
|
self.on_close: Callable[[], None] | None = None
|
|
24
41
|
self.on_open: Callable[[], None] | None = None
|
|
25
42
|
self.hsi_thread = None
|
|
26
43
|
|
|
27
|
-
def on_hsi_open(self):
|
|
44
|
+
def on_hsi_open(self) -> None:
|
|
28
45
|
server = "WEB"
|
|
29
46
|
json_d = {
|
|
30
47
|
"type": "CONNECTION",
|
|
@@ -34,7 +51,7 @@ class NeoWebSocket:
|
|
|
34
51
|
}
|
|
35
52
|
json_d = json.dumps(json_d)
|
|
36
53
|
|
|
37
|
-
print(f"[KOTAK_OPEN_SEND]: {json_d}")
|
|
54
|
+
# print(f"[KOTAK_OPEN_SEND]: {json_d}")
|
|
38
55
|
|
|
39
56
|
if self.hsiWebsocket:
|
|
40
57
|
self.hsiWebsocket.send(json_d)
|
|
@@ -42,7 +59,7 @@ class NeoWebSocket:
|
|
|
42
59
|
if self.on_open:
|
|
43
60
|
self.on_open()
|
|
44
61
|
|
|
45
|
-
def on_hsi_close(self):
|
|
62
|
+
def on_hsi_close(self) -> None:
|
|
46
63
|
if self.is_hsi_open == 1:
|
|
47
64
|
self.is_hsi_open = 0
|
|
48
65
|
self.reconnect()
|
|
@@ -55,10 +72,10 @@ class NeoWebSocket:
|
|
|
55
72
|
wait_exponential_max=20000,
|
|
56
73
|
stop_max_attempt_number=5,
|
|
57
74
|
)
|
|
58
|
-
def reconnect(self):
|
|
75
|
+
def reconnect(self) -> None:
|
|
59
76
|
self.start_hsi_websocket()
|
|
60
77
|
|
|
61
|
-
def on_hsi_error(self, error: Any):
|
|
78
|
+
def on_hsi_error(self, error: Any) -> None:
|
|
62
79
|
if self.is_hsi_open == 1:
|
|
63
80
|
self.is_hsi_open = 0
|
|
64
81
|
|
|
@@ -67,7 +84,7 @@ class NeoWebSocket:
|
|
|
67
84
|
else:
|
|
68
85
|
print("Error Occurred in Websocket! Error Message ", error)
|
|
69
86
|
|
|
70
|
-
def on_hsi_message(self, message: Any):
|
|
87
|
+
def on_hsi_message(self, message: Any) -> None:
|
|
71
88
|
if message:
|
|
72
89
|
if isinstance(message, str):
|
|
73
90
|
req = json.loads(message)
|
|
@@ -78,15 +95,32 @@ class NeoWebSocket:
|
|
|
78
95
|
if self.on_message:
|
|
79
96
|
self.on_message({"type": "order_feed", "data": message})
|
|
80
97
|
|
|
81
|
-
def start_hsi_ping_thread(self):
|
|
98
|
+
def start_hsi_ping_thread(self) -> None:
|
|
82
99
|
while self.hsiWebsocket and self.is_hsi_open:
|
|
83
100
|
time.sleep(30)
|
|
84
101
|
payload = {"type": "HB"}
|
|
85
102
|
self.hsiWebsocket.send(json.dumps(payload))
|
|
86
103
|
|
|
87
|
-
def start_hsi_websocket(self):
|
|
88
|
-
|
|
89
|
-
|
|
104
|
+
def start_hsi_websocket(self) -> None:
|
|
105
|
+
if self.version == "NEW":
|
|
106
|
+
url = ORDER_FEED_URL
|
|
107
|
+
|
|
108
|
+
if self.data_center:
|
|
109
|
+
if self.data_center.lower() == "adc":
|
|
110
|
+
url = ORDER_FEED_URL_ADC
|
|
111
|
+
# elif self.data_center.lower() == "e21":
|
|
112
|
+
# url = ORDER_FEED_URL_E21
|
|
113
|
+
# elif self.data_center.lower() == "e22":
|
|
114
|
+
# url = ORDER_FEED_URL_E22
|
|
115
|
+
# elif self.data_center.lower() == "e41":
|
|
116
|
+
# url = ORDER_FEED_URL_E41
|
|
117
|
+
# elif self.data_center.lower() == "e43":
|
|
118
|
+
# url = ORDER_FEED_URL_E43
|
|
119
|
+
|
|
120
|
+
else:
|
|
121
|
+
url = OLD_ORDER_FEED_URL.format(server_id=self.server_id)
|
|
122
|
+
|
|
123
|
+
self.hsiWebsocket = HSIWebSocket(self.version)
|
|
90
124
|
self.hsiWebsocket.open_connection(
|
|
91
125
|
url=url,
|
|
92
126
|
onopen=self.on_hsi_open,
|
|
@@ -95,11 +129,11 @@ class NeoWebSocket:
|
|
|
95
129
|
onerror=self.on_hsi_error,
|
|
96
130
|
)
|
|
97
131
|
|
|
98
|
-
def start_hsi_websocket_thread(self):
|
|
132
|
+
def start_hsi_websocket_thread(self) -> None:
|
|
99
133
|
self.hsi_thread = threading.Thread(target=self.start_hsi_websocket)
|
|
100
134
|
self.hsi_thread.start()
|
|
101
135
|
|
|
102
|
-
def get_order_feed(self):
|
|
136
|
+
def get_order_feed(self) -> None:
|
|
103
137
|
if self.hsiWebsocket is None or self.is_hsi_open == 0:
|
|
104
138
|
self.start_hsi_websocket_thread()
|
|
105
139
|
else:
|
|
@@ -14,7 +14,7 @@ class StartHSIServer:
|
|
|
14
14
|
onmessage: Callable[[Any], None],
|
|
15
15
|
onerror: Callable[[Any], None],
|
|
16
16
|
onclose: Callable[[], None],
|
|
17
|
-
):
|
|
17
|
+
) -> None:
|
|
18
18
|
self.openState = None
|
|
19
19
|
self.readyState = None
|
|
20
20
|
self.url = url
|
|
@@ -39,15 +39,17 @@ class StartHSIServer:
|
|
|
39
39
|
except Exception:
|
|
40
40
|
print("WebSocket not supported!")
|
|
41
41
|
|
|
42
|
-
def on_message(self, ws: websocket.WebSocket, message: Any):
|
|
42
|
+
def on_message(self, ws: websocket.WebSocket, message: Any) -> None:
|
|
43
43
|
# print("Received message:", message)
|
|
44
44
|
self.onmessage(message)
|
|
45
45
|
|
|
46
|
-
def on_error(self, ws: websocket.WebSocket, error: Any):
|
|
46
|
+
def on_error(self, ws: websocket.WebSocket, error: Any) -> None:
|
|
47
47
|
print("Error:", error)
|
|
48
48
|
self.onerror(error)
|
|
49
49
|
|
|
50
|
-
def on_close(
|
|
50
|
+
def on_close(
|
|
51
|
+
self, ws: websocket.WebSocket, close_status_code: Any, close_msg: Any
|
|
52
|
+
) -> None:
|
|
51
53
|
# print("Connection closed")
|
|
52
54
|
self.openState = 0
|
|
53
55
|
self.readyState = 0
|
|
@@ -55,7 +57,7 @@ class StartHSIServer:
|
|
|
55
57
|
hsiWs.close() # type: ignore
|
|
56
58
|
self.onclose()
|
|
57
59
|
|
|
58
|
-
def on_open(self, ws: websocket.WebSocket):
|
|
60
|
+
def on_open(self, ws: websocket.WebSocket) -> None:
|
|
59
61
|
# print("Connection established HSWebSocket")
|
|
60
62
|
self.openState = 1
|
|
61
63
|
self.readyState = 1
|
|
@@ -63,7 +65,7 @@ class StartHSIServer:
|
|
|
63
65
|
|
|
64
66
|
|
|
65
67
|
class HSIWebSocket:
|
|
66
|
-
def __init__(self) -> None:
|
|
68
|
+
def __init__(self, version: str) -> None:
|
|
67
69
|
# self.hsiWs = None
|
|
68
70
|
self.hsiSocket = None
|
|
69
71
|
self.reqData = None
|
|
@@ -74,6 +76,7 @@ class HSIWebSocket:
|
|
|
74
76
|
self.onmessage = None
|
|
75
77
|
self.onclose = None
|
|
76
78
|
self.onerror = None
|
|
79
|
+
self.version = version
|
|
77
80
|
# self.token, self.sid = token, sid
|
|
78
81
|
|
|
79
82
|
def open_connection(
|
|
@@ -91,7 +94,7 @@ class HSIWebSocket:
|
|
|
91
94
|
self.onerror = onerror
|
|
92
95
|
StartHSIServer(self.url, self.onopen, self.onmessage, self.onerror, self.onclose)
|
|
93
96
|
|
|
94
|
-
def send(self, d:
|
|
97
|
+
def send(self, d: str) -> None:
|
|
95
98
|
reqJson = json.loads(d)
|
|
96
99
|
req = None
|
|
97
100
|
|
|
@@ -115,7 +118,7 @@ class HSIWebSocket:
|
|
|
115
118
|
else:
|
|
116
119
|
print("Invalid connection mode !")
|
|
117
120
|
|
|
118
|
-
print(f"[KOTAK_OPEN_SEND]: {self.reqData}")
|
|
121
|
+
# print(f"[KOTAK_OPEN_SEND]: {self.reqData}")
|
|
119
122
|
|
|
120
123
|
elif reqJson["type"] == "HB":
|
|
121
124
|
# self.reqData=reqJson
|
|
@@ -131,6 +134,10 @@ class HSIWebSocket:
|
|
|
131
134
|
|
|
132
135
|
if hsiWs and req:
|
|
133
136
|
js_obj = json.dumps(req)
|
|
137
|
+
|
|
138
|
+
if self.version == "NEW":
|
|
139
|
+
js_obj = str(js_obj).replace('"', "").replace(" ", "")
|
|
140
|
+
|
|
134
141
|
hsiWs.send(js_obj)
|
|
135
142
|
else:
|
|
136
143
|
print(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -9,13 +9,13 @@ from queue import Queue
|
|
|
9
9
|
from typing import Any, Literal
|
|
10
10
|
|
|
11
11
|
import polars as pl
|
|
12
|
+
import requests
|
|
13
|
+
import websocket # type: ignore
|
|
12
14
|
from pya3 import Aliceblue as Alice
|
|
13
15
|
from pya3 import OrderType as AliceOrderType
|
|
14
16
|
from pya3 import ProductType as AliceProductType
|
|
15
17
|
from pya3 import TransactionType as AliceTransactionType
|
|
16
|
-
import requests
|
|
17
18
|
from retrying import retry # type: ignore
|
|
18
|
-
import websocket # type: ignore
|
|
19
19
|
|
|
20
20
|
from quantplay.broker.generics.broker import Broker
|
|
21
21
|
from quantplay.exception.exceptions import (
|
|
@@ -9,11 +9,11 @@ from typing import Any
|
|
|
9
9
|
import logzero # type: ignore
|
|
10
10
|
import polars as pl
|
|
11
11
|
import pyotp
|
|
12
|
+
import websocket # type: ignore
|
|
12
13
|
from requests.exceptions import ConnectionError, ConnectTimeout
|
|
13
14
|
from retrying import retry # type: ignore
|
|
14
15
|
from SmartApi import SmartConnect # type: ignore
|
|
15
16
|
from SmartApi.smartExceptions import DataException # type: ignore
|
|
16
|
-
import websocket # type: ignore
|
|
17
17
|
|
|
18
18
|
from quantplay.broker.angelone_utils.angeloneWS import AngelOneOrderUpdateWS
|
|
19
19
|
from quantplay.broker.generics.broker import Broker
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quantplay-2.1.65 → quantplay-2.1.67}/quantplay/broker/xts_utils_v2/InteractiveSocketClientV2.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|