quantplay 2.0.28__tar.gz → 2.0.30__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.28 → quantplay-2.0.30}/PKG-INFO +1 -1
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/aliceblue.py +41 -23
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/angelone.py +1 -1
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/five_paisa.py +2 -1
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/generics/broker.py +25 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/motilal.py +9 -6
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/noren.py +8 -4
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/upstox.py +2 -1
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/xts.py +10 -2
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay.egg-info/PKG-INFO +1 -1
- {quantplay-2.0.28 → quantplay-2.0.30}/setup.py +1 -1
- {quantplay-2.0.28 → quantplay-2.0.30}/README.md +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/pyproject.toml +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/auto_login/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/auto_login/aliceblue.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/finvasia_utils/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/flattrade.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/ft_utils/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/ft_utils/ft_noren.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/generics/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/iifl_xts.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/kite_utils.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/shoonya.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/uplink/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/uplink/uplink_utils.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/xts_utils/Connect.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/xts_utils/Exception.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/xts_utils/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/broker/zerodha.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/exception/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/exception/exceptions.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/model/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/model/broker.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/model/generics.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/model/order_event.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/py.typed +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/equities/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/equities/intraday/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/equities/overnight/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/futures/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/futures/overnight/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/options/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/options/intraday/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/options/intraday/ladder.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/options/intraday/musk.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/options/intraday/short_straddle.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/utils/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/utils/constant.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/utils/exchange.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/utils/number_utils.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/utils/pickle_utils.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/utils/selenium_utils.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/wrapper/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/wrapper/aws/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay/wrapper/aws/s3.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay.egg-info/SOURCES.txt +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay.egg-info/dependency_links.txt +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay.egg-info/requires.txt +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/quantplay.egg-info/top_level.txt +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/setup.cfg +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/tests/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/tests/conftest.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/tests/wrapper/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/tests/wrapper/aws/__init__.py +0 -0
- {quantplay-2.0.28 → quantplay-2.0.30}/tests/wrapper/aws/s3_test.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 Any, Callable, 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
|
|
13
13
|
|
|
14
14
|
from quantplay.broker.generics.broker import Broker
|
|
15
15
|
from quantplay.exception.exceptions import (
|
|
@@ -19,8 +19,8 @@ from quantplay.exception.exceptions import (
|
|
|
19
19
|
TokenException,
|
|
20
20
|
retry_exception,
|
|
21
21
|
)
|
|
22
|
-
from quantplay.exception.exceptions import TokenException as QuantplayTokenException
|
|
23
22
|
from quantplay.model.broker import ModifyOrderRequest, UserBrokerProfileResponse
|
|
23
|
+
from quantplay.model.generics import ExchangeType
|
|
24
24
|
from quantplay.model.order_event import OrderUpdateEvent
|
|
25
25
|
from quantplay.utils.constant import Constants, OrderType
|
|
26
26
|
from quantplay.utils.pickle_utils import InstrumentData
|
|
@@ -94,8 +94,10 @@ class Aliceblue(Broker):
|
|
|
94
94
|
if exchange == "NSE":
|
|
95
95
|
if "-EQ" not in symbol:
|
|
96
96
|
return f"{symbol}-EQ"
|
|
97
|
+
|
|
97
98
|
elif symbol not in self.quantplay_symbol_map:
|
|
98
99
|
return symbol
|
|
100
|
+
|
|
99
101
|
return self.quantplay_symbol_map[symbol]
|
|
100
102
|
|
|
101
103
|
def load_instrument(self, file_name: str | None = None):
|
|
@@ -213,11 +215,20 @@ class Aliceblue(Broker):
|
|
|
213
215
|
exception_message = f"Order placement failed [{str(e)}]"
|
|
214
216
|
raise QuantplayOrderPlacementException(exception_message)
|
|
215
217
|
|
|
216
|
-
def ltp(self, exchange, tradingsymbol: str):
|
|
218
|
+
def ltp(self, exchange: ExchangeType, tradingsymbol: str) -> float:
|
|
217
219
|
tradingsymbol = self.get_symbol(tradingsymbol, exchange=exchange)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
220
|
+
try:
|
|
221
|
+
inst = self.invoke_aliceblue_api(
|
|
222
|
+
self.alice.get_instrument_by_symbol,
|
|
223
|
+
exchange=exchange,
|
|
224
|
+
symbol=tradingsymbol,
|
|
225
|
+
)
|
|
226
|
+
except Exception:
|
|
227
|
+
inst = self.invoke_aliceblue_api(
|
|
228
|
+
self.alice.get_instrument_by_symbol,
|
|
229
|
+
exchange=exchange,
|
|
230
|
+
symbol=tradingsymbol.replace("-EQ", ""),
|
|
231
|
+
)
|
|
221
232
|
info = self.invoke_aliceblue_api(self.alice.get_scrip_info, instrument=inst)
|
|
222
233
|
|
|
223
234
|
return float(info["LTP"])
|
|
@@ -308,7 +319,8 @@ class Aliceblue(Broker):
|
|
|
308
319
|
holdings_response = self.invoke_aliceblue_api(self.alice.get_holding_positions)
|
|
309
320
|
|
|
310
321
|
if (
|
|
311
|
-
|
|
322
|
+
holdings_response is None
|
|
323
|
+
or "HoldingVal" not in holdings_response
|
|
312
324
|
or len(holdings_response["HoldingVal"]) == 0
|
|
313
325
|
):
|
|
314
326
|
return pl.DataFrame(schema=self.holidings_schema)
|
|
@@ -325,7 +337,9 @@ class Aliceblue(Broker):
|
|
|
325
337
|
"HUqty": "quantity",
|
|
326
338
|
},
|
|
327
339
|
)
|
|
328
|
-
|
|
340
|
+
holdings_df = holdings_df.with_columns(
|
|
341
|
+
pl.col("tradingsymbol").str.replace("-EQ", "").alias("tradingsymbol")
|
|
342
|
+
)
|
|
329
343
|
holdings_df = holdings_df.with_columns(pl.lit("NSE").alias("exchange"))
|
|
330
344
|
holdings_df = holdings_df.with_columns(
|
|
331
345
|
pl.struct(["exchange", "tradingsymbol"])
|
|
@@ -335,7 +349,6 @@ class Aliceblue(Broker):
|
|
|
335
349
|
)
|
|
336
350
|
.alias("price")
|
|
337
351
|
)
|
|
338
|
-
|
|
339
352
|
holdings_df = holdings_df.with_columns(
|
|
340
353
|
pl.col("quantity").cast(pl.Int64).alias("quantity"),
|
|
341
354
|
pl.col("average_price").cast(pl.Float64).alias("average_price"),
|
|
@@ -417,13 +430,7 @@ class Aliceblue(Broker):
|
|
|
417
430
|
def orders(self, tag: str | None = None, add_ltp: bool = True) -> pl.DataFrame:
|
|
418
431
|
orders_response = self.invoke_aliceblue_api(self.alice.order_data)
|
|
419
432
|
|
|
420
|
-
if not isinstance(orders_response, list)
|
|
421
|
-
("no data" in orders_response["emsg"].lower())
|
|
422
|
-
or (
|
|
423
|
-
"401" in orders_response["emsg"].lower()
|
|
424
|
-
or ("404" in orders_response["emsg"])
|
|
425
|
-
)
|
|
426
|
-
):
|
|
433
|
+
if not isinstance(orders_response, list):
|
|
427
434
|
return pl.DataFrame(schema=self.orders_schema)
|
|
428
435
|
|
|
429
436
|
if len(orders_response) == 0:
|
|
@@ -549,7 +556,7 @@ class Aliceblue(Broker):
|
|
|
549
556
|
|
|
550
557
|
return orders_df[list(self.orders_schema.keys())].cast(self.orders_schema)
|
|
551
558
|
|
|
552
|
-
def margins(self):
|
|
559
|
+
def margins(self) -> Dict[str, float]:
|
|
553
560
|
margins = self.invoke_aliceblue_api(self.alice.get_balance)
|
|
554
561
|
|
|
555
562
|
margins = [a for a in margins if a["segment"] == "ALL"][0]
|
|
@@ -567,20 +574,31 @@ class Aliceblue(Broker):
|
|
|
567
574
|
|
|
568
575
|
return margins
|
|
569
576
|
|
|
570
|
-
# TODO
|
|
571
577
|
def invoke_aliceblue_api(self, fn: Callable, *args, **kwargs) -> Any:
|
|
572
578
|
try:
|
|
573
579
|
response = fn(*args, **kwargs)
|
|
574
580
|
|
|
575
|
-
if "emsg" in response and "expired" in response["emsg"].lower():
|
|
576
|
-
raise TokenException("Session expired")
|
|
577
|
-
if "stat" in response and response["stat"].lower() == "not_ok":
|
|
578
|
-
raise InvalidArgumentException(response["emsg"])
|
|
579
581
|
if response is None:
|
|
580
582
|
raise InvalidArgumentException(
|
|
581
583
|
"Invalid data response. Aliceblue sent incorrect data, Please check."
|
|
582
584
|
)
|
|
583
585
|
|
|
586
|
+
if "emsg" in response and "expired" in response["emsg"].lower():
|
|
587
|
+
raise TokenException("Session expired")
|
|
588
|
+
elif (
|
|
589
|
+
"stat" in response
|
|
590
|
+
and response["stat"].lower() == "not_ok"
|
|
591
|
+
and (
|
|
592
|
+
"no data" in response["emsg"]
|
|
593
|
+
or "401" in response["emsg"]
|
|
594
|
+
or "404" in response["emsg"]
|
|
595
|
+
)
|
|
596
|
+
):
|
|
597
|
+
return None
|
|
598
|
+
|
|
599
|
+
elif "stat" in response and response["stat"].lower() == "not_ok":
|
|
600
|
+
raise InvalidArgumentException(response["emsg"])
|
|
601
|
+
|
|
584
602
|
return response
|
|
585
603
|
|
|
586
604
|
except (TokenException, InvalidArgumentException):
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import codecs
|
|
2
2
|
import pickle
|
|
3
3
|
import traceback
|
|
4
|
+
from typing import Dict
|
|
4
5
|
|
|
5
6
|
import polars as pl
|
|
6
7
|
import pyotp
|
|
@@ -509,7 +510,7 @@ class FivePaisa(Broker):
|
|
|
509
510
|
stop_max_attempt_number=3,
|
|
510
511
|
retry_on_exception=retry_exception,
|
|
511
512
|
)
|
|
512
|
-
def margins(self):
|
|
513
|
+
def margins(self) -> Dict[str, float]:
|
|
513
514
|
margins = self.client.margin()
|
|
514
515
|
if margins is None:
|
|
515
516
|
raise TokenException("5Paisa Token expired")
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import io
|
|
3
|
+
import json
|
|
3
4
|
import math
|
|
4
5
|
import os
|
|
5
6
|
import platform
|
|
@@ -42,6 +43,13 @@ from quantplay.wrapper.aws.s3 import S3Utils
|
|
|
42
43
|
|
|
43
44
|
logger = Constants.logger
|
|
44
45
|
|
|
46
|
+
status_to_log_map = {
|
|
47
|
+
"error": logger.error,
|
|
48
|
+
"info": logger.info,
|
|
49
|
+
"warn": logger.warn,
|
|
50
|
+
"debug": logger.debug,
|
|
51
|
+
}
|
|
52
|
+
|
|
45
53
|
|
|
46
54
|
class Broker:
|
|
47
55
|
def __init__(self):
|
|
@@ -1155,6 +1163,23 @@ class Broker:
|
|
|
1155
1163
|
"Max Modification Limit Exceeded : [{}]".format(order_id)
|
|
1156
1164
|
)
|
|
1157
1165
|
|
|
1166
|
+
def log_event(
|
|
1167
|
+
self,
|
|
1168
|
+
event: Dict[str, Any],
|
|
1169
|
+
status: Literal["error", "info", "warn", "debug"] = "info",
|
|
1170
|
+
) -> None:
|
|
1171
|
+
"""Logs Strategy Events in Standard Format
|
|
1172
|
+
|
|
1173
|
+
Format: [username][strategy_name][event_type]: [event as JSON String]
|
|
1174
|
+
|
|
1175
|
+
Args:
|
|
1176
|
+
event (Dict[str, str]): Event as a Dictionary
|
|
1177
|
+
status (Literal['error', 'info', 'warn', 'debug'], optional): Logging Level. Defaults to 'info'.
|
|
1178
|
+
"""
|
|
1179
|
+
status_to_log_map[status](
|
|
1180
|
+
f"[{self.username}][{self.nickname}][{self.broker_name}] {json.dumps(event, default=Constants.myconverter)}"
|
|
1181
|
+
)
|
|
1182
|
+
|
|
1158
1183
|
# **
|
|
1159
1184
|
# ** Generics
|
|
1160
1185
|
# **
|
|
@@ -273,10 +273,10 @@ class Motilal(Broker):
|
|
|
273
273
|
"scripcode": token,
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
Constants.logger.info("[GET_LTP_REQUEST] response {}"
|
|
277
|
-
response = self.__post_request(self.ltp_url,
|
|
278
|
-
Constants.logger.info("[GET_LTP_RESPONSE] response {}"
|
|
279
|
-
return response
|
|
276
|
+
Constants.logger.info(f"[GET_LTP_REQUEST] response {data}")
|
|
277
|
+
response = self.__post_request(self.ltp_url, data)
|
|
278
|
+
Constants.logger.info(f"[GET_LTP_RESPONSE] response {response}")
|
|
279
|
+
return response["data"]["ltp"] / 100.0
|
|
280
280
|
|
|
281
281
|
def modify_price(
|
|
282
282
|
self,
|
|
@@ -376,7 +376,7 @@ class Motilal(Broker):
|
|
|
376
376
|
)
|
|
377
377
|
Constants.logger.error(exception_message)
|
|
378
378
|
|
|
379
|
-
def margins(self):
|
|
379
|
+
def margins(self) -> Dict[str, float]:
|
|
380
380
|
response = self.__post_request(self.margin_summary_url, {})
|
|
381
381
|
margin_summary = response["data"]
|
|
382
382
|
|
|
@@ -533,10 +533,13 @@ class Motilal(Broker):
|
|
|
533
533
|
retry_on_exception=retry_exception,
|
|
534
534
|
)
|
|
535
535
|
def __post_request(self, url, data):
|
|
536
|
+
if not data:
|
|
537
|
+
data = {"Clientcode": self.headers["vendorinfo"]}
|
|
538
|
+
data = json.dumps(data)
|
|
536
539
|
api_response = requests.post(
|
|
537
540
|
url,
|
|
538
541
|
headers=self.headers,
|
|
539
|
-
data=
|
|
542
|
+
data=data,
|
|
540
543
|
).json()
|
|
541
544
|
|
|
542
545
|
if api_response["status"] == "ERROR" and api_response["errorcode"] in [
|
|
@@ -251,7 +251,13 @@ class Noren(Broker):
|
|
|
251
251
|
def ltp(self, exchange, tradingsymbol):
|
|
252
252
|
tradingsymbol = self.get_symbol(tradingsymbol, exchange)
|
|
253
253
|
|
|
254
|
-
|
|
254
|
+
try:
|
|
255
|
+
token = self.symbol_data["{}:{}".format(exchange, tradingsymbol)]["token"]
|
|
256
|
+
except KeyError:
|
|
257
|
+
token = self.symbol_data["{}:{}".format(exchange, tradingsymbol[:-3])][
|
|
258
|
+
"token"
|
|
259
|
+
]
|
|
260
|
+
|
|
255
261
|
quote = self.api.get_quotes(exchange, str(token))
|
|
256
262
|
|
|
257
263
|
if quote is None:
|
|
@@ -300,7 +306,6 @@ class Noren(Broker):
|
|
|
300
306
|
order_id = order_to_modify["order_id"]
|
|
301
307
|
existing_details = self.order_history(order_id)
|
|
302
308
|
|
|
303
|
-
# TODO
|
|
304
309
|
order_to_modify["order_type"] = self.get_order_type(order_to_modify["order_type"]) # type: ignore
|
|
305
310
|
|
|
306
311
|
if "trigger_price" not in order_to_modify:
|
|
@@ -663,7 +668,6 @@ class Noren(Broker):
|
|
|
663
668
|
response = fn(*args, **kwargs)
|
|
664
669
|
if response is None:
|
|
665
670
|
return response
|
|
666
|
-
# TODO: Verify
|
|
667
671
|
if "stat" in response and "not_ok" == response["stat"].lower():
|
|
668
672
|
raise TokenException(response["emsg"] if response is not None else "")
|
|
669
673
|
|
|
@@ -683,7 +687,7 @@ class Noren(Broker):
|
|
|
683
687
|
stop_max_attempt_number=3,
|
|
684
688
|
retry_on_exception=retry_exception,
|
|
685
689
|
)
|
|
686
|
-
def margins(self) -> Dict:
|
|
690
|
+
def margins(self) -> Dict[str, float]:
|
|
687
691
|
api_margins = self.invoke_noren_api(self.api.get_limits)
|
|
688
692
|
|
|
689
693
|
try:
|
|
@@ -3,6 +3,7 @@ import json
|
|
|
3
3
|
import ssl
|
|
4
4
|
import threading
|
|
5
5
|
import traceback
|
|
6
|
+
from typing import Dict
|
|
6
7
|
|
|
7
8
|
import polars as pl
|
|
8
9
|
import upstox_client
|
|
@@ -550,7 +551,7 @@ class Upstox(Broker):
|
|
|
550
551
|
stop_max_attempt_number=3,
|
|
551
552
|
retry_on_exception=retry_exception,
|
|
552
553
|
)
|
|
553
|
-
def margins(self):
|
|
554
|
+
def margins(self) -> Dict[str, float]:
|
|
554
555
|
api_instance = upstox_client.UserApi(self.api_client)
|
|
555
556
|
|
|
556
557
|
segment = "SEC" # str | (optional)
|
|
@@ -4,6 +4,7 @@ import pickle
|
|
|
4
4
|
import traceback
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from queue import Queue
|
|
7
|
+
from typing import Dict
|
|
7
8
|
|
|
8
9
|
import pandas as pd
|
|
9
10
|
import polars as pl
|
|
@@ -15,6 +16,7 @@ from quantplay.broker.generics.broker import Broker
|
|
|
15
16
|
from quantplay.broker.xts_utils.Connect import XTSConnect
|
|
16
17
|
from quantplay.broker.xts_utils.InteractiveSocketClient import OrderSocket_io
|
|
17
18
|
from quantplay.exception.exceptions import (
|
|
19
|
+
BrokerException,
|
|
18
20
|
InvalidArgumentException,
|
|
19
21
|
RetryableException,
|
|
20
22
|
TokenException,
|
|
@@ -175,7 +177,7 @@ class XTS(Broker):
|
|
|
175
177
|
stop_max_attempt_number=3,
|
|
176
178
|
retry_on_exception=retry_exception,
|
|
177
179
|
)
|
|
178
|
-
def margins(self) ->
|
|
180
|
+
def margins(self) -> Dict[str, float]:
|
|
179
181
|
# TODO: Edit For Dealers
|
|
180
182
|
|
|
181
183
|
api_response = self.wrapper.get_balance(clientID=self.ClientID)
|
|
@@ -553,8 +555,14 @@ class XTS(Broker):
|
|
|
553
555
|
],
|
|
554
556
|
xtsMessageCode=1512,
|
|
555
557
|
publishFormat="JSON",
|
|
556
|
-
)
|
|
558
|
+
)
|
|
557
559
|
|
|
560
|
+
if api_response["type"] == "error":
|
|
561
|
+
raise BrokerException(
|
|
562
|
+
api_response.get("description", "Broker Failed to Provide LTP")
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
api_response = api_response["result"]
|
|
558
566
|
ltp_json = api_response["listQuotes"][0]
|
|
559
567
|
|
|
560
568
|
ltp = json.loads(ltp_json)["LastTradedPrice"]
|
|
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
|
{quantplay-2.0.28 → quantplay-2.0.30}/quantplay/strategies/options/intraday/short_straddle.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
|