quantplay 2.0.141__tar.gz → 2.0.142__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.0.141 → quantplay-2.0.142}/PKG-INFO +1 -1
- quantplay-2.0.142/quantplay/broker/breeze/breeze_utils.py +90 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/broker_factory.py +18 -8
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/icici_direct.py +26 -3
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/xts_utils/Connect.py +1 -1
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay.egg-info/PKG-INFO +1 -1
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay.egg-info/SOURCES.txt +2 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/setup.py +1 -1
- quantplay-2.0.142/tests/wrapper/aws/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/README.md +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/pyproject.toml +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/aliceblue.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/angelone.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/auto_login/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/auto_login/aliceblue.py +0 -0
- {quantplay-2.0.141/quantplay/broker/finvasia_utils → quantplay-2.0.142/quantplay/broker/breeze}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/dhan.py +0 -0
- {quantplay-2.0.141/quantplay/broker/ft_utils → quantplay-2.0.142/quantplay/broker/finvasia_utils}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/five_paisa.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/flattrade.py +0 -0
- {quantplay-2.0.141/quantplay/broker/generics → quantplay-2.0.142/quantplay/broker/ft_utils}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/ft_utils/ft_noren.py +0 -0
- {quantplay-2.0.141/quantplay/broker/uplink → quantplay-2.0.142/quantplay/broker/generics}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/generics/broker.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/iifl_xts.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/jainam_xts.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/kite_utils.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/kotak.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/motilal.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/noren.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/shoonya.py +0 -0
- {quantplay-2.0.141/quantplay/broker/xts_utils → quantplay-2.0.142/quantplay/broker/uplink}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/uplink/uplink_utils.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/upstox.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/xts.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/xts_utils/Exception.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
- {quantplay-2.0.141/quantplay/model → quantplay-2.0.142/quantplay/broker/xts_utils}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/broker/zerodha.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/exception/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/exception/exceptions.py +0 -0
- {quantplay-2.0.141/quantplay/wrapper → quantplay-2.0.142/quantplay/model}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/model/broker.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/model/broker_response.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/model/generics.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/model/instrument_data.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/model/order_event.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/py.typed +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/utils/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/utils/caching.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/utils/constant.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/utils/exchange.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/utils/number_utils.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/utils/pickle_utils.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/utils/selenium_utils.py +0 -0
- {quantplay-2.0.141/quantplay/wrapper/aws → quantplay-2.0.142/quantplay/wrapper}/__init__.py +0 -0
- {quantplay-2.0.141/tests → quantplay-2.0.142/quantplay/wrapper/aws}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay/wrapper/aws/s3.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay.egg-info/dependency_links.txt +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay.egg-info/requires.txt +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/quantplay.egg-info/top_level.txt +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/setup.cfg +0 -0
- {quantplay-2.0.141/tests/wrapper → quantplay-2.0.142/tests}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/tests/conftest.py +0 -0
- {quantplay-2.0.141/tests/wrapper/aws → quantplay-2.0.142/tests/wrapper}/__init__.py +0 -0
- {quantplay-2.0.141 → quantplay-2.0.142}/tests/wrapper/aws/s3_test.py +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import binascii
|
|
2
|
+
import time
|
|
3
|
+
import traceback
|
|
4
|
+
|
|
5
|
+
import pyotp
|
|
6
|
+
from retrying import retry # type: ignore
|
|
7
|
+
from selenium.common.exceptions import WebDriverException
|
|
8
|
+
|
|
9
|
+
from quantplay.exception.exceptions import (
|
|
10
|
+
InvalidArgumentException,
|
|
11
|
+
RetryableException,
|
|
12
|
+
TokenException,
|
|
13
|
+
WrongLibrarySetup,
|
|
14
|
+
retry_exception,
|
|
15
|
+
)
|
|
16
|
+
from quantplay.utils.selenium_utils import Selenium
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BreezeUtils:
|
|
20
|
+
user_id_xpath = '//*[@id="txtuid"]'
|
|
21
|
+
password_xpath = '//*[@id="txtPass"]'
|
|
22
|
+
i_agree_xpath = '//*[@id="chkssTnc"]'
|
|
23
|
+
|
|
24
|
+
login_xpath = '//*[@id="btnSubmit"]'
|
|
25
|
+
totp_xpath = '//*[@id="pnlOTP"]/div[2]/div[2]/div[3]/div/div[{}]/input'
|
|
26
|
+
submit_xpath = '//*[@id="Button1"]'
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
@retry(
|
|
30
|
+
wait_exponential_multiplier=1000,
|
|
31
|
+
wait_exponential_max=10000,
|
|
32
|
+
stop_max_attempt_number=3,
|
|
33
|
+
retry_on_exception=retry_exception,
|
|
34
|
+
)
|
|
35
|
+
def get_session_code(api_key: str, user_id: str, password: str, totp: str):
|
|
36
|
+
try:
|
|
37
|
+
driver = Selenium().get_browser()
|
|
38
|
+
|
|
39
|
+
icici_direct_url = (
|
|
40
|
+
f"https://api.icicidirect.com/apiuser/login?api_key={api_key}"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
driver.get(icici_direct_url)
|
|
44
|
+
time.sleep(2)
|
|
45
|
+
|
|
46
|
+
user_id_element = driver.find_element("xpath", BreezeUtils.user_id_xpath)
|
|
47
|
+
password_element = driver.find_element("xpath", BreezeUtils.password_xpath)
|
|
48
|
+
i_agree_element = driver.find_element("xpath", BreezeUtils.i_agree_xpath)
|
|
49
|
+
login_element = driver.find_element("xpath", BreezeUtils.login_xpath)
|
|
50
|
+
|
|
51
|
+
user_id_element.send_keys(user_id)
|
|
52
|
+
password_element.send_keys(password)
|
|
53
|
+
i_agree_element.click()
|
|
54
|
+
time.sleep(0.5)
|
|
55
|
+
login_element.click()
|
|
56
|
+
time.sleep(2)
|
|
57
|
+
totp_code = pyotp.TOTP(str(totp)).now()
|
|
58
|
+
for i in range(1, 7):
|
|
59
|
+
entry = totp_code[i - 1]
|
|
60
|
+
totp_pin = driver.find_element(
|
|
61
|
+
"xpath", BreezeUtils.totp_xpath.replace("{}", str(i))
|
|
62
|
+
)
|
|
63
|
+
totp_pin.send_keys(entry)
|
|
64
|
+
submit_element = driver.find_element("xpath", BreezeUtils.submit_xpath)
|
|
65
|
+
submit_element.click()
|
|
66
|
+
|
|
67
|
+
time.sleep(2)
|
|
68
|
+
|
|
69
|
+
url = driver.current_url
|
|
70
|
+
print("got icici redirect url {}".format(url))
|
|
71
|
+
session_token = url.split("apisession=")[1].split("&")[0]
|
|
72
|
+
|
|
73
|
+
driver.close()
|
|
74
|
+
|
|
75
|
+
return session_token
|
|
76
|
+
|
|
77
|
+
except binascii.Error:
|
|
78
|
+
raise InvalidArgumentException("Invalid TOTP key provided")
|
|
79
|
+
|
|
80
|
+
except (InvalidArgumentException, TokenException) as e:
|
|
81
|
+
raise e
|
|
82
|
+
|
|
83
|
+
except WebDriverException:
|
|
84
|
+
raise WrongLibrarySetup(
|
|
85
|
+
"ICICI login failed, please contact support team or generate token from Dashboard page"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
except Exception as e:
|
|
89
|
+
traceback.print_exc()
|
|
90
|
+
raise RetryableException(str(e))
|
|
@@ -262,14 +262,24 @@ class BrokerFactory:
|
|
|
262
262
|
broker_data["user_token"] = broker_client.user_token
|
|
263
263
|
|
|
264
264
|
elif broker == Broker.ICICI:
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
265
|
+
if "password" in broker_data:
|
|
266
|
+
broker_client = ICICI(
|
|
267
|
+
api_key=broker_data["api_key"],
|
|
268
|
+
api_secret=broker_data["api_secret"],
|
|
269
|
+
user_id=broker_data["user_id"],
|
|
270
|
+
password=broker_data["password"],
|
|
271
|
+
totp=broker_data["totp"],
|
|
272
|
+
session_token=broker_data["session_token"],
|
|
273
|
+
load_instrument=False,
|
|
274
|
+
)
|
|
275
|
+
else:
|
|
276
|
+
broker_client = ICICI(
|
|
277
|
+
api_key=broker_data["api_key"],
|
|
278
|
+
api_secret=broker_data["api_secret"],
|
|
279
|
+
session_token=broker_data["session_token"],
|
|
280
|
+
load_instrument=False,
|
|
281
|
+
)
|
|
282
|
+
broker_data["session_token"] = broker_client.session_token
|
|
273
283
|
|
|
274
284
|
elif broker == Broker.FLATTRADE:
|
|
275
285
|
broker_client = FlatTrade(
|
|
@@ -2,6 +2,8 @@ from collections.abc import Callable
|
|
|
2
2
|
from datetime import datetime, date, timedelta
|
|
3
3
|
from typing import Any, Literal, Dict
|
|
4
4
|
from breeze_connect.breeze_connect import BreezeConnect # type: ignore
|
|
5
|
+
|
|
6
|
+
from quantplay.broker.breeze.breeze_utils import BreezeUtils
|
|
5
7
|
from quantplay.exception import QuantplayOrderPlacementException, InvalidArgumentException
|
|
6
8
|
|
|
7
9
|
from quantplay.broker.generics.broker import Broker
|
|
@@ -52,15 +54,36 @@ class ICICI(Broker):
|
|
|
52
54
|
api_key: str | None = None,
|
|
53
55
|
api_secret: str | None = None,
|
|
54
56
|
session_token: str | None = None,
|
|
57
|
+
user_id: str | None = None,
|
|
58
|
+
password: str | None = None,
|
|
59
|
+
totp: str | None = None,
|
|
55
60
|
load_instrument: bool = True,
|
|
56
61
|
) -> None:
|
|
57
|
-
if api_key and
|
|
58
|
-
self.
|
|
59
|
-
|
|
62
|
+
if api_key and user_id and password and totp:
|
|
63
|
+
self.set_session_token(api_key, user_id, password, totp)
|
|
64
|
+
else:
|
|
65
|
+
self.session_token = session_token
|
|
60
66
|
|
|
67
|
+
if api_key and api_secret and self.session_token:
|
|
68
|
+
self.wrapper = BreezeConnect(api_key) # type:ignore
|
|
69
|
+
self.wrapper.generate_session(api_secret, self.session_token) # type: ignore
|
|
70
|
+
else:
|
|
71
|
+
raise InvalidArgumentException(
|
|
72
|
+
"ICICI token generation failed, missing arguments"
|
|
73
|
+
)
|
|
61
74
|
if load_instrument:
|
|
62
75
|
self.load_instrument()
|
|
63
76
|
|
|
77
|
+
def set_session_token(
|
|
78
|
+
self,
|
|
79
|
+
api_key: str,
|
|
80
|
+
user_id: str,
|
|
81
|
+
password: str,
|
|
82
|
+
totp: str,
|
|
83
|
+
):
|
|
84
|
+
session_token = BreezeUtils.get_session_code(api_key, user_id, password, totp)
|
|
85
|
+
self.session_token = session_token
|
|
86
|
+
|
|
64
87
|
def load_instrument(self, file_name: str | None = None) -> None:
|
|
65
88
|
try:
|
|
66
89
|
self.symbol_data = InstrumentData.get_instance().load_data( # type: ignore
|
|
@@ -28,6 +28,8 @@ quantplay/broker/xts.py
|
|
|
28
28
|
quantplay/broker/zerodha.py
|
|
29
29
|
quantplay/broker/auto_login/__init__.py
|
|
30
30
|
quantplay/broker/auto_login/aliceblue.py
|
|
31
|
+
quantplay/broker/breeze/__init__.py
|
|
32
|
+
quantplay/broker/breeze/breeze_utils.py
|
|
31
33
|
quantplay/broker/finvasia_utils/__init__.py
|
|
32
34
|
quantplay/broker/finvasia_utils/fa_noren.py
|
|
33
35
|
quantplay/broker/ft_utils/__init__.py
|
|
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.0.141 → quantplay-2.0.142}/quantplay/broker/xts_utils/InteractiveSocketClient.py
RENAMED
|
File without changes
|
{quantplay-2.0.141/quantplay/model → quantplay-2.0.142/quantplay/broker/xts_utils}/__init__.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
|