quantplay 2.0.20__tar.gz → 2.0.22__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.20 → quantplay-2.0.22}/PKG-INFO +1 -1
- {quantplay-2.0.20 → quantplay-2.0.22}/pyproject.toml +2 -1
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/aliceblue.py +5 -8
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/angelone.py +2 -13
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/auto_login/aliceblue.py +10 -9
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/five_paisa.py +11 -20
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/flattrade.py +0 -2
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/ft_utils/flattrade_utils.py +1 -1
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/generics/broker.py +3 -6
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/iifl_xts.py +0 -2
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/kite_utils.py +1 -1
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/motilal.py +3 -17
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/noren.py +4 -24
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/shoonya.py +0 -2
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/uplink/uplink_utils.py +6 -4
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/upstox.py +2 -12
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/xts.py +3 -5
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/xts_utils/Connect.py +20 -15
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/xts_utils/InteractiveSocketClient.py +4 -3
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/zerodha.py +3 -15
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/utils/constant.py +0 -26
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/utils/number_utils.py +6 -4
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/utils/pickle_utils.py +0 -3
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/utils/selenium_utils.py +5 -3
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/wrapper/aws/s3.py +3 -3
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay.egg-info/PKG-INFO +1 -1
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay.egg-info/SOURCES.txt +0 -11
- {quantplay-2.0.20 → quantplay-2.0.22}/setup.py +1 -1
- {quantplay-2.0.20 → quantplay-2.0.22}/tests/wrapper/aws/s3_test.py +1 -1
- quantplay-2.0.20/quantplay/strategies/options/__init__.py +0 -0
- quantplay-2.0.20/quantplay/strategies/options/intraday/__init__.py +0 -0
- quantplay-2.0.20/quantplay/strategies/options/intraday/ladder.py +0 -65
- quantplay-2.0.20/quantplay/strategies/options/intraday/musk.py +0 -72
- quantplay-2.0.20/quantplay/strategies/options/intraday/short_straddle.py +0 -10
- quantplay-2.0.20/quantplay/utils/__init__.py +0 -0
- quantplay-2.0.20/quantplay/wrapper/__init__.py +0 -0
- quantplay-2.0.20/quantplay/wrapper/aws/__init__.py +0 -0
- quantplay-2.0.20/tests/__init__.py +0 -0
- quantplay-2.0.20/tests/wrapper/__init__.py +0 -0
- quantplay-2.0.20/tests/wrapper/aws/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/README.md +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/auto_login/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/finvasia_utils/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/ft_utils/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/ft_utils/ft_noren.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/generics/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/uplink/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/xts_utils/Exception.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/broker/xts_utils/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/exception/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/exception/exceptions.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/model/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/model/broker.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/model/generics.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/model/order_event.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/py.typed +0 -0
- {quantplay-2.0.20/quantplay/strategies → quantplay-2.0.22/quantplay/utils}/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay/utils/exchange.py +0 -0
- {quantplay-2.0.20/quantplay/strategies/equities → quantplay-2.0.22/quantplay/wrapper}/__init__.py +0 -0
- {quantplay-2.0.20/quantplay/strategies/equities/intraday → quantplay-2.0.22/quantplay/wrapper/aws}/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay.egg-info/dependency_links.txt +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay.egg-info/requires.txt +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/quantplay.egg-info/top_level.txt +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/setup.cfg +0 -0
- {quantplay-2.0.20/quantplay/strategies/equities/overnight → quantplay-2.0.22/tests}/__init__.py +0 -0
- {quantplay-2.0.20 → quantplay-2.0.22}/tests/conftest.py +0 -0
- {quantplay-2.0.20/quantplay/strategies/futures → quantplay-2.0.22/tests/wrapper}/__init__.py +0 -0
- {quantplay-2.0.20/quantplay/strategies/futures/overnight → quantplay-2.0.22/tests/wrapper/aws}/__init__.py +0 -0
|
@@ -3,13 +3,13 @@ import copy
|
|
|
3
3
|
import pickle
|
|
4
4
|
from queue import Queue
|
|
5
5
|
import traceback
|
|
6
|
-
from typing import Callable, Dict, Literal
|
|
6
|
+
from typing import Any, Callable, Dict, Literal
|
|
7
7
|
|
|
8
8
|
import polars as pl
|
|
9
9
|
from pya3 import Aliceblue as Alice
|
|
10
10
|
from pya3 import OrderType as AliceOrderType
|
|
11
11
|
from pya3 import ProductType, TransactionType
|
|
12
|
-
from retrying import retry
|
|
12
|
+
from retrying import retry # type: ignore
|
|
13
13
|
|
|
14
14
|
from quantplay.broker.generics.broker import Broker
|
|
15
15
|
from quantplay.exception.exceptions import (
|
|
@@ -22,7 +22,7 @@ from quantplay.exception.exceptions import (
|
|
|
22
22
|
from quantplay.exception.exceptions import TokenException as QuantplayTokenException
|
|
23
23
|
from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
|
|
24
24
|
from quantplay.model.order_event import OrderUpdateEvent
|
|
25
|
-
from quantplay.utils.constant import Constants, OrderType
|
|
25
|
+
from quantplay.utils.constant import Constants, OrderType
|
|
26
26
|
from quantplay.utils.pickle_utils import InstrumentData
|
|
27
27
|
from quantplay.wrapper.aws.s3 import S3Utils
|
|
28
28
|
|
|
@@ -30,7 +30,6 @@ logger = Constants.logger
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
class Aliceblue(Broker):
|
|
33
|
-
@timeit(MetricName="Aliceblue:__init__")
|
|
34
33
|
@retry(
|
|
35
34
|
wait_exponential_multiplier=3000,
|
|
36
35
|
wait_exponential_max=10000,
|
|
@@ -99,7 +98,6 @@ class Aliceblue(Broker):
|
|
|
99
98
|
return symbol
|
|
100
99
|
return self.quantplay_symbol_map[symbol]
|
|
101
100
|
|
|
102
|
-
@timeit(MetricName="Aliceblue:load_instrument")
|
|
103
101
|
def load_instrument(self, file_name: str | None = None):
|
|
104
102
|
try:
|
|
105
103
|
instrument_data_instance = InstrumentData.get_instance()
|
|
@@ -298,7 +296,6 @@ class Aliceblue(Broker):
|
|
|
298
296
|
|
|
299
297
|
return response
|
|
300
298
|
|
|
301
|
-
@timeit(MetricName="Aliceblue:holdings")
|
|
302
299
|
@retry(
|
|
303
300
|
wait_exponential_multiplier=3000,
|
|
304
301
|
wait_exponential_max=10000,
|
|
@@ -352,7 +349,6 @@ class Aliceblue(Broker):
|
|
|
352
349
|
|
|
353
350
|
return holdings_df[list(self.holidings_schema.keys())].cast(self.holidings_schema)
|
|
354
351
|
|
|
355
|
-
@timeit(MetricName="Aliceblue:positions")
|
|
356
352
|
@retry(
|
|
357
353
|
wait_exponential_multiplier=3000,
|
|
358
354
|
wait_exponential_max=10000,
|
|
@@ -570,7 +566,8 @@ class Aliceblue(Broker):
|
|
|
570
566
|
|
|
571
567
|
return margins
|
|
572
568
|
|
|
573
|
-
|
|
569
|
+
# TODO
|
|
570
|
+
def invoke_aliceblue_api(self, fn: Callable, *args, **kwargs) -> Any:
|
|
574
571
|
try:
|
|
575
572
|
response = fn(*args, **kwargs)
|
|
576
573
|
if response is None:
|
|
@@ -10,7 +10,7 @@ from typing import Callable, Dict
|
|
|
10
10
|
import polars as pl
|
|
11
11
|
import pyotp
|
|
12
12
|
from requests.exceptions import ConnectionError, ConnectTimeout
|
|
13
|
-
from retrying import retry
|
|
13
|
+
from retrying import retry # type: ignore
|
|
14
14
|
from SmartApi import SmartConnect
|
|
15
15
|
|
|
16
16
|
from quantplay.broker.generics.broker import Broker
|
|
@@ -26,7 +26,7 @@ from quantplay.exception.exceptions import (
|
|
|
26
26
|
from quantplay.exception.exceptions import TokenException as QuantplayTokenException
|
|
27
27
|
from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
|
|
28
28
|
from quantplay.model.order_event import OrderUpdateEvent
|
|
29
|
-
from quantplay.utils.constant import Constants, OrderType
|
|
29
|
+
from quantplay.utils.constant import Constants, OrderType
|
|
30
30
|
from quantplay.utils.exchange import Market as MarketConstants
|
|
31
31
|
from quantplay.utils.pickle_utils import InstrumentData
|
|
32
32
|
from quantplay.wrapper.aws.s3 import S3Utils
|
|
@@ -36,7 +36,6 @@ class AngelOne(Broker):
|
|
|
36
36
|
order_sl = "STOPLOSS_LIMIT"
|
|
37
37
|
order_slm = "STOPLOSS_MARKET"
|
|
38
38
|
|
|
39
|
-
@timeit(MetricName="Angelone:init")
|
|
40
39
|
@retry(
|
|
41
40
|
wait_exponential_multiplier=3000,
|
|
42
41
|
wait_exponential_max=10000,
|
|
@@ -108,7 +107,6 @@ class AngelOne(Broker):
|
|
|
108
107
|
if "errorCode" in response and response["errorCode"] == "AG8001":
|
|
109
108
|
raise TokenException(f"{self.user_id}: Invalid Token")
|
|
110
109
|
|
|
111
|
-
@timeit(MetricName="Angelone:load_instrument")
|
|
112
110
|
def load_instrument(self, file_name: str | None = None) -> None:
|
|
113
111
|
try:
|
|
114
112
|
instrument_data_instance = InstrumentData.get_instance()
|
|
@@ -164,7 +162,6 @@ class AngelOne(Broker):
|
|
|
164
162
|
"Product {} not supported for trading".format(product)
|
|
165
163
|
)
|
|
166
164
|
|
|
167
|
-
@timeit(MetricName="Angelone:get_ltp")
|
|
168
165
|
@retry(
|
|
169
166
|
wait_exponential_multiplier=3000,
|
|
170
167
|
wait_exponential_max=10000,
|
|
@@ -195,7 +192,6 @@ class AngelOne(Broker):
|
|
|
195
192
|
|
|
196
193
|
return response["data"]["ltp"]
|
|
197
194
|
|
|
198
|
-
@timeit(MetricName="Angelone:place_order")
|
|
199
195
|
def place_order(
|
|
200
196
|
self,
|
|
201
197
|
tradingsymbol=None,
|
|
@@ -255,7 +251,6 @@ class AngelOne(Broker):
|
|
|
255
251
|
return "NORMAL"
|
|
256
252
|
return variety
|
|
257
253
|
|
|
258
|
-
@timeit(MetricName="Angelone:modify_order")
|
|
259
254
|
@retry(
|
|
260
255
|
wait_exponential_multiplier=3000,
|
|
261
256
|
wait_exponential_max=10000,
|
|
@@ -312,11 +307,9 @@ class AngelOne(Broker):
|
|
|
312
307
|
)
|
|
313
308
|
raise
|
|
314
309
|
|
|
315
|
-
@timeit(MetricName="Angelone:cancel_order")
|
|
316
310
|
def cancel_order(self, order_id, variety="NORMAL"):
|
|
317
311
|
self.wrapper.cancelOrder(order_id=order_id, variety=variety)
|
|
318
312
|
|
|
319
|
-
@timeit(MetricName="Angelone:holdings")
|
|
320
313
|
@retry(
|
|
321
314
|
wait_exponential_multiplier=3000,
|
|
322
315
|
wait_exponential_max=15000,
|
|
@@ -354,7 +347,6 @@ class AngelOne(Broker):
|
|
|
354
347
|
|
|
355
348
|
return holdings
|
|
356
349
|
|
|
357
|
-
@timeit(MetricName="Angelone:positions")
|
|
358
350
|
@retry(
|
|
359
351
|
wait_exponential_multiplier=3000,
|
|
360
352
|
wait_exponential_max=15000,
|
|
@@ -435,7 +427,6 @@ class AngelOne(Broker):
|
|
|
435
427
|
self.positions_schema
|
|
436
428
|
)
|
|
437
429
|
|
|
438
|
-
@timeit(MetricName="Angelone:orders")
|
|
439
430
|
@retry(
|
|
440
431
|
wait_exponential_multiplier=3000,
|
|
441
432
|
wait_exponential_max=10000,
|
|
@@ -543,7 +534,6 @@ class AngelOne(Broker):
|
|
|
543
534
|
traceback.print_exc()
|
|
544
535
|
raise ServiceException("Unknown error while fetching order book [{}]")
|
|
545
536
|
|
|
546
|
-
@timeit(MetricName="Angelone:profile")
|
|
547
537
|
@retry(
|
|
548
538
|
wait_exponential_multiplier=3000,
|
|
549
539
|
wait_exponential_max=10000,
|
|
@@ -569,7 +559,6 @@ class AngelOne(Broker):
|
|
|
569
559
|
|
|
570
560
|
return response
|
|
571
561
|
|
|
572
|
-
@timeit(MetricName="Angelone:margins")
|
|
573
562
|
@retry(
|
|
574
563
|
wait_exponential_multiplier=3000,
|
|
575
564
|
wait_exponential_max=10000,
|
|
@@ -3,7 +3,7 @@ import time
|
|
|
3
3
|
import traceback
|
|
4
4
|
|
|
5
5
|
import pyotp
|
|
6
|
-
from retrying import retry
|
|
6
|
+
from retrying import retry # type: ignore
|
|
7
7
|
from selenium.common.exceptions import NoSuchElementException, WebDriverException
|
|
8
8
|
|
|
9
9
|
from quantplay.exception.exceptions import (
|
|
@@ -12,11 +12,12 @@ from quantplay.exception.exceptions import (
|
|
|
12
12
|
RetryableException,
|
|
13
13
|
)
|
|
14
14
|
from quantplay.utils.selenium_utils import Selenium
|
|
15
|
+
from selenium.webdriver import Chrome
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class AliceblueLogin:
|
|
18
19
|
@staticmethod
|
|
19
|
-
def check_error(page_source):
|
|
20
|
+
def check_error(page_source: str):
|
|
20
21
|
for error_message in [
|
|
21
22
|
"User profile not found",
|
|
22
23
|
"Invalid username or password",
|
|
@@ -33,36 +34,36 @@ class AliceblueLogin:
|
|
|
33
34
|
raise InvalidArgumentException("Invalid API Key")
|
|
34
35
|
|
|
35
36
|
@staticmethod
|
|
36
|
-
def click_on_login(driver):
|
|
37
|
+
def click_on_login(driver: Chrome):
|
|
37
38
|
login = '//*[@id="login_card_inital"]/div[6]/button'
|
|
38
39
|
login = driver.find_element("xpath", login)
|
|
39
40
|
login.click()
|
|
40
41
|
|
|
41
42
|
@staticmethod
|
|
42
|
-
def enter_user_id(driver, user_id: str):
|
|
43
|
+
def enter_user_id(driver: Chrome, user_id: str):
|
|
43
44
|
time.sleep(0.5)
|
|
44
45
|
user_id_xpath = '//*[@id="userid_inp"]'
|
|
45
|
-
driver.find_element("xpath", user_id_xpath).send_keys(user_id)
|
|
46
|
+
driver.find_element("xpath", user_id_xpath).send_keys(user_id) # type: ignore
|
|
46
47
|
|
|
47
48
|
time.sleep(0.5)
|
|
48
49
|
next_xpath = '//*[@id="userId_btn_label"]'
|
|
49
50
|
driver.find_element("xpath", next_xpath).click()
|
|
50
51
|
|
|
51
52
|
@staticmethod
|
|
52
|
-
def enter_password(driver, password: str):
|
|
53
|
+
def enter_password(driver: Chrome, password: str):
|
|
53
54
|
time.sleep(0.5)
|
|
54
55
|
password_xpath = '//*[@id="password_inp"]'
|
|
55
|
-
driver.find_element("xpath", password_xpath).send_keys(password)
|
|
56
|
+
driver.find_element("xpath", password_xpath).send_keys(password) # type: ignore
|
|
56
57
|
|
|
57
58
|
time.sleep(0.5)
|
|
58
59
|
next_xpath = '//*[@id="password_btn"]'
|
|
59
60
|
driver.find_element("xpath", next_xpath).click()
|
|
60
61
|
|
|
61
62
|
@staticmethod
|
|
62
|
-
def enter_totp(driver, totp: str):
|
|
63
|
+
def enter_totp(driver: Chrome, totp: str):
|
|
63
64
|
time.sleep(1.5)
|
|
64
65
|
totp_xpath = '//*[@id="totp_otp_inp"]'
|
|
65
|
-
driver.find_element("xpath", totp_xpath).send_keys(totp)
|
|
66
|
+
driver.find_element("xpath", totp_xpath).send_keys(totp) # type: ignore
|
|
66
67
|
|
|
67
68
|
# time.sleep(0.5)
|
|
68
69
|
# next_xpath = '//*[@id="totp_btn"]'
|
|
@@ -5,7 +5,7 @@ import traceback
|
|
|
5
5
|
import polars as pl
|
|
6
6
|
import pyotp
|
|
7
7
|
from py5paisa import FivePaisaClient
|
|
8
|
-
from retrying import retry
|
|
8
|
+
from retrying import retry # type: ignore
|
|
9
9
|
|
|
10
10
|
from quantplay.broker.generics.broker import Broker
|
|
11
11
|
from quantplay.exception.exceptions import (
|
|
@@ -17,7 +17,7 @@ from quantplay.exception.exceptions import (
|
|
|
17
17
|
retry_exception,
|
|
18
18
|
)
|
|
19
19
|
from quantplay.model.broker import UserBrokerProfileResponse
|
|
20
|
-
from quantplay.utils.constant import Constants, OrderStatus
|
|
20
|
+
from quantplay.utils.constant import Constants, OrderStatus
|
|
21
21
|
|
|
22
22
|
logger = Constants.logger
|
|
23
23
|
|
|
@@ -29,7 +29,6 @@ class FivePaisa(Broker):
|
|
|
29
29
|
stop_max_attempt_number=3,
|
|
30
30
|
retry_on_exception=retry_exception,
|
|
31
31
|
)
|
|
32
|
-
@timeit(MetricName="5Paisa:__init__")
|
|
33
32
|
def __init__(
|
|
34
33
|
self,
|
|
35
34
|
app_source: str | None = None,
|
|
@@ -122,7 +121,6 @@ class FivePaisa(Broker):
|
|
|
122
121
|
stop_max_attempt_number=3,
|
|
123
122
|
retry_on_exception=retry_exception,
|
|
124
123
|
)
|
|
125
|
-
@timeit(MetricName="5Paisa:profile")
|
|
126
124
|
def profile(self):
|
|
127
125
|
response: UserBrokerProfileResponse = {
|
|
128
126
|
"user_id": self.client.client_code,
|
|
@@ -136,7 +134,6 @@ class FivePaisa(Broker):
|
|
|
136
134
|
stop_max_attempt_number=3,
|
|
137
135
|
retry_on_exception=retry_exception,
|
|
138
136
|
)
|
|
139
|
-
@timeit(MetricName="5Paisa:get_ltp")
|
|
140
137
|
def get_ltp(self, exchange, tradingsymbol: str) -> float:
|
|
141
138
|
tradingsymbol = self.get_symbol(tradingsymbol, exchange)
|
|
142
139
|
exchange_name = self.get_exchange(exchange)
|
|
@@ -153,16 +150,16 @@ class FivePaisa(Broker):
|
|
|
153
150
|
|
|
154
151
|
return data.with_columns(
|
|
155
152
|
pl.when((pl.col("Exch").eq("N")) & (pl.col("ExchType").eq("D")))
|
|
156
|
-
.then("NFO")
|
|
153
|
+
.then(pl.lit("NFO"))
|
|
157
154
|
.alias("exchange"),
|
|
158
155
|
pl.when((pl.col("Exch").eq("N")) & (pl.col("ExchType").eq("C")))
|
|
159
|
-
.then("NFO")
|
|
156
|
+
.then(pl.lit("NFO"))
|
|
160
157
|
.alias("exchange"),
|
|
161
158
|
pl.when((pl.col("Exch").eq("B")) & (pl.col("ExchType").eq("D")))
|
|
162
|
-
.then("NFO")
|
|
159
|
+
.then(pl.lit("NFO"))
|
|
163
160
|
.alias("exchange"),
|
|
164
161
|
pl.when((pl.col("Exch").eq("B")) & (pl.col("ExchType").eq("C")))
|
|
165
|
-
.then("NFO")
|
|
162
|
+
.then(pl.lit("NFO"))
|
|
166
163
|
.alias("exchange"),
|
|
167
164
|
)
|
|
168
165
|
|
|
@@ -172,7 +169,6 @@ class FivePaisa(Broker):
|
|
|
172
169
|
stop_max_attempt_number=3,
|
|
173
170
|
retry_on_exception=retry_exception,
|
|
174
171
|
)
|
|
175
|
-
@timeit(MetricName="5Paisa:holdings")
|
|
176
172
|
def holdings(self):
|
|
177
173
|
holdings = self.client.holdings()
|
|
178
174
|
if holdings is None:
|
|
@@ -219,7 +215,6 @@ class FivePaisa(Broker):
|
|
|
219
215
|
stop_max_attempt_number=3,
|
|
220
216
|
retry_on_exception=retry_exception,
|
|
221
217
|
)
|
|
222
|
-
@timeit(MetricName="5Paisa:positions")
|
|
223
218
|
def positions(self, drop_cnc: bool = True):
|
|
224
219
|
positions = self.client.positions()
|
|
225
220
|
|
|
@@ -279,7 +274,7 @@ class FivePaisa(Broker):
|
|
|
279
274
|
(pl.col("exchange").is_in(["NFO", "BFO"]))
|
|
280
275
|
& (pl.col("product").ne("NRML"))
|
|
281
276
|
)
|
|
282
|
-
.then("CNC")
|
|
277
|
+
.then(pl.lit("CNC"))
|
|
283
278
|
.otherwise(pl.col("product"))
|
|
284
279
|
.alias("product"),
|
|
285
280
|
)
|
|
@@ -295,7 +290,6 @@ class FivePaisa(Broker):
|
|
|
295
290
|
stop_max_attempt_number=3,
|
|
296
291
|
retry_on_exception=retry_exception,
|
|
297
292
|
)
|
|
298
|
-
@timeit(MetricName="Upstox:orders")
|
|
299
293
|
def orders(self, tag: str | None = None, add_ltp: bool = True):
|
|
300
294
|
orders = self.client.order_book()
|
|
301
295
|
if orders is None:
|
|
@@ -335,13 +329,13 @@ class FivePaisa(Broker):
|
|
|
335
329
|
orders = (
|
|
336
330
|
orders.with_columns(
|
|
337
331
|
pl.when(pl.col("AtMarket") == "Y")
|
|
338
|
-
.then("MARKET")
|
|
339
|
-
.otherwise("LIMIT")
|
|
332
|
+
.then(pl.lit("MARKET"))
|
|
333
|
+
.otherwise(pl.lit("LIMIT"))
|
|
340
334
|
.alias("order_type"),
|
|
341
335
|
)
|
|
342
336
|
.with_columns(
|
|
343
337
|
pl.when((pl.col("order_type") == "LIMIT") & (pl.col("WithSL") == "Y"))
|
|
344
|
-
.then("SL")
|
|
338
|
+
.then(pl.lit("SL"))
|
|
345
339
|
.otherwise(pl.col("order_type"))
|
|
346
340
|
.alias("order_type"),
|
|
347
341
|
pl.col("transaction_type")
|
|
@@ -378,7 +372,7 @@ class FivePaisa(Broker):
|
|
|
378
372
|
pl.col("product")
|
|
379
373
|
== "CNC" & (pl.col("exchange").is_in(["NFO", "BFO"]))
|
|
380
374
|
)
|
|
381
|
-
.then("NRML")
|
|
375
|
+
.then(pl.lit("NRML"))
|
|
382
376
|
.otherwise(pl.col("product"))
|
|
383
377
|
.alias("product"),
|
|
384
378
|
)
|
|
@@ -445,7 +439,6 @@ class FivePaisa(Broker):
|
|
|
445
439
|
return "D"
|
|
446
440
|
raise InvalidArgumentException(f"exchange {exchange} not supported")
|
|
447
441
|
|
|
448
|
-
@timeit(MetricName="FivePaisa:place_order")
|
|
449
442
|
def place_order(
|
|
450
443
|
self,
|
|
451
444
|
tradingsymbol=None,
|
|
@@ -514,7 +507,6 @@ class FivePaisa(Broker):
|
|
|
514
507
|
stop_max_attempt_number=3,
|
|
515
508
|
retry_on_exception=retry_exception,
|
|
516
509
|
)
|
|
517
|
-
@timeit(MetricName="FivePaisa:margins")
|
|
518
510
|
def margins(self):
|
|
519
511
|
margins = self.client.margin()
|
|
520
512
|
if margins is None:
|
|
@@ -527,7 +519,6 @@ class FivePaisa(Broker):
|
|
|
527
519
|
}
|
|
528
520
|
return margins
|
|
529
521
|
|
|
530
|
-
@timeit(MetricName="5Paisa:account_summary")
|
|
531
522
|
def account_summary(self):
|
|
532
523
|
margins = self.margins()
|
|
533
524
|
response = {
|
|
@@ -9,11 +9,9 @@ from quantplay.broker.ft_utils.ft_noren import FT_NorenApi
|
|
|
9
9
|
from quantplay.broker.noren import Noren
|
|
10
10
|
from quantplay.exception.exceptions import InvalidArgumentException, RetryableException
|
|
11
11
|
from quantplay.model.order_event import OrderUpdateEvent
|
|
12
|
-
from quantplay.utils.constant import timeit
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
class FlatTrade(Noren):
|
|
16
|
-
@timeit(MetricName="Flattrade:__init__")
|
|
17
15
|
def __init__(
|
|
18
16
|
self,
|
|
19
17
|
order_updates: Queue[OrderUpdateEvent] | None = None,
|
|
@@ -34,7 +34,7 @@ from quantplay.model.broker import (
|
|
|
34
34
|
)
|
|
35
35
|
from quantplay.model.generics import ProductType, TransactionType, OrderTypeType
|
|
36
36
|
from quantplay.model.order_event import OrderUpdateEvent
|
|
37
|
-
from quantplay.utils.constant import Constants
|
|
37
|
+
from quantplay.utils.constant import Constants
|
|
38
38
|
from quantplay.utils.exchange import Market as MarketConstants
|
|
39
39
|
from quantplay.utils.number_utils import NumberUtils
|
|
40
40
|
from quantplay.utils.pickle_utils import InstrumentData, PickleUtils
|
|
@@ -163,7 +163,6 @@ class Broker:
|
|
|
163
163
|
if save_as:
|
|
164
164
|
PickleUtils.save_data(self.symbol_data, save_as)
|
|
165
165
|
|
|
166
|
-
@timeit(MetricName="Broker:initialize_broker_symbol_map")
|
|
167
166
|
def initialize_broker_symbol_map(self):
|
|
168
167
|
self.broker_symbol_map = {}
|
|
169
168
|
for a in self.symbol_data:
|
|
@@ -183,7 +182,6 @@ class Broker:
|
|
|
183
182
|
else:
|
|
184
183
|
self.quantplay_symbol_map = {v: k for k, v in self.broker_symbol_map.items()}
|
|
185
184
|
|
|
186
|
-
@timeit(MetricName="Broker:load_instrument")
|
|
187
185
|
def load_instrument(self, file_name: str) -> None:
|
|
188
186
|
try:
|
|
189
187
|
instrument_data_instance = InstrumentData.get_instance()
|
|
@@ -663,7 +661,6 @@ class Broker:
|
|
|
663
661
|
self.cancel_order(order_id)
|
|
664
662
|
time.sleep(0.1)
|
|
665
663
|
|
|
666
|
-
@timeit(MetricName="Broker:square_off_all")
|
|
667
664
|
def square_off_all(
|
|
668
665
|
self,
|
|
669
666
|
dry_run: bool = True,
|
|
@@ -699,8 +696,8 @@ class Broker:
|
|
|
699
696
|
|
|
700
697
|
positions = positions.with_columns(
|
|
701
698
|
pl.when(pl.col("quantity") < 0)
|
|
702
|
-
.then("BUY")
|
|
703
|
-
.otherwise("SELL")
|
|
699
|
+
.then(pl.lit("BUY"))
|
|
700
|
+
.otherwise(pl.lit("SELL"))
|
|
704
701
|
.alias("transaction_type")
|
|
705
702
|
)
|
|
706
703
|
|
|
@@ -10,7 +10,7 @@ import polars as pl
|
|
|
10
10
|
|
|
11
11
|
from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
|
|
12
12
|
from quantplay.model.order_event import OrderUpdateEvent
|
|
13
|
-
from quantplay.utils.constant import Constants,
|
|
13
|
+
from quantplay.utils.constant import Constants, OrderType
|
|
14
14
|
from quantplay.broker.generics.broker import Broker
|
|
15
15
|
from quantplay.exception.exceptions import InvalidArgumentException
|
|
16
16
|
import pyotp
|
|
@@ -22,7 +22,7 @@ from quantplay.exception.exceptions import (
|
|
|
22
22
|
retry_exception,
|
|
23
23
|
RetryableException,
|
|
24
24
|
)
|
|
25
|
-
from retrying import retry
|
|
25
|
+
from retrying import retry # type: ignore
|
|
26
26
|
from quantplay.wrapper.aws.s3 import S3Utils
|
|
27
27
|
|
|
28
28
|
|
|
@@ -52,7 +52,6 @@ class Motilal(Broker):
|
|
|
52
52
|
"browserversion": "105.0",
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
@timeit(MetricName="Motilal:__init__")
|
|
56
55
|
@retry(
|
|
57
56
|
wait_exponential_multiplier=3000,
|
|
58
57
|
wait_exponential_max=10000,
|
|
@@ -150,15 +149,13 @@ class Motilal(Broker):
|
|
|
150
149
|
self.nfo_exchange = "NSEFO"
|
|
151
150
|
self.exchange_code_map = {"NFO": "NSEFO", "CDS": "NSECD", "BFO": "BSEFO"}
|
|
152
151
|
|
|
153
|
-
@timeit(MetricName="Motilal:load_file_by_url")
|
|
154
152
|
def load_file_by_url(self, exchange):
|
|
155
153
|
data_url = "https://openapi.motilaloswal.com/getscripmastercsv?name={}".format(
|
|
156
154
|
exchange
|
|
157
155
|
)
|
|
158
|
-
df = pd.read_csv(data_url)
|
|
156
|
+
df = pd.read_csv(data_url) # type: ignore
|
|
159
157
|
self.instrument_data_by_exchange[exchange] = df
|
|
160
158
|
|
|
161
|
-
@timeit(MetricName="Motilal:load_instrument")
|
|
162
159
|
def load_instrument(self, file_name: str | None = None) -> None:
|
|
163
160
|
try:
|
|
164
161
|
self.symbol_data = InstrumentData.get_instance().load_data( # type: ignore
|
|
@@ -266,7 +263,6 @@ class Motilal(Broker):
|
|
|
266
263
|
Constants.logger.info(response)
|
|
267
264
|
return response
|
|
268
265
|
|
|
269
|
-
@timeit(MetricName="Motilal:get_ltp")
|
|
270
266
|
@retry(
|
|
271
267
|
wait_exponential_multiplier=3000,
|
|
272
268
|
wait_exponential_max=10000,
|
|
@@ -289,7 +285,6 @@ class Motilal(Broker):
|
|
|
289
285
|
Constants.logger.info("[GET_LTP_RESPONSE] response {}".format(response.json()))
|
|
290
286
|
return response.json()["data"]["ltp"] / 100.0
|
|
291
287
|
|
|
292
|
-
@timeit(MetricName="Motilal:modify_price")
|
|
293
288
|
def modify_price(
|
|
294
289
|
self,
|
|
295
290
|
order_id: str,
|
|
@@ -319,7 +314,6 @@ class Motilal(Broker):
|
|
|
319
314
|
print(order)
|
|
320
315
|
self.modify_order(order) # type: ignore
|
|
321
316
|
|
|
322
|
-
@timeit(MetricName="Motilal:modify_order")
|
|
323
317
|
def modify_order(self, order_to_modify: ModifyOrderRequest) -> str:
|
|
324
318
|
order: dict = copy.deepcopy(order_to_modify) # type:ignore
|
|
325
319
|
data = {
|
|
@@ -356,7 +350,6 @@ class Motilal(Broker):
|
|
|
356
350
|
Constants.logger.error("{}".format(exception_message))
|
|
357
351
|
return order["order_id"]
|
|
358
352
|
|
|
359
|
-
@timeit(MetricName="Motilal:cancel_order")
|
|
360
353
|
@retry(
|
|
361
354
|
wait_exponential_multiplier=3000,
|
|
362
355
|
wait_exponential_max=10000,
|
|
@@ -401,7 +394,6 @@ class Motilal(Broker):
|
|
|
401
394
|
|
|
402
395
|
return response["data"]
|
|
403
396
|
|
|
404
|
-
@timeit(MetricName="Motilal:margins")
|
|
405
397
|
@retry(
|
|
406
398
|
wait_exponential_multiplier=3000,
|
|
407
399
|
wait_exponential_max=10000,
|
|
@@ -426,7 +418,6 @@ class Motilal(Broker):
|
|
|
426
418
|
|
|
427
419
|
return margins
|
|
428
420
|
|
|
429
|
-
@timeit(MetricName="Motilal:place_order")
|
|
430
421
|
def place_order(
|
|
431
422
|
self,
|
|
432
423
|
tradingsymbol=None,
|
|
@@ -557,14 +548,12 @@ class Motilal(Broker):
|
|
|
557
548
|
|
|
558
549
|
thread.start_new_thread(run, ())
|
|
559
550
|
|
|
560
|
-
@timeit(MetricName="Motilal:account_summary")
|
|
561
551
|
def account_summary(self):
|
|
562
552
|
response = self.margins()
|
|
563
553
|
response["pnl"] = float(self.positions()["pnl"].sum()) # type: ignore
|
|
564
554
|
|
|
565
555
|
return response
|
|
566
556
|
|
|
567
|
-
@timeit(MetricName="Motilal:profile")
|
|
568
557
|
def profile(self) -> UserBrokerProfileResponse:
|
|
569
558
|
api_response = requests.post(
|
|
570
559
|
self.get_profile_url,
|
|
@@ -583,7 +572,6 @@ class Motilal(Broker):
|
|
|
583
572
|
|
|
584
573
|
return response
|
|
585
574
|
|
|
586
|
-
@timeit(MetricName="Motilal:holdings")
|
|
587
575
|
@retry(
|
|
588
576
|
wait_exponential_multiplier=3000,
|
|
589
577
|
wait_exponential_max=10000,
|
|
@@ -636,7 +624,6 @@ class Motilal(Broker):
|
|
|
636
624
|
|
|
637
625
|
return holdings_df[list(self.holidings_schema.keys())].cast(self.holidings_schema)
|
|
638
626
|
|
|
639
|
-
@timeit(MetricName="Motilal:positions")
|
|
640
627
|
@retry(
|
|
641
628
|
wait_exponential_multiplier=3000,
|
|
642
629
|
wait_exponential_max=10000,
|
|
@@ -711,7 +698,6 @@ class Motilal(Broker):
|
|
|
711
698
|
self.positions_schema
|
|
712
699
|
)
|
|
713
700
|
|
|
714
|
-
@timeit(MetricName="Motilal:orders")
|
|
715
701
|
def orders(self, tag: str | None = None, add_ltp: bool = True) -> pl.DataFrame:
|
|
716
702
|
response = (requests.post(self.order_book_url, headers=self.headers)).json()
|
|
717
703
|
if response["status"] == "ERROR":
|