quantplay 2.0.86__tar.gz → 2.0.91__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.86 → quantplay-2.0.91}/PKG-INFO +1 -1
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/aliceblue.py +3 -1
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/angelone.py +13 -4
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/dhan.py +1 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/finvasia_utils/fa_noren.py +3 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/five_paisa.py +1 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/ft_utils/ft_noren.py +5 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/kotak.py +1 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/motilal.py +32 -16
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/noren.py +2 -1
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/upstox.py +1 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/xts.py +2 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/zerodha.py +10 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/model/broker.py +1 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay.egg-info/PKG-INFO +1 -1
- {quantplay-2.0.86 → quantplay-2.0.91}/setup.py +1 -1
- {quantplay-2.0.86 → quantplay-2.0.91}/README.md +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/pyproject.toml +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/auto_login/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/auto_login/aliceblue.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/broker_factory.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/finvasia_utils/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/flattrade.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/ft_utils/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/generics/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/generics/broker.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/iifl_xts.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/kite_utils.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/shoonya.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/uplink/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/uplink/uplink_utils.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/xts_utils/Connect.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/xts_utils/Exception.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/broker/xts_utils/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/exception/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/exception/exceptions.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/model/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/model/generics.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/model/instrument_data.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/model/order_event.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/py.typed +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/utils/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/utils/caching.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/utils/constant.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/utils/exchange.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/utils/number_utils.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/utils/pickle_utils.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/utils/selenium_utils.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/wrapper/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/wrapper/aws/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay/wrapper/aws/s3.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay.egg-info/SOURCES.txt +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay.egg-info/dependency_links.txt +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay.egg-info/requires.txt +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/quantplay.egg-info/top_level.txt +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/setup.cfg +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/tests/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/tests/conftest.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/tests/wrapper/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/tests/wrapper/aws/__init__.py +0 -0
- {quantplay-2.0.86 → quantplay-2.0.91}/tests/wrapper/aws/s3_test.py +0 -0
|
@@ -328,7 +328,7 @@ class Aliceblue(Broker):
|
|
|
328
328
|
"order_id": order_id,
|
|
329
329
|
"price": price,
|
|
330
330
|
}
|
|
331
|
-
if
|
|
331
|
+
if order_type is not None:
|
|
332
332
|
data["order_type"] = order_type
|
|
333
333
|
|
|
334
334
|
if trigger_price is not None and trigger_price > 0:
|
|
@@ -607,6 +607,7 @@ class Aliceblue(Broker):
|
|
|
607
607
|
"margin_used": 0.0,
|
|
608
608
|
"total_balance": 0.0,
|
|
609
609
|
"margin_available": 0.0,
|
|
610
|
+
"cash": 0,
|
|
610
611
|
}
|
|
611
612
|
|
|
612
613
|
margins = [a for a in margins if a["segment"] == "ALL"][0]
|
|
@@ -615,6 +616,7 @@ class Aliceblue(Broker):
|
|
|
615
616
|
"margin_used": float(margins["debits"]),
|
|
616
617
|
"total_balance": float(margins["credits"]),
|
|
617
618
|
"margin_available": float(margins["net"]),
|
|
619
|
+
"cash": 0,
|
|
618
620
|
}
|
|
619
621
|
|
|
620
622
|
def invoke_aliceblue_api(self, fn: Any, *args: Any, **kwargs: Any) -> Any:
|
|
@@ -532,15 +532,24 @@ class AngelOne(Broker):
|
|
|
532
532
|
if "errorcode" in api_margins and api_margins["errorcode"] == "AB1004":
|
|
533
533
|
raise TokenException("Angelone server not not responding")
|
|
534
534
|
|
|
535
|
-
return {
|
|
535
|
+
return {
|
|
536
|
+
"margin_used": 0.0,
|
|
537
|
+
"margin_available": 0.0,
|
|
538
|
+
"total_balance": 0.0,
|
|
539
|
+
"cash": 0,
|
|
540
|
+
}
|
|
536
541
|
|
|
537
542
|
api_margins = api_margins["data"]
|
|
538
543
|
|
|
539
544
|
try:
|
|
545
|
+
margin_used = float(api_margins["utiliseddebits"])
|
|
546
|
+
margin_available = float(api_margins["net"])
|
|
547
|
+
|
|
540
548
|
margins: MarginsResponse = {
|
|
541
|
-
"margin_used":
|
|
542
|
-
"margin_available":
|
|
543
|
-
"
|
|
549
|
+
"margin_used": margin_used,
|
|
550
|
+
"margin_available": margin_available,
|
|
551
|
+
"cash": float(api_margins["availablecash"]),
|
|
552
|
+
"total_balance": margin_used + margin_available,
|
|
544
553
|
}
|
|
545
554
|
|
|
546
555
|
return margins
|
|
@@ -13,6 +13,7 @@ import requests
|
|
|
13
13
|
import websocket
|
|
14
14
|
|
|
15
15
|
from quantplay.model.generics import ExchangeType, NorenTypes
|
|
16
|
+
from quantplay.exception import TokenException
|
|
16
17
|
|
|
17
18
|
logger = logging.getLogger(__name__)
|
|
18
19
|
|
|
@@ -294,6 +295,8 @@ class FA_NorenApi:
|
|
|
294
295
|
|
|
295
296
|
self.__username = userid
|
|
296
297
|
self.__accountid = userid
|
|
298
|
+
if "stat" in resDict and resDict["stat"].lower() == "not_ok":
|
|
299
|
+
raise TokenException(resDict["emsg"])
|
|
297
300
|
self.__susertoken = resDict["susertoken"]
|
|
298
301
|
|
|
299
302
|
return resDict
|
|
@@ -544,6 +544,7 @@ class FivePaisa(Broker):
|
|
|
544
544
|
"margin_used": margins["MarginUtilized"],
|
|
545
545
|
"margin_available": margins["NetAvailableMargin"],
|
|
546
546
|
"total_balance": margins["NetAvailableMargin"] + margins["MarginUtilized"],
|
|
547
|
+
"cash": 0,
|
|
547
548
|
}
|
|
548
549
|
|
|
549
550
|
def cancel_order(self, order_id: str, variety: str | None = None) -> None:
|
|
@@ -12,6 +12,7 @@ from typing import Any, Callable, Dict, List, Literal, TypedDict
|
|
|
12
12
|
import requests
|
|
13
13
|
import websocket
|
|
14
14
|
|
|
15
|
+
from quantplay.exception.exceptions import TokenException
|
|
15
16
|
from quantplay.model.generics import ExchangeType, NorenTypes
|
|
16
17
|
|
|
17
18
|
logger = logging.getLogger(__name__)
|
|
@@ -291,6 +292,10 @@ class FT_NorenApi:
|
|
|
291
292
|
|
|
292
293
|
self.__username = userid
|
|
293
294
|
self.__accountid = userid
|
|
295
|
+
|
|
296
|
+
if "stat" in resDict and resDict["stat"].lower() == "not_ok":
|
|
297
|
+
raise TokenException(resDict["emsg"])
|
|
298
|
+
|
|
294
299
|
self.__susertoken = resDict["susertoken"]
|
|
295
300
|
|
|
296
301
|
return resDict
|
|
@@ -285,38 +285,53 @@ class Motilal(Broker):
|
|
|
285
285
|
Constants.logger.info(f"[GET_LTP_RESPONSE] response {response}")
|
|
286
286
|
return response["data"]["ltp"] / 100.0
|
|
287
287
|
|
|
288
|
-
def
|
|
289
|
-
|
|
290
|
-
order_id: str,
|
|
291
|
-
price: float,
|
|
292
|
-
trigger_price: float | None = None,
|
|
293
|
-
order_type: OrderTypeType | None = None,
|
|
294
|
-
):
|
|
288
|
+
def add_existing_order_details(self, order_to_modify: Dict[str, str]):
|
|
289
|
+
order_id = order_to_modify["order_id"]
|
|
295
290
|
orders = self.orders()
|
|
296
291
|
orders = orders.filter(pl.col("order_id") == order_id)
|
|
297
292
|
|
|
298
293
|
if len(orders) != 1:
|
|
299
|
-
|
|
300
|
-
"
|
|
294
|
+
raise InvalidArgumentException(
|
|
295
|
+
f"Invalid modify request, order_id {order_id} not found"
|
|
301
296
|
)
|
|
302
|
-
return
|
|
303
297
|
|
|
304
298
|
order = orders.to_dicts()[0]
|
|
305
299
|
order["last_modified_time"] = str(order["last_modified_time"])
|
|
306
300
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
301
|
+
if "price" in order_to_modify:
|
|
302
|
+
order["price"] = order_to_modify["price"]
|
|
303
|
+
if (
|
|
304
|
+
"trigger_price" in order_to_modify
|
|
305
|
+
and order_to_modify["trigger_price"] is not None # type:ignore
|
|
306
|
+
):
|
|
307
|
+
order["trigger_price"] = order_to_modify["trigger_price"]
|
|
310
308
|
|
|
311
|
-
if
|
|
309
|
+
if "order_type" in order_to_modify and order_to_modify["order_type"] == "SL":
|
|
312
310
|
order["order_type"] = "STOPLOSS"
|
|
313
311
|
|
|
314
|
-
|
|
315
|
-
|
|
312
|
+
return order
|
|
313
|
+
|
|
314
|
+
def modify_price(
|
|
315
|
+
self,
|
|
316
|
+
order_id: str,
|
|
317
|
+
price: float,
|
|
318
|
+
trigger_price: float | None = None,
|
|
319
|
+
order_type: OrderTypeType | None = None,
|
|
320
|
+
):
|
|
321
|
+
order_to_modify = {
|
|
322
|
+
"order_id": order_id,
|
|
323
|
+
"price": price,
|
|
324
|
+
"trigger_price": trigger_price,
|
|
325
|
+
"order_type": order_type,
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
self.modify_order(order_to_modify) # type: ignore
|
|
316
329
|
|
|
317
330
|
# TODO
|
|
318
331
|
def modify_order(self, order: Any) -> str:
|
|
319
332
|
order = copy.deepcopy(order) # type:ignore
|
|
333
|
+
order = self.add_existing_order_details(order)
|
|
334
|
+
|
|
320
335
|
data = {
|
|
321
336
|
"uniqueorderid": order["order_id"],
|
|
322
337
|
"newordertype": order["order_type"].upper(),
|
|
@@ -396,6 +411,7 @@ class Motilal(Broker):
|
|
|
396
411
|
"margin_available": margin_available,
|
|
397
412
|
"margin_used": margin_used,
|
|
398
413
|
"total_balance": margin_used + margin_available,
|
|
414
|
+
"cash": 0,
|
|
399
415
|
}
|
|
400
416
|
|
|
401
417
|
def place_order(
|
|
@@ -739,6 +739,7 @@ class Noren(Broker):
|
|
|
739
739
|
margins: MarginsResponse = {
|
|
740
740
|
"margin_used": api_margins["margin_used"],
|
|
741
741
|
"margin_available": margin_available,
|
|
742
|
+
"cash": cash,
|
|
742
743
|
"total_balance": float(cash) + float(holdings_val),
|
|
743
744
|
}
|
|
744
745
|
|
|
@@ -748,4 +749,4 @@ class Noren(Broker):
|
|
|
748
749
|
logger.error(f"[NOREN_MARGIN_ERROR] {e}")
|
|
749
750
|
RetryableException("[NOREN] Failed to fetch account margin")
|
|
750
751
|
|
|
751
|
-
return {"margin_available": 0, "margin_used": 0, "total_balance": 0}
|
|
752
|
+
return {"margin_available": 0, "margin_used": 0, "total_balance": 0, "cash": 0}
|
|
@@ -182,6 +182,7 @@ class XTS(Broker):
|
|
|
182
182
|
"margin_used": 0,
|
|
183
183
|
"margin_available": 0,
|
|
184
184
|
"total_balance": 0,
|
|
185
|
+
"cash": 0,
|
|
185
186
|
}
|
|
186
187
|
api_response = api_response["result"]["BalanceList"][0]["limitObject"]
|
|
187
188
|
margin_used = api_response["RMSSubLimits"]["marginUtilized"]
|
|
@@ -190,6 +191,7 @@ class XTS(Broker):
|
|
|
190
191
|
"margin_used": margin_used,
|
|
191
192
|
"margin_available": margin_available,
|
|
192
193
|
"total_balance": margin_used + margin_available,
|
|
194
|
+
"cash": 0,
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
@retry(
|
|
@@ -381,7 +381,16 @@ class Zerodha(Broker):
|
|
|
381
381
|
[self.get_token(x) for x in holdings_df["instrument_token"].to_list()],
|
|
382
382
|
)
|
|
383
383
|
)
|
|
384
|
+
if "collateral_quantity" in holdings_df.columns:
|
|
385
|
+
holdings_df = holdings_df.with_columns(
|
|
386
|
+
pl.col("collateral_quantity").alias("pledged_quantity")
|
|
387
|
+
)
|
|
388
|
+
else:
|
|
389
|
+
holdings_df = holdings_df.with_columns(pl.lit(0).alias("pledged_quantity"))
|
|
384
390
|
|
|
391
|
+
holdings_df = holdings_df.with_columns(
|
|
392
|
+
(pl.col("pledged_quantity") + pl.col("quantity")).alias("quantity")
|
|
393
|
+
)
|
|
385
394
|
holdings_df = holdings_df.with_columns(
|
|
386
395
|
(pl.col("quantity") * pl.col("price")).alias("value"),
|
|
387
396
|
pl.lit(0).alias("pledged_quantity"),
|
|
@@ -531,6 +540,7 @@ class Zerodha(Broker):
|
|
|
531
540
|
"margin_used": margin_used,
|
|
532
541
|
"margin_available": margin_available,
|
|
533
542
|
"total_balance": margin_used + margin_available,
|
|
543
|
+
"cash": float(margins["equity"]["available"]["cash"]),
|
|
534
544
|
}
|
|
535
545
|
return response
|
|
536
546
|
|
|
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
|
|
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
|