quantplay 2.0.34__tar.gz → 2.0.36__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.34 → quantplay-2.0.36}/PKG-INFO +1 -1
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/aliceblue.py +2 -4
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/angelone.py +4 -6
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/five_paisa.py +3 -3
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/generics/broker.py +4 -3
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/uplink/uplink_utils.py +0 -1
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/upstox.py +8 -8
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/xts.py +6 -3
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/xts_utils/Connect.py +35 -24
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/xts_utils/InteractiveSocketClient.py +39 -39
- quantplay-2.0.36/quantplay/model/xts.py +7 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/utils/pickle_utils.py +3 -3
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/wrapper/aws/s3.py +3 -3
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay.egg-info/PKG-INFO +1 -1
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay.egg-info/SOURCES.txt +1 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/setup.py +1 -1
- {quantplay-2.0.34 → quantplay-2.0.36}/README.md +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/pyproject.toml +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/auto_login/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/auto_login/aliceblue.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/finvasia_utils/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/flattrade.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/ft_utils/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/ft_utils/ft_noren.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/generics/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/iifl_xts.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/kite_utils.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/motilal.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/noren.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/shoonya.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/uplink/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/xts_utils/Exception.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/xts_utils/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/broker/zerodha.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/exception/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/exception/exceptions.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/model/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/model/broker.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/model/generics.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/model/instrument_data.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/model/order_event.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/py.typed +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/utils/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/utils/constant.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/utils/exchange.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/utils/number_utils.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/utils/selenium_utils.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/wrapper/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay/wrapper/aws/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay.egg-info/dependency_links.txt +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay.egg-info/requires.txt +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/quantplay.egg-info/top_level.txt +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/setup.cfg +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/tests/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/tests/conftest.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/tests/wrapper/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/tests/wrapper/aws/__init__.py +0 -0
- {quantplay-2.0.34 → quantplay-2.0.36}/tests/wrapper/aws/s3_test.py +0 -0
|
@@ -134,7 +134,7 @@ class Aliceblue(Broker):
|
|
|
134
134
|
return TransactionType.Sell
|
|
135
135
|
|
|
136
136
|
raise InvalidArgumentException(
|
|
137
|
-
"transaction type {} not supported for trading"
|
|
137
|
+
f"transaction type {transaction_type} not supported for trading"
|
|
138
138
|
)
|
|
139
139
|
|
|
140
140
|
def get_order_type(self, order_type):
|
|
@@ -170,9 +170,7 @@ class Aliceblue(Broker):
|
|
|
170
170
|
]:
|
|
171
171
|
return product
|
|
172
172
|
|
|
173
|
-
raise InvalidArgumentException(
|
|
174
|
-
"Product {} not supported for trading".format(product)
|
|
175
|
-
)
|
|
173
|
+
raise InvalidArgumentException(f"Product {product} not supported for trading")
|
|
176
174
|
|
|
177
175
|
def place_order(
|
|
178
176
|
self,
|
|
@@ -5,7 +5,7 @@ import json
|
|
|
5
5
|
import pickle
|
|
6
6
|
from queue import Queue
|
|
7
7
|
import traceback
|
|
8
|
-
from typing import Callable, Dict
|
|
8
|
+
from typing import Any, Callable, Dict
|
|
9
9
|
|
|
10
10
|
from SmartApi.smartExceptions import DataException
|
|
11
11
|
import polars as pl
|
|
@@ -157,9 +157,7 @@ class AngelOne(Broker):
|
|
|
157
157
|
elif product in ["BO", "MARGIN", "INTRADAY", "CARRYFORWARD", "DELIVERY"]:
|
|
158
158
|
return product
|
|
159
159
|
|
|
160
|
-
raise InvalidArgumentException(
|
|
161
|
-
"Product {} not supported for trading".format(product)
|
|
162
|
-
)
|
|
160
|
+
raise InvalidArgumentException(f"Product {product} not supported for trading")
|
|
163
161
|
|
|
164
162
|
def ltp(self, exchange, tradingsymbol: str) -> float:
|
|
165
163
|
if tradingsymbol in MarketConstants.INDEX_SYMBOL_TO_DERIVATIVE_SYMBOL_MAP:
|
|
@@ -224,7 +222,7 @@ class AngelOne(Broker):
|
|
|
224
222
|
"ordertag": tag,
|
|
225
223
|
}
|
|
226
224
|
|
|
227
|
-
Constants.logger.info("[PLACING_ORDER] {
|
|
225
|
+
Constants.logger.info(f"[PLACING_ORDER] {json.dumps(order)}")
|
|
228
226
|
return self.invoke_angelone_api(self.wrapper.placeOrder, orderparams=order)
|
|
229
227
|
|
|
230
228
|
except (TimeoutError, ConnectTimeout):
|
|
@@ -563,7 +561,7 @@ class AngelOne(Broker):
|
|
|
563
561
|
stop_max_attempt_number=3,
|
|
564
562
|
retry_on_exception=retry_exception,
|
|
565
563
|
)
|
|
566
|
-
def invoke_angelone_api(self, fn: Callable, *args, **kwargs) ->
|
|
564
|
+
def invoke_angelone_api(self, fn: Callable, *args, **kwargs) -> Any:
|
|
567
565
|
try:
|
|
568
566
|
response = fn(*args, **kwargs)
|
|
569
567
|
if "errorCode" in response and response["errorCode"] == "AG8001":
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from ast import alias
|
|
1
2
|
import codecs
|
|
2
3
|
import pickle
|
|
3
4
|
import traceback
|
|
@@ -5,7 +6,7 @@ from typing import Dict
|
|
|
5
6
|
|
|
6
7
|
import polars as pl
|
|
7
8
|
import pyotp
|
|
8
|
-
from py5paisa import FivePaisaClient
|
|
9
|
+
from py5paisa import FivePaisaClient # type: ignore
|
|
9
10
|
from retrying import retry # type: ignore
|
|
10
11
|
|
|
11
12
|
from quantplay.broker.generics.broker import Broker
|
|
@@ -147,9 +148,8 @@ class FivePaisa(Broker):
|
|
|
147
148
|
return self.client.fetch_market_feed_scrip(req_list_)["Data"][0]["LastRate"] # type: ignore
|
|
148
149
|
|
|
149
150
|
def add_exchange(self, data: pl.DataFrame):
|
|
150
|
-
data["exchange"] = None
|
|
151
|
-
|
|
152
151
|
return data.with_columns(
|
|
152
|
+
pl.lit(None).alias("exchange"),
|
|
153
153
|
pl.when((pl.col("Exch").eq("N")) & (pl.col("ExchType").eq("D")))
|
|
154
154
|
.then(pl.lit("NFO"))
|
|
155
155
|
.alias("exchange"),
|
|
@@ -147,7 +147,7 @@ class Broker:
|
|
|
147
147
|
if not input:
|
|
148
148
|
raise InvalidArgumentException(message)
|
|
149
149
|
|
|
150
|
-
def symbol_attribute(self, exchange: ExchangeType, symbol, value):
|
|
150
|
+
def symbol_attribute(self, exchange: ExchangeType, symbol: str, value):
|
|
151
151
|
try:
|
|
152
152
|
return_value = self.symbol_data[f"{exchange}:{symbol}"][value]
|
|
153
153
|
return return_value
|
|
@@ -307,6 +307,7 @@ class Broker:
|
|
|
307
307
|
file_name = url.split(".txt")[0].split("/")[-1]
|
|
308
308
|
os.system("cp /tmp/{}.txt /tmp/{}.csv".format(file_name, file_name))
|
|
309
309
|
time.sleep(2)
|
|
310
|
+
|
|
310
311
|
return pd.read_csv("/tmp/{}.csv".format(file_name))
|
|
311
312
|
|
|
312
313
|
def initialize_expiry_fields(self):
|
|
@@ -1166,13 +1167,13 @@ class Broker:
|
|
|
1166
1167
|
if modification_count[order_id] > max_modification_count:
|
|
1167
1168
|
order["order_type"] = "MARKET"
|
|
1168
1169
|
order["price"] = 0
|
|
1169
|
-
Constants.logger.info("Placing MARKET order [{}]"
|
|
1170
|
+
Constants.logger.info(f"Placing MARKET order [{order}]")
|
|
1170
1171
|
self.modify_order(order) # type: ignore
|
|
1171
1172
|
|
|
1172
1173
|
elif modification_count[order_id] > 20:
|
|
1173
1174
|
self.cancel_order(order_id)
|
|
1174
1175
|
Constants.logger.error(
|
|
1175
|
-
"Max Modification Limit Exceeded : [{}]"
|
|
1176
|
+
f"Max Modification Limit Exceeded : [{order_id}]"
|
|
1176
1177
|
)
|
|
1177
1178
|
|
|
1178
1179
|
def log_event(
|
|
@@ -142,8 +142,8 @@ class Upstox(Broker):
|
|
|
142
142
|
f"{self.get_exchange(symbol_info['exchange'])}:{tradingsymbol}"
|
|
143
143
|
].last_price
|
|
144
144
|
except ApiException as e:
|
|
145
|
-
Constants.logger.error("Exception when calling MarketQuoteApi->ltp: %s\n" % e)
|
|
146
145
|
self.handle_exception(e)
|
|
146
|
+
Constants.logger.error("Exception when calling MarketQuoteApi->ltp: %s\n" % e)
|
|
147
147
|
return ltp
|
|
148
148
|
|
|
149
149
|
@retry(
|
|
@@ -172,6 +172,7 @@ class Upstox(Broker):
|
|
|
172
172
|
api_response = api_instance.modify_order(body, self.api_version)
|
|
173
173
|
return api_response.status # type:ignore
|
|
174
174
|
except ApiException as e:
|
|
175
|
+
self.handle_exception(e)
|
|
175
176
|
Constants.logger.error(
|
|
176
177
|
"Exception when calling OrderApi->modify_order: %s\n" % e
|
|
177
178
|
)
|
|
@@ -181,10 +182,9 @@ class Upstox(Broker):
|
|
|
181
182
|
order_to_modify["order_id"], order_to_modify["price"]
|
|
182
183
|
)
|
|
183
184
|
)
|
|
184
|
-
self.handle_exception(e)
|
|
185
185
|
return order_to_modify["order_id"]
|
|
186
186
|
|
|
187
|
-
def cancel_order(self, order_id: str, variety=None) -> None:
|
|
187
|
+
def cancel_order(self, order_id: str, variety: str | None = None) -> None:
|
|
188
188
|
api_instance = upstox_client.OrderApi(self.api_client)
|
|
189
189
|
|
|
190
190
|
try:
|
|
@@ -289,8 +289,8 @@ class Upstox(Broker):
|
|
|
289
289
|
self.email = response["email"]
|
|
290
290
|
self.enabled_exchanges = response["exchanges"]
|
|
291
291
|
except ApiException as e:
|
|
292
|
-
Constants.logger.info("error when calling UserApi->get_profile: %s\n" % e)
|
|
293
292
|
self.handle_exception(e)
|
|
293
|
+
Constants.logger.info("error when calling UserApi->get_profile: %s\n" % e)
|
|
294
294
|
|
|
295
295
|
self.user_id = response["user_id"]
|
|
296
296
|
return response
|
|
@@ -305,10 +305,10 @@ class Upstox(Broker):
|
|
|
305
305
|
holdings = [holding.to_dict() for holding in api_response.data] # type:ignore
|
|
306
306
|
holdings_df = pl.DataFrame(holdings)
|
|
307
307
|
except ApiException as e:
|
|
308
|
+
self.handle_exception(e)
|
|
308
309
|
Constants.logger.error(
|
|
309
310
|
"Exception when calling PortfolioApi->get_holdings: %s\n" % e
|
|
310
311
|
)
|
|
311
|
-
self.handle_exception(e)
|
|
312
312
|
|
|
313
313
|
if len(holdings_df) == 0:
|
|
314
314
|
return pl.DataFrame(schema=self.holidings_schema)
|
|
@@ -359,10 +359,10 @@ class Upstox(Broker):
|
|
|
359
359
|
]
|
|
360
360
|
positions_df = pl.DataFrame(positions)
|
|
361
361
|
except ApiException as e:
|
|
362
|
+
self.handle_exception(e)
|
|
362
363
|
Constants.logger.error(
|
|
363
364
|
"Exception when calling PortfolioApi->get_positions: %s\n" % e
|
|
364
365
|
)
|
|
365
|
-
self.handle_exception(e)
|
|
366
366
|
|
|
367
367
|
if len(positions_df) == 0:
|
|
368
368
|
return pl.DataFrame(schema=self.positions_schema)
|
|
@@ -451,10 +451,10 @@ class Upstox(Broker):
|
|
|
451
451
|
orders = [order.to_dict() for order in api_response.data] # type:ignore
|
|
452
452
|
orders_df = pl.DataFrame(orders)
|
|
453
453
|
except ApiException as e:
|
|
454
|
+
self.handle_exception(e)
|
|
454
455
|
Constants.logger.error(
|
|
455
456
|
"Exception when calling OrderApi->get_order_book: %s\n" % e
|
|
456
457
|
)
|
|
457
|
-
self.handle_exception(e)
|
|
458
458
|
|
|
459
459
|
if len(orders_df) == 0:
|
|
460
460
|
return pl.DataFrame(schema=self.orders_schema)
|
|
@@ -570,10 +570,10 @@ class Upstox(Broker):
|
|
|
570
570
|
api_response.data["equity"].available_margin # type:ignore
|
|
571
571
|
)
|
|
572
572
|
except ApiException as e:
|
|
573
|
+
self.handle_exception(e)
|
|
573
574
|
Constants.logger.error(
|
|
574
575
|
"Exception when calling UserApi->get_user_fund_margin: %s\n" % e
|
|
575
576
|
)
|
|
576
|
-
self.handle_exception(e)
|
|
577
577
|
|
|
578
578
|
margins = {
|
|
579
579
|
"margin_used": margin_used,
|
|
@@ -52,7 +52,7 @@ class XTS(Broker):
|
|
|
52
52
|
self.root_url = root_url
|
|
53
53
|
|
|
54
54
|
try:
|
|
55
|
-
if wrapper:
|
|
55
|
+
if wrapper and ClientID:
|
|
56
56
|
self.set_wrapper(wrapper, md_wrapper)
|
|
57
57
|
self.ClientID = ClientID
|
|
58
58
|
self.wrapper.root = root_url
|
|
@@ -164,7 +164,7 @@ class XTS(Broker):
|
|
|
164
164
|
):
|
|
165
165
|
raise TokenException(response["description"])
|
|
166
166
|
if "type" in response and response["type"] == "error":
|
|
167
|
-
raise Exception("[XTS_Error]:
|
|
167
|
+
raise Exception(f"[XTS_Error]: {response["description"]}")
|
|
168
168
|
|
|
169
169
|
@retry(
|
|
170
170
|
wait_exponential_multiplier=3000,
|
|
@@ -668,7 +668,7 @@ class XTS(Broker):
|
|
|
668
668
|
disclosed_quantity = 0
|
|
669
669
|
|
|
670
670
|
api_response = self.wrapper.modify_order(
|
|
671
|
-
appOrderID=order_id,
|
|
671
|
+
appOrderID=int(order_id),
|
|
672
672
|
modifiedTimeInForce=time_in_force,
|
|
673
673
|
modifiedDisclosedQuantity=disclosed_quantity,
|
|
674
674
|
modifiedLimitPrice=price,
|
|
@@ -698,6 +698,9 @@ class XTS(Broker):
|
|
|
698
698
|
)
|
|
699
699
|
|
|
700
700
|
def stream_order_updates(self):
|
|
701
|
+
if self.wrapper.token is None:
|
|
702
|
+
raise InvalidArgumentException("XTS Token Missing")
|
|
703
|
+
|
|
701
704
|
socket = OrderSocket_io(
|
|
702
705
|
userID=self.ClientID,
|
|
703
706
|
token=self.wrapper.token,
|
|
@@ -9,7 +9,7 @@ import json
|
|
|
9
9
|
import logging
|
|
10
10
|
import os
|
|
11
11
|
import traceback
|
|
12
|
-
from typing import Any, Dict, Literal
|
|
12
|
+
from typing import Any, Dict, List, Literal
|
|
13
13
|
|
|
14
14
|
import requests
|
|
15
15
|
import urllib3
|
|
@@ -20,6 +20,7 @@ from six.moves.urllib.parse import urljoin # type:ignore
|
|
|
20
20
|
from quantplay.broker.xts_utils import Exception as ex
|
|
21
21
|
from quantplay.broker.xts_utils.Exception import XTSDataException
|
|
22
22
|
from quantplay.exception.exceptions import BrokerException
|
|
23
|
+
from quantplay.model.xts import ExchangeSegmentType
|
|
23
24
|
|
|
24
25
|
log = logging.getLogger(__name__)
|
|
25
26
|
|
|
@@ -346,15 +347,15 @@ class XTSConnect(XTSCommon):
|
|
|
346
347
|
|
|
347
348
|
def modify_order(
|
|
348
349
|
self,
|
|
349
|
-
appOrderID,
|
|
350
|
+
appOrderID: int,
|
|
350
351
|
modifiedProductType,
|
|
351
352
|
modifiedOrderType,
|
|
352
|
-
modifiedOrderQuantity,
|
|
353
|
-
modifiedDisclosedQuantity,
|
|
354
|
-
modifiedLimitPrice,
|
|
355
|
-
modifiedStopPrice,
|
|
353
|
+
modifiedOrderQuantity: int,
|
|
354
|
+
modifiedDisclosedQuantity: int,
|
|
355
|
+
modifiedLimitPrice: float,
|
|
356
|
+
modifiedStopPrice: float,
|
|
356
357
|
modifiedTimeInForce,
|
|
357
|
-
orderUniqueIdentifier,
|
|
358
|
+
orderUniqueIdentifier: str,
|
|
358
359
|
clientID: str | None = None,
|
|
359
360
|
):
|
|
360
361
|
"""The facility to modify your open orders by allowing you to change limit order to market or vice versa,
|
|
@@ -468,7 +469,7 @@ class XTSConnect(XTSCommon):
|
|
|
468
469
|
raise BrokerException("convert_position Failed for XTS")
|
|
469
470
|
|
|
470
471
|
def cancel_order(
|
|
471
|
-
self, appOrderID, orderUniqueIdentifier, clientID: str | None = None
|
|
472
|
+
self, appOrderID: int, orderUniqueIdentifier: str, clientID: str | None = None
|
|
472
473
|
):
|
|
473
474
|
"""This API can be called to cancel any open order of the user by providing correct appOrderID matching with
|
|
474
475
|
the chosen open order to cancel."""
|
|
@@ -485,7 +486,7 @@ class XTSConnect(XTSCommon):
|
|
|
485
486
|
traceback.print_exc()
|
|
486
487
|
raise BrokerException("cancel_order Failed for XTS")
|
|
487
488
|
|
|
488
|
-
def cancelall_order(self, exchangeSegment, exchangeInstrumentID):
|
|
489
|
+
def cancelall_order(self, exchangeSegment: ExchangeSegmentType, exchangeInstrumentID):
|
|
489
490
|
"""This API can be called to cancel all open order of the user by providing exchange segment and exchange instrument ID"""
|
|
490
491
|
try:
|
|
491
492
|
params: Dict[str, Any] = {
|
|
@@ -506,10 +507,10 @@ class XTSConnect(XTSCommon):
|
|
|
506
507
|
exchangeInstrumentID,
|
|
507
508
|
orderSide,
|
|
508
509
|
orderType,
|
|
509
|
-
orderQuantity,
|
|
510
|
-
disclosedQuantity,
|
|
511
|
-
limitPrice,
|
|
512
|
-
stopPrice,
|
|
510
|
+
orderQuantity: int,
|
|
511
|
+
disclosedQuantity: int,
|
|
512
|
+
limitPrice: float,
|
|
513
|
+
stopPrice: float,
|
|
513
514
|
orderUniqueIdentifier,
|
|
514
515
|
clientID: str | None = None,
|
|
515
516
|
):
|
|
@@ -537,7 +538,7 @@ class XTSConnect(XTSCommon):
|
|
|
537
538
|
traceback.print_exc()
|
|
538
539
|
raise BrokerException("place_cover_order Failed for XTS")
|
|
539
540
|
|
|
540
|
-
def exit_cover_order(self, appOrderID, clientID: str | None = None):
|
|
541
|
+
def exit_cover_order(self, appOrderID: int, clientID: str | None = None):
|
|
541
542
|
"""Exit Cover API is a functionality to enable user to easily exit an open stoploss order by converting it
|
|
542
543
|
into Exit order."""
|
|
543
544
|
try:
|
|
@@ -583,7 +584,7 @@ class XTSConnect(XTSCommon):
|
|
|
583
584
|
traceback.print_exc()
|
|
584
585
|
raise BrokerException("squareoff_position Failed for XTS")
|
|
585
586
|
|
|
586
|
-
def get_order_history(self, appOrderID, clientID: str | None = None):
|
|
587
|
+
def get_order_history(self, appOrderID: int, clientID: str | None = None):
|
|
587
588
|
"""Order history will provide particular order trail chain. This indicate the particular order & its state
|
|
588
589
|
changes. i.e.Pending New to New, New to PartiallyFilled, PartiallyFilled, PartiallyFilled & PartiallyFilled
|
|
589
590
|
to Filled etc"""
|
|
@@ -677,7 +678,7 @@ class XTSConnect(XTSCommon):
|
|
|
677
678
|
traceback.print_exc()
|
|
678
679
|
raise BrokerException("send_unsubscription Failed for XTS")
|
|
679
680
|
|
|
680
|
-
def get_master(self, exchangeSegmentList):
|
|
681
|
+
def get_master(self, exchangeSegmentList: List[ExchangeSegmentType]):
|
|
681
682
|
try:
|
|
682
683
|
params: Dict[str, Any] = {"exchangeSegmentList": exchangeSegmentList}
|
|
683
684
|
response = self._post("market.instruments.master", json.dumps(params))
|
|
@@ -688,7 +689,7 @@ class XTSConnect(XTSCommon):
|
|
|
688
689
|
|
|
689
690
|
def get_ohlc(
|
|
690
691
|
self,
|
|
691
|
-
exchangeSegment,
|
|
692
|
+
exchangeSegment: ExchangeSegmentType,
|
|
692
693
|
exchangeInstrumentID,
|
|
693
694
|
startTime,
|
|
694
695
|
endTime,
|
|
@@ -708,7 +709,7 @@ class XTSConnect(XTSCommon):
|
|
|
708
709
|
traceback.print_exc()
|
|
709
710
|
raise BrokerException("get_ohlc Failed for XTS")
|
|
710
711
|
|
|
711
|
-
def get_series(self, exchangeSegment):
|
|
712
|
+
def get_series(self, exchangeSegment: ExchangeSegmentType):
|
|
712
713
|
try:
|
|
713
714
|
params: Dict[str, Any] = {"exchangeSegment": exchangeSegment}
|
|
714
715
|
response = self._get("market.instruments.instrument.series", params)
|
|
@@ -717,7 +718,7 @@ class XTSConnect(XTSCommon):
|
|
|
717
718
|
traceback.print_exc()
|
|
718
719
|
raise BrokerException("get_series Failed for XTS")
|
|
719
720
|
|
|
720
|
-
def get_equity_symbol(self, exchangeSegment, series, symbol):
|
|
721
|
+
def get_equity_symbol(self, exchangeSegment: ExchangeSegmentType, series, symbol):
|
|
721
722
|
try:
|
|
722
723
|
params: Dict[str, Any] = {
|
|
723
724
|
"exchangeSegment": exchangeSegment,
|
|
@@ -730,7 +731,7 @@ class XTSConnect(XTSCommon):
|
|
|
730
731
|
traceback.print_exc()
|
|
731
732
|
raise BrokerException("get_equity_symbol Failed for XTS")
|
|
732
733
|
|
|
733
|
-
def get_expiry_date(self, exchangeSegment, series, symbol):
|
|
734
|
+
def get_expiry_date(self, exchangeSegment: ExchangeSegmentType, series, symbol):
|
|
734
735
|
try:
|
|
735
736
|
params: Dict[str, Any] = {
|
|
736
737
|
"exchangeSegment": exchangeSegment,
|
|
@@ -743,7 +744,9 @@ class XTSConnect(XTSCommon):
|
|
|
743
744
|
traceback.print_exc()
|
|
744
745
|
raise BrokerException("get_expiry_date Failed for XTS")
|
|
745
746
|
|
|
746
|
-
def get_future_symbol(
|
|
747
|
+
def get_future_symbol(
|
|
748
|
+
self, exchangeSegment: ExchangeSegmentType, series, symbol, expiryDate
|
|
749
|
+
):
|
|
747
750
|
try:
|
|
748
751
|
params: Dict[str, Any] = {
|
|
749
752
|
"exchangeSegment": exchangeSegment,
|
|
@@ -758,7 +761,13 @@ class XTSConnect(XTSCommon):
|
|
|
758
761
|
raise BrokerException("get_future_symbol Failed for XTS")
|
|
759
762
|
|
|
760
763
|
def get_option_symbol(
|
|
761
|
-
self,
|
|
764
|
+
self,
|
|
765
|
+
exchangeSegment: ExchangeSegmentType,
|
|
766
|
+
series,
|
|
767
|
+
symbol,
|
|
768
|
+
expiryDate,
|
|
769
|
+
optionType,
|
|
770
|
+
strikePrice,
|
|
762
771
|
):
|
|
763
772
|
try:
|
|
764
773
|
params: Dict[str, Any] = {
|
|
@@ -775,7 +784,9 @@ class XTSConnect(XTSCommon):
|
|
|
775
784
|
traceback.print_exc()
|
|
776
785
|
raise BrokerException("get_option_symbol Failed for XTS")
|
|
777
786
|
|
|
778
|
-
def get_option_type(
|
|
787
|
+
def get_option_type(
|
|
788
|
+
self, exchangeSegment: ExchangeSegmentType, series, symbol, expiryDate
|
|
789
|
+
):
|
|
779
790
|
try:
|
|
780
791
|
params: Dict[str, Any] = {
|
|
781
792
|
"exchangeSegment": exchangeSegment,
|
|
@@ -789,7 +800,7 @@ class XTSConnect(XTSCommon):
|
|
|
789
800
|
traceback.print_exc()
|
|
790
801
|
raise BrokerException("get_option_type Failed for XTS")
|
|
791
802
|
|
|
792
|
-
def get_index_list(self, exchangeSegment):
|
|
803
|
+
def get_index_list(self, exchangeSegment: ExchangeSegmentType):
|
|
793
804
|
try:
|
|
794
805
|
params: Dict[str, Any] = {"exchangeSegment": exchangeSegment}
|
|
795
806
|
response = self._get("market.instruments.indexlist", params)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from typing import Literal
|
|
2
|
-
import socketio
|
|
1
|
+
from typing import Any, Dict, List, Literal
|
|
2
|
+
import socketio # type: ignore
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class OrderSocket_io(socketio.Client):
|
|
@@ -38,18 +38,18 @@ class OrderSocket_io(socketio.Client):
|
|
|
38
38
|
|
|
39
39
|
def __init__(
|
|
40
40
|
self,
|
|
41
|
-
token,
|
|
42
|
-
userID,
|
|
43
|
-
root_url,
|
|
44
|
-
reconnection=True,
|
|
45
|
-
reconnection_attempts=0,
|
|
46
|
-
reconnection_delay=1,
|
|
47
|
-
reconnection_delay_max=50000,
|
|
48
|
-
randomization_factor=0.5,
|
|
49
|
-
logger=False,
|
|
50
|
-
binary=False,
|
|
51
|
-
json=None,
|
|
52
|
-
**kwargs,
|
|
41
|
+
token: str,
|
|
42
|
+
userID: str,
|
|
43
|
+
root_url: str,
|
|
44
|
+
reconnection: bool = True,
|
|
45
|
+
reconnection_attempts: int = 0,
|
|
46
|
+
reconnection_delay: float = 1,
|
|
47
|
+
reconnection_delay_max: float = 50000,
|
|
48
|
+
randomization_factor: float = 0.5,
|
|
49
|
+
logger: bool = False,
|
|
50
|
+
binary: bool = False,
|
|
51
|
+
json: Any | None = None,
|
|
52
|
+
**kwargs: Any,
|
|
53
53
|
):
|
|
54
54
|
self.sid = socketio.Client(logger=False, engineio_logger=False)
|
|
55
55
|
self.eventlistener = self.sid
|
|
@@ -65,24 +65,24 @@ class OrderSocket_io(socketio.Client):
|
|
|
65
65
|
port + self.token + "&userID=" + self.userID + "&apiType=INTERACTIVE"
|
|
66
66
|
)
|
|
67
67
|
|
|
68
|
-
def setup_event_listners(self, on_order):
|
|
69
|
-
self.sid.on("order", on_order)
|
|
68
|
+
def setup_event_listners(self, on_order: Any):
|
|
69
|
+
self.sid.on("order", on_order) # type: ignore
|
|
70
70
|
|
|
71
71
|
# self.sid.on("connect", self.on_connect)
|
|
72
|
-
self.sid.on("message", self.on_message)
|
|
72
|
+
self.sid.on("message", self.on_message) # type: ignore
|
|
73
73
|
# self.sid.on("joined", self.on_joined)
|
|
74
|
-
self.sid.on("error", self.on_error)
|
|
75
|
-
self.sid.on("trade", self.on_trade)
|
|
76
|
-
self.sid.on("position", self.on_position)
|
|
77
|
-
self.sid.on("tradeConversion", self.on_tradeconversion)
|
|
78
|
-
self.sid.on("logout", self.on_messagelogout)
|
|
74
|
+
self.sid.on("error", self.on_error) # type: ignore
|
|
75
|
+
self.sid.on("trade", self.on_trade) # type: ignore
|
|
76
|
+
self.sid.on("position", self.on_position) # type: ignore
|
|
77
|
+
self.sid.on("tradeConversion", self.on_tradeconversion) # type: ignore
|
|
78
|
+
self.sid.on("logout", self.on_messagelogout) # type: ignore
|
|
79
79
|
# self.sid.on("disconnect", self.on_disconnect)
|
|
80
80
|
|
|
81
81
|
def connect( # type: ignore
|
|
82
82
|
self,
|
|
83
|
-
headers={},
|
|
83
|
+
headers: Dict[str, str] = {},
|
|
84
84
|
transports: Literal["polling", "websocket"] = "websocket",
|
|
85
|
-
namespaces=None,
|
|
85
|
+
namespaces: List[str] | None = None,
|
|
86
86
|
socketio_path: str = "/interactive/socket.io",
|
|
87
87
|
verify: bool = False,
|
|
88
88
|
):
|
|
@@ -108,7 +108,7 @@ class OrderSocket_io(socketio.Client):
|
|
|
108
108
|
url = self.connection_url
|
|
109
109
|
|
|
110
110
|
"""Connected to the socket."""
|
|
111
|
-
self.sid.connect(url, headers, transports, namespaces, socketio_path)
|
|
111
|
+
self.sid.connect(url, headers, transports, namespaces, socketio_path) # type: ignore
|
|
112
112
|
self.sid.wait()
|
|
113
113
|
"""Disconnect from the socket."""
|
|
114
114
|
# self.sid.disconnect()
|
|
@@ -121,33 +121,33 @@ class OrderSocket_io(socketio.Client):
|
|
|
121
121
|
"""On message from socket"""
|
|
122
122
|
print("I received a message!")
|
|
123
123
|
|
|
124
|
-
def on_joined(self, data):
|
|
124
|
+
def on_joined(self, data: Any):
|
|
125
125
|
"""On socket joined"""
|
|
126
|
-
print("Interactive socket joined successfully!"
|
|
126
|
+
print(f"Interactive socket joined successfully!{data}")
|
|
127
127
|
|
|
128
|
-
def on_error(self, data):
|
|
128
|
+
def on_error(self, data: Any):
|
|
129
129
|
"""On receiving error from socket"""
|
|
130
|
-
print("Interactive socket error!"
|
|
130
|
+
print(f"Interactive socket error!{data}")
|
|
131
131
|
|
|
132
|
-
def on_order(self, data):
|
|
132
|
+
def on_order(self, data: Any):
|
|
133
133
|
"""On receiving order placed data from socket"""
|
|
134
|
-
print("Order placed!"
|
|
134
|
+
print(f"Order placed!{data}")
|
|
135
135
|
|
|
136
|
-
def on_trade(self, data):
|
|
136
|
+
def on_trade(self, data: Any):
|
|
137
137
|
"""On receiving trade data from socket"""
|
|
138
|
-
print("Trade Received!"
|
|
138
|
+
print(f"Trade Received!{data}")
|
|
139
139
|
|
|
140
|
-
def on_position(self, data):
|
|
140
|
+
def on_position(self, data: Any):
|
|
141
141
|
"""On receiving position data from socket"""
|
|
142
|
-
print("Position Retrieved!"
|
|
142
|
+
print(f"Position Retrieved!{data}")
|
|
143
143
|
|
|
144
|
-
def on_tradeconversion(self, data):
|
|
144
|
+
def on_tradeconversion(self, data: Any):
|
|
145
145
|
"""On receiving trade conversion data from socket"""
|
|
146
|
-
print("Trade Conversion Received!"
|
|
146
|
+
print(f"Trade Conversion Received!{data}")
|
|
147
147
|
|
|
148
|
-
def on_messagelogout(self, data):
|
|
148
|
+
def on_messagelogout(self, data: Any):
|
|
149
149
|
"""On receiving user logout message"""
|
|
150
|
-
print("User logged out!"
|
|
150
|
+
print(f"User logged out!{data}")
|
|
151
151
|
|
|
152
152
|
def on_disconnect(self):
|
|
153
153
|
"""On receiving disconnection from socket"""
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
ExchangeSegmentType = Literal[1, 2, 3, 11, 12]
|
|
5
|
+
XTSMessageCodeType = Literal[1501, 1502, 1505, 1507, 1510, 1512, 1105]
|
|
6
|
+
PublishFormatType = Literal["JSON", "Binary"]
|
|
7
|
+
ExchangeType = Literal["NSECM", "NSEFO", "NSECD", "BSECM", "BSEFO"]
|
|
@@ -8,12 +8,12 @@ from quantplay.model.instrument_data import InstrumentDataType
|
|
|
8
8
|
class PickleUtils:
|
|
9
9
|
@staticmethod
|
|
10
10
|
def save_data(data: Any, file_name: str):
|
|
11
|
-
with open("/tmp/{}.pickle"
|
|
11
|
+
with open(f"/tmp/{file_name}.pickle", "wb") as handle:
|
|
12
12
|
pickle.dump(data, handle, protocol=pickle.HIGHEST_PROTOCOL)
|
|
13
13
|
|
|
14
14
|
@staticmethod
|
|
15
15
|
def load_data(file_name: str):
|
|
16
|
-
with open("/tmp/{}.pickle"
|
|
16
|
+
with open(f"/tmp/{file_name}.pickle", "rb") as disk_data:
|
|
17
17
|
unserialized_data = pickle.load(disk_data)
|
|
18
18
|
|
|
19
19
|
return unserialized_data
|
|
@@ -44,7 +44,7 @@ class InstrumentData:
|
|
|
44
44
|
|
|
45
45
|
try:
|
|
46
46
|
self.lock.acquire()
|
|
47
|
-
with open("/tmp/{}.pickle"
|
|
47
|
+
with open(f"/tmp/{file_name}.pickle", "rb") as disk_data:
|
|
48
48
|
unserialized_data = pickle.load(disk_data)
|
|
49
49
|
self.instrument_data[file_name] = unserialized_data
|
|
50
50
|
self.lock.release()
|
|
@@ -37,15 +37,15 @@ class S3Utils:
|
|
|
37
37
|
lock.release()
|
|
38
38
|
|
|
39
39
|
except Exception:
|
|
40
|
-
print("Data not found for {}"
|
|
40
|
+
print(f"Data not found for {key}")
|
|
41
41
|
|
|
42
|
-
print("fetching bucket from s3 {} key {}"
|
|
42
|
+
print(f"fetching bucket from s3 {bucket} key {key}")
|
|
43
43
|
|
|
44
44
|
client = boto3.client("s3") # type: ignore
|
|
45
45
|
raw_stream = client.get_object(Bucket=bucket, Key=key)
|
|
46
46
|
content = raw_stream["Body"].read().decode("utf-8")
|
|
47
47
|
|
|
48
|
-
print("Saving data at
|
|
48
|
+
print(f"Saving data at /tmp/{key}")
|
|
49
49
|
full_folder_path = full_path[0 : full_path.rfind("/")]
|
|
50
50
|
if not os.path.exists(full_folder_path):
|
|
51
51
|
os.makedirs(full_folder_path)
|
|
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
|