quantplay 2.0.151__tar.gz → 2.0.161__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.
Files changed (70) hide show
  1. {quantplay-2.0.151 → quantplay-2.0.161}/PKG-INFO +1 -1
  2. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/icici_direct.py +32 -21
  3. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/kotak.py +173 -18
  4. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay.egg-info/PKG-INFO +1 -1
  5. {quantplay-2.0.151 → quantplay-2.0.161}/setup.py +1 -1
  6. {quantplay-2.0.151 → quantplay-2.0.161}/README.md +0 -0
  7. {quantplay-2.0.151 → quantplay-2.0.161}/pyproject.toml +0 -0
  8. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/__init__.py +0 -0
  9. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/__init__.py +0 -0
  10. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/aliceblue.py +0 -0
  11. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/angelone.py +0 -0
  12. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/auto_login/__init__.py +0 -0
  13. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/auto_login/aliceblue.py +0 -0
  14. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/breeze/__init__.py +0 -0
  15. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/breeze/breeze_utils.py +0 -0
  16. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/broker_factory.py +0 -0
  17. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/dhan.py +0 -0
  18. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/finvasia_utils/__init__.py +0 -0
  19. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
  20. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/five_paisa.py +0 -0
  21. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/flattrade.py +0 -0
  22. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/ft_utils/__init__.py +0 -0
  23. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  24. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/ft_utils/ft_noren.py +0 -0
  25. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/generics/__init__.py +0 -0
  26. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/generics/broker.py +0 -0
  27. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/iifl_xts.py +0 -0
  28. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/jainam_xts.py +0 -0
  29. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/kite_utils.py +0 -0
  30. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/motilal.py +0 -0
  31. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/noren.py +0 -0
  32. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/shoonya.py +0 -0
  33. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/uplink/__init__.py +0 -0
  34. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/uplink/uplink_utils.py +0 -0
  35. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/upstox.py +0 -0
  36. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/xts.py +0 -0
  37. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/xts_utils/Connect.py +0 -0
  38. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/xts_utils/Exception.py +0 -0
  39. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
  40. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/xts_utils/__init__.py +0 -0
  41. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/broker/zerodha.py +0 -0
  42. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/exception/__init__.py +0 -0
  43. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/exception/exceptions.py +0 -0
  44. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/model/__init__.py +0 -0
  45. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/model/broker.py +0 -0
  46. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/model/broker_response.py +0 -0
  47. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/model/generics.py +0 -0
  48. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/model/instrument_data.py +0 -0
  49. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/model/order_event.py +0 -0
  50. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/py.typed +0 -0
  51. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/utils/__init__.py +0 -0
  52. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/utils/caching.py +0 -0
  53. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/utils/constant.py +0 -0
  54. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/utils/exchange.py +0 -0
  55. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/utils/number_utils.py +0 -0
  56. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/utils/pickle_utils.py +0 -0
  57. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/utils/selenium_utils.py +0 -0
  58. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/wrapper/__init__.py +0 -0
  59. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/wrapper/aws/__init__.py +0 -0
  60. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay/wrapper/aws/s3.py +0 -0
  61. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay.egg-info/SOURCES.txt +0 -0
  62. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay.egg-info/dependency_links.txt +0 -0
  63. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay.egg-info/requires.txt +0 -0
  64. {quantplay-2.0.151 → quantplay-2.0.161}/quantplay.egg-info/top_level.txt +0 -0
  65. {quantplay-2.0.151 → quantplay-2.0.161}/setup.cfg +0 -0
  66. {quantplay-2.0.151 → quantplay-2.0.161}/tests/__init__.py +0 -0
  67. {quantplay-2.0.151 → quantplay-2.0.161}/tests/conftest.py +0 -0
  68. {quantplay-2.0.151 → quantplay-2.0.161}/tests/wrapper/__init__.py +0 -0
  69. {quantplay-2.0.151 → quantplay-2.0.161}/tests/wrapper/aws/__init__.py +0 -0
  70. {quantplay-2.0.151 → quantplay-2.0.161}/tests/wrapper/aws/s3_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantplay
3
- Version: 2.0.151
3
+ Version: 2.0.161
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -146,12 +146,12 @@ class ICICI(Broker):
146
146
 
147
147
  return self.quantplay_symbol_map[symbol]
148
148
 
149
- def orders(self, tag: str | None = None, add_ltp: bool = True) -> pl.DataFrame:
149
+ def orders_by_exchange(self, exchange: ExchangeType):
150
150
  to_date = datetime.now().isoformat()[:19] + ".000Z"
151
151
  from_date = (datetime.now() - timedelta(hours=10)).isoformat()[:19] + ".000Z"
152
152
 
153
153
  orders: Dict[str, Any] = self.wrapper.get_order_list( # type:ignore
154
- exchange_code="NFO",
154
+ exchange_code=exchange,
155
155
  from_date=from_date,
156
156
  to_date=to_date,
157
157
  )
@@ -230,20 +230,21 @@ class ICICI(Broker):
230
230
 
231
231
  return orders_df
232
232
 
233
+ def orders(self, tag: str | None = None, add_ltp: bool = True) -> pl.DataFrame:
234
+ nfo_orders = self.orders_by_exchange("NFO")
235
+ bfo_orders = self.orders_by_exchange("BFO")
236
+
237
+ return pl.concat([nfo_orders, bfo_orders])
238
+
233
239
  def positions(self, drop_cnc: bool = True) -> pl.DataFrame:
234
- to_date = datetime.now().isoformat()[:19] + ".000Z"
235
- from_date = (datetime.now() - timedelta(hours=10)).isoformat()[:19] + ".000Z"
236
- positions: Dict[str, Any] = self.wrapper.get_portfolio_holdings( # type:ignore
237
- exchange_code="NFO",
238
- from_date=from_date,
239
- to_date=to_date,
240
- stock_code="",
241
- portfolio_type="",
242
- )
240
+ positions: Dict[str, Any] = self.wrapper.get_portfolio_positions() # type:ignore
241
+
243
242
  if "Success" in positions and positions["Success"] is None:
244
243
  return pl.DataFrame(schema=self.positions_schema)
245
244
  positions_df = pl.DataFrame(positions["Success"])
246
-
245
+ if "realized_profit" not in positions_df:
246
+ positions_df = positions_df.with_columns(pl.lit(0.0).alias("realized_profit"))
247
+ positions_df = positions_df.filter(pl.col("exchange_code").is_in(["NFO", "BFO"]))
247
248
  positions_df = positions_df.rename(
248
249
  {
249
250
  "exchange_code": "exchange",
@@ -252,6 +253,9 @@ class ICICI(Broker):
252
253
  "product_type": "product",
253
254
  }
254
255
  )
256
+ positions_df = positions_df.with_columns(
257
+ pl.col("quantity").cast(pl.Int32).alias("quantity")
258
+ )
255
259
  positions_df = positions_df.with_columns(
256
260
  pl.col("strike").cast(pl.Float32).alias("strike"),
257
261
  pl.col("expiry").str.strptime(pl.Date, format="%d-%b-%Y").alias("expiry"),
@@ -260,11 +264,11 @@ class ICICI(Broker):
260
264
  .when(pl.col("right") == "Put")
261
265
  .then(pl.lit("PE"))
262
266
  .alias("instrument_type"),
263
- (
264
- pl.col("unrealized_profit").cast(pl.Float32)
265
- + pl.col("realized_profit").cast(pl.Float32)
266
- ).alias("pnl"),
267
- pl.col("quantity").cast(pl.Int32).alias("quantity"),
267
+ pl.when(pl.col("action") == "Sell")
268
+ .then(abs(pl.col("quantity").cast(pl.Float32)) * -1)
269
+ .otherwise(abs(pl.col("quantity").cast(pl.Float32)))
270
+ .alias("quantity"),
271
+ pl.lit(0).alias("pnl"),
268
272
  pl.col("average_price").cast(pl.Float32).alias("average_price"),
269
273
  )
270
274
 
@@ -341,9 +345,14 @@ class ICICI(Broker):
341
345
  if tag is None:
342
346
  tag = ""
343
347
  icici_tradingsymbol = self.get_symbol(tradingsymbol)
344
- symbol_data: Dict[str, Any] = self.symbol_data[ # type:ignore
345
- f"{exchange}:{icici_tradingsymbol}"
346
- ]
348
+ try:
349
+ symbol_data: Dict[str, Any] = self.symbol_data[ # type:ignore
350
+ f"{exchange}:{icici_tradingsymbol}"
351
+ ]
352
+ except KeyError:
353
+ raise QuantplayOrderPlacementException(
354
+ f"Failed to find tradingsymbol {tradingsymbol}"
355
+ )
347
356
  icici_product = "cash"
348
357
  if exchange in ["NFO", "BFO"]:
349
358
  icici_product = "futures"
@@ -365,7 +374,7 @@ class ICICI(Broker):
365
374
  else:
366
375
  response: Dict[str, Any] = self.wrapper.place_order( # type:ignore
367
376
  stock_code=symbol_data["symbol_code"],
368
- exchange_code="NFO",
377
+ exchange_code=exchange,
369
378
  product=icici_product,
370
379
  action=transaction_type.lower(),
371
380
  order_type=order_type.lower(),
@@ -380,6 +389,8 @@ class ICICI(Broker):
380
389
  )
381
390
  if "Success" in response and "order_id" in response["Success"]:
382
391
  return response["Success"]["order_id"]
392
+ elif "Error" in response:
393
+ raise QuantplayOrderPlacementException(response["Error"])
383
394
  else:
384
395
  raise QuantplayOrderPlacementException(
385
396
  f"ICICI: order placement failed {response}"
@@ -6,6 +6,7 @@ from urllib.parse import urlencode
6
6
 
7
7
  import polars as pl
8
8
  import requests
9
+ import urllib
9
10
 
10
11
  from quantplay.broker.generics.broker import Broker
11
12
  from quantplay.model.broker import (
@@ -20,6 +21,15 @@ from quantplay.model.generics import (
20
21
  TransactionType,
21
22
  )
22
23
  from quantplay.model.order_event import OrderUpdateEvent
24
+ from quantplay.exception.exceptions import (
25
+ InvalidArgumentException,
26
+ BrokerException,
27
+ QuantplayOrderPlacementException,
28
+ )
29
+ from quantplay.utils.constant import Constants
30
+ from quantplay.utils.pickle_utils import InstrumentData
31
+ from quantplay.wrapper.aws.s3 import S3Utils
32
+ import uuid
23
33
 
24
34
  PROD_BASE_URL = "https://gw-napi.kotaksecurities.com/"
25
35
  SESSION_PROD_BASE_URL = "https://napi.kotaksecurities.com/"
@@ -59,6 +69,27 @@ class Kotak(Broker):
59
69
  elif consumer_key and consumer_secret and mobilenumber and password and mpin:
60
70
  self.login(consumer_key, consumer_secret, mobilenumber, password, mpin)
61
71
 
72
+ if load_instrument:
73
+ self.load_instrument()
74
+
75
+ def load_instrument(self, file_name: str | None = None) -> None:
76
+ try:
77
+ self.symbol_data = InstrumentData.get_instance().load_data( # type: ignore
78
+ "kotak_instruments"
79
+ )
80
+ Constants.logger.info("[LOADING_INSTRUMENTS] loading data from cache")
81
+ except Exception:
82
+ inst_data_df = S3Utils.get_parquet(
83
+ "quantplay-market-data/symbol_data/kotak_instruments.parquet"
84
+ )
85
+ inst_data_df = inst_data_df.with_columns(
86
+ pl.col("tradingsymbol").alias("broker_symbol")
87
+ )
88
+ self.instrument_data = inst_data_df
89
+ self.initialize_symbol_data_v2(save_as="kotak_instruments")
90
+
91
+ self.initialize_broker_symbol_map()
92
+
62
93
  def login(
63
94
  self,
64
95
  consumer_key: str,
@@ -83,7 +114,7 @@ class Kotak(Broker):
83
114
  )
84
115
 
85
116
  if not session_init.ok:
86
- raise Exception("")
117
+ raise InvalidArgumentException(json.loads(session_init.content))
87
118
 
88
119
  json_resp = json.loads(session_init.text)
89
120
  self.configuration["bearer_token"] = json_resp.get("access_token")
@@ -146,6 +177,11 @@ class Kotak(Broker):
146
177
  Return the Token in a String Format
147
178
  """
148
179
 
180
+ def order_history(self, order_id: str):
181
+ body = {"nOrdNo": order_id}
182
+ order_history = self.request("order_history", body=body)["data"] # type:ignore
183
+ return pl.DataFrame(order_history)
184
+
149
185
  # **
150
186
  # ** GET Api's
151
187
  # **
@@ -187,6 +223,7 @@ class Kotak(Broker):
187
223
  pl.col("order_timestamp")
188
224
  .str.strptime(pl.Datetime(time_unit="ms"), format="%d-%b-%Y %H:%M:%S")
189
225
  .alias("order_timestamp"),
226
+ pl.col("status").str.to_uppercase().alias("status"),
190
227
  )
191
228
  orders_df = orders_df.with_columns(
192
229
  pl.col("order_timestamp").alias("update_timestamp"),
@@ -228,15 +265,79 @@ class Kotak(Broker):
228
265
  return orders_df
229
266
 
230
267
  def positions(self, drop_cnc: bool = True) -> pl.DataFrame:
231
- positions_resp = self.request("order_book")
268
+ positions_resp = self.request("positions")
232
269
 
233
270
  if positions_resp["stat"] == "Not_Ok" and positions_resp["errMsg"] == "No Data":
234
271
  return pl.DataFrame(schema=self.positions_schema)
272
+ positions_df = pl.DataFrame(positions_resp["data"])
273
+
274
+ positions_df = positions_df.rename(
275
+ {
276
+ "trdSym": "tradingsymbol",
277
+ "buyAmt": "buy_value",
278
+ "sellAmt": "sell_value",
279
+ "prod": "product",
280
+ "tok": "token",
281
+ "exSeg": "exchange",
282
+ "optTp": "option_type",
283
+ }
284
+ )
285
+ positions_df = positions_df.with_columns(
286
+ (
287
+ pl.col("flBuyQty").fill_null(0).cast(pl.Int64)
288
+ + pl.col("cfBuyQty").fill_null(0).cast(pl.Int64)
289
+ ).alias("buy_quantity"),
290
+ (
291
+ pl.col("flSellQty").fill_null(0).cast(pl.Int64)
292
+ + pl.col("cfSellQty").fill_null(0).cast(pl.Int64)
293
+ ).alias("sell_quantity"),
294
+ pl.lit(None).alias("ltp"),
295
+ pl.lit(None).alias("pnl"),
296
+ pl.when(pl.col("exchange") == "nse_cm")
297
+ .then(pl.lit("NSE"))
298
+ .when(pl.col("exchange") == "bse_cm")
299
+ .then(pl.lit("BSE"))
300
+ .when(pl.col("exchange") == "nse_fo")
301
+ .then(pl.lit("NFO"))
302
+ .when(pl.col("exchange") == "bse_fo")
303
+ .then(pl.lit("BFO"))
304
+ .when(pl.col("exchange") == "cde_fo")
305
+ .then(pl.lit("CDS"))
306
+ .when(pl.col("exchange") == "bcs-fo")
307
+ .then(pl.lit("BCD"))
308
+ .when(pl.col("exchange") == "mcx")
309
+ .then(pl.lit("MCX"))
310
+ .otherwise(pl.col("exchange"))
311
+ .alias("exchange"),
312
+ pl.when(pl.col("option_type") == "XX")
313
+ .then(pl.lit(None))
314
+ .otherwise(pl.col("option_type"))
315
+ .alias("option_type"),
316
+ )
317
+ positions_df = positions_df.with_columns(
318
+ (pl.col("buy_quantity") - pl.col("sell_quantity")).alias("quantity")
319
+ )
320
+ positions_df = positions_df.with_columns(
321
+ (
322
+ (
323
+ pl.col("buy_value").cast(pl.Float32)
324
+ - pl.col("sell_value").cast(pl.Float32)
325
+ )
326
+ / pl.col("quantity")
327
+ ).alias("average_price")
328
+ )
329
+ positions_df = positions_df[list(self.positions_schema.keys())].cast(
330
+ self.positions_schema
331
+ )
332
+ return positions_df
333
+
334
+ def trades(self) -> pl.DataFrame:
335
+ self.request("trade_report")
235
336
 
236
337
  return pl.DataFrame(schema=self.positions_schema)
237
338
 
238
339
  def holdings(self) -> pl.DataFrame:
239
- holdings_resp = self.request("order_book")
340
+ holdings_resp = self.request("holdings")
240
341
 
241
342
  if holdings_resp["stat"] == "Not_Ok" and holdings_resp["errMsg"] == "No Data":
242
343
  return pl.DataFrame(schema=self.holidings_schema)
@@ -289,18 +390,25 @@ class Kotak(Broker):
289
390
  "qt": str(quantity),
290
391
  "rt": "DAY",
291
392
  "tp": str(trigger_price or "0"),
292
- "ts": tradingsymbol,
393
+ "ts": self.get_symbol(tradingsymbol, exchange),
293
394
  "tt": self.get_transaction_type(transaction_type),
294
- "ig": tag,
395
+ "ig": str(uuid.uuid4()),
295
396
  }
296
397
 
297
- place_order_resp = self.request("place_order", body=place_order_body)
398
+ place_order_resp = self.request( # type:ignore
399
+ "place_order", body=place_order_body
400
+ ) # type:ignore
298
401
  print(place_order_resp)
299
402
 
300
- return ""
403
+ if place_order_resp["stat"] == "Not_Ok":
404
+ raise QuantplayOrderPlacementException(place_order_resp["errMsg"])
405
+
406
+ return place_order_resp["nOrdNo"]
301
407
 
302
408
  def cancel_order(self, order_id: str, variety: str | None = None) -> None:
303
- return
409
+ body = {"on": order_id, "am": "No"}
410
+
411
+ self.request("cancel_order", body=body)
304
412
 
305
413
  def modify_order(self, order: ModifyOrderRequest) -> str:
306
414
  return ""
@@ -339,6 +447,34 @@ class Kotak(Broker):
339
447
 
340
448
  return exchange_segment_map.get(exchange, exchange)
341
449
 
450
+ def get_quantplay_exchange(self, exchange: str) -> str:
451
+ exchange_segment_map: dict[str, str] = {
452
+ "nse_cm": "NSE",
453
+ "bse_cm": "BSE",
454
+ "nse_fo": "NFO",
455
+ "bse_fo": "BFO",
456
+ "cde_fo": "CDS",
457
+ "mcx": "MCX",
458
+ }
459
+
460
+ return exchange_segment_map.get(exchange, exchange)
461
+
462
+ def get_lot_size(self, exchange: str, tradingsymbol: str):
463
+ tradingsymbol = self.get_quantplay_symbol(tradingsymbol)
464
+ exchange = self.get_quantplay_exchange(exchange)
465
+
466
+ try:
467
+ return int(
468
+ self.symbol_data["{}:{}".format(exchange, tradingsymbol)]["lot_size"]
469
+ )
470
+ except Exception as e:
471
+ Constants.logger.error(
472
+ "[GET_LOT_SIZE] unable to get lot size for {} {}".format(
473
+ exchange, tradingsymbol
474
+ )
475
+ )
476
+ raise e
477
+
342
478
  def get_product(self, product: ProductType) -> str:
343
479
  product_map: dict[ProductType, str] = {
344
480
  "NRML": "NRML",
@@ -348,6 +484,21 @@ class Kotak(Broker):
348
484
 
349
485
  return product_map.get(product, product)
350
486
 
487
+ def get_symbol(self, symbol: str, exchange: ExchangeType | None = None):
488
+ if exchange == "NSE":
489
+ if symbol in ["NIFTY", "BANKNIFTY"]:
490
+ return symbol
491
+ if "-EQ" not in symbol:
492
+ return f"{symbol}-EQ"
493
+ else:
494
+ return symbol
495
+ if exchange == "BSE":
496
+ return symbol
497
+
498
+ if symbol not in self.quantplay_symbol_map:
499
+ return symbol
500
+ return self.quantplay_symbol_map[symbol]
501
+
351
502
  # **
352
503
  # ** Kotak Utils
353
504
  # **
@@ -375,7 +526,7 @@ class Kotak(Broker):
375
526
  "place_order": ("Orders/2.0/quick/order/rule/ms/place", "POST", False),
376
527
  "cancel_order": ("Orders/2.0/quick/order/cancel", "POST", False),
377
528
  "modify_order": ("Orders/2.0/quick/order/vr/modify", "POST", False),
378
- "order_history": ("Orders/2.0/quick/order/history", "GET", True),
529
+ "order_history": ("Orders/2.0/quick/order/history", "POST", False),
379
530
  "order_book": ("Orders/2.0/quick/user/orders", "GET", True),
380
531
  "trade_report": ("Orders/2.0/quick/user/trades", "GET", True),
381
532
  "positions": ("Orders/2.0/quick/user/positions", "GET", True),
@@ -406,23 +557,26 @@ class Kotak(Broker):
406
557
 
407
558
  query_params = {"sId": self.configuration["serverId"]}
408
559
  if item == "place_order":
409
- query_params["sId"] = "server4"
410
- request_headers["neo-fin-key"] = "neotradeapi"
560
+ request_headers.pop("accept", None)
411
561
 
412
562
  request_body = None
413
- request_params = None
414
563
 
415
564
  if params is not None:
416
565
  request_params = urlencode({**params, **query_params})
417
566
  else:
418
567
  request_params = urlencode(query_params)
419
568
 
569
+ request_body = {}
420
570
  if body is not None:
421
571
  if content_type == "application/json":
422
572
  request_body = json.dumps(body)
423
-
573
+ elif item in ["place_order"]:
574
+ request_body["jData"] = json.dumps(body)
424
575
  elif content_type == "application/x-www-form-urlencoded":
425
- request_body = {"jData": json.dumps(body)}
576
+ request_body = urllib.parse.urlencode( # type:ignore
577
+ {"jData": json.dumps(body)},
578
+ quote_via=urllib.parse.quote, # type:ignore
579
+ )
426
580
 
427
581
  resp = None
428
582
  resp_data = None
@@ -431,17 +585,18 @@ class Kotak(Broker):
431
585
  resp = requests.get(url=url, params=request_params, headers=request_headers)
432
586
 
433
587
  elif method == "POST":
588
+ url += "?" + urlencode(query_params)
589
+
434
590
  resp = requests.post(
435
- url=url,
591
+ url,
436
592
  headers=request_headers,
437
- data=request_body,
438
- params=request_params,
593
+ data=request_body, # type:ignore
439
594
  )
440
595
 
441
596
  if resp and resp.ok:
442
597
  resp_data = resp.json()
443
598
 
444
599
  if resp_data is None:
445
- raise Exception("")
600
+ raise BrokerException("Request Failed: No response from Kotak server")
446
601
 
447
602
  return resp_data
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantplay
3
- Version: 2.0.151
3
+ Version: 2.0.161
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -21,7 +21,7 @@ requirements = [
21
21
  setup(
22
22
  name="quantplay",
23
23
  long_description=Path("README.md").read_text(),
24
- version="2.0.151",
24
+ version="2.0.161",
25
25
  setup_requires=["pytest-runner"],
26
26
  install_requires=requirements,
27
27
  tests_require=[],
File without changes
File without changes
File without changes