quantplay 2.0.28__tar.gz → 2.0.29__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 (71) hide show
  1. {quantplay-2.0.28 → quantplay-2.0.29}/PKG-INFO +1 -1
  2. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/aliceblue.py +14 -11
  3. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/angelone.py +1 -1
  4. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/five_paisa.py +2 -1
  5. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/generics/broker.py +25 -0
  6. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/motilal.py +1 -1
  7. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/noren.py +1 -1
  8. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/upstox.py +2 -1
  9. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/xts.py +10 -2
  10. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay.egg-info/PKG-INFO +1 -1
  11. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay.egg-info/SOURCES.txt +0 -11
  12. {quantplay-2.0.28 → quantplay-2.0.29}/setup.py +1 -1
  13. quantplay-2.0.28/quantplay/strategies/options/__init__.py +0 -0
  14. quantplay-2.0.28/quantplay/strategies/options/intraday/__init__.py +0 -0
  15. quantplay-2.0.28/quantplay/strategies/options/intraday/ladder.py +0 -65
  16. quantplay-2.0.28/quantplay/strategies/options/intraday/musk.py +0 -72
  17. quantplay-2.0.28/quantplay/strategies/options/intraday/short_straddle.py +0 -10
  18. quantplay-2.0.28/quantplay/utils/__init__.py +0 -0
  19. quantplay-2.0.28/quantplay/wrapper/__init__.py +0 -0
  20. quantplay-2.0.28/quantplay/wrapper/aws/__init__.py +0 -0
  21. quantplay-2.0.28/tests/__init__.py +0 -0
  22. quantplay-2.0.28/tests/wrapper/__init__.py +0 -0
  23. quantplay-2.0.28/tests/wrapper/aws/__init__.py +0 -0
  24. {quantplay-2.0.28 → quantplay-2.0.29}/README.md +0 -0
  25. {quantplay-2.0.28 → quantplay-2.0.29}/pyproject.toml +0 -0
  26. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/__init__.py +0 -0
  27. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/__init__.py +0 -0
  28. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/auto_login/__init__.py +0 -0
  29. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/auto_login/aliceblue.py +0 -0
  30. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/finvasia_utils/__init__.py +0 -0
  31. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
  32. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/flattrade.py +0 -0
  33. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/ft_utils/__init__.py +0 -0
  34. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  35. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/ft_utils/ft_noren.py +0 -0
  36. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/generics/__init__.py +0 -0
  37. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/iifl_xts.py +0 -0
  38. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/kite_utils.py +0 -0
  39. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/shoonya.py +0 -0
  40. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/uplink/__init__.py +0 -0
  41. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/uplink/uplink_utils.py +0 -0
  42. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/xts_utils/Connect.py +0 -0
  43. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/xts_utils/Exception.py +0 -0
  44. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
  45. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/xts_utils/__init__.py +0 -0
  46. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/broker/zerodha.py +0 -0
  47. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/exception/__init__.py +0 -0
  48. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/exception/exceptions.py +0 -0
  49. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/model/__init__.py +0 -0
  50. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/model/broker.py +0 -0
  51. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/model/generics.py +0 -0
  52. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/model/order_event.py +0 -0
  53. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/py.typed +0 -0
  54. {quantplay-2.0.28/quantplay/strategies → quantplay-2.0.29/quantplay/utils}/__init__.py +0 -0
  55. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/utils/constant.py +0 -0
  56. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/utils/exchange.py +0 -0
  57. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/utils/number_utils.py +0 -0
  58. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/utils/pickle_utils.py +0 -0
  59. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/utils/selenium_utils.py +0 -0
  60. {quantplay-2.0.28/quantplay/strategies/equities → quantplay-2.0.29/quantplay/wrapper}/__init__.py +0 -0
  61. {quantplay-2.0.28/quantplay/strategies/equities/intraday → quantplay-2.0.29/quantplay/wrapper/aws}/__init__.py +0 -0
  62. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay/wrapper/aws/s3.py +0 -0
  63. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay.egg-info/dependency_links.txt +0 -0
  64. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay.egg-info/requires.txt +0 -0
  65. {quantplay-2.0.28 → quantplay-2.0.29}/quantplay.egg-info/top_level.txt +0 -0
  66. {quantplay-2.0.28 → quantplay-2.0.29}/setup.cfg +0 -0
  67. {quantplay-2.0.28/quantplay/strategies/equities/overnight → quantplay-2.0.29/tests}/__init__.py +0 -0
  68. {quantplay-2.0.28 → quantplay-2.0.29}/tests/conftest.py +0 -0
  69. {quantplay-2.0.28/quantplay/strategies/futures → quantplay-2.0.29/tests/wrapper}/__init__.py +0 -0
  70. {quantplay-2.0.28/quantplay/strategies/futures/overnight → quantplay-2.0.29/tests/wrapper/aws}/__init__.py +0 -0
  71. {quantplay-2.0.28 → quantplay-2.0.29}/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.28
3
+ Version: 2.0.29
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -3,7 +3,7 @@ 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
@@ -417,13 +417,7 @@ class Aliceblue(Broker):
417
417
  def orders(self, tag: str | None = None, add_ltp: bool = True) -> pl.DataFrame:
418
418
  orders_response = self.invoke_aliceblue_api(self.alice.order_data)
419
419
 
420
- if not isinstance(orders_response, list) and (
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
- ):
420
+ if not isinstance(orders_response, list):
427
421
  return pl.DataFrame(schema=self.orders_schema)
428
422
 
429
423
  if len(orders_response) == 0:
@@ -549,7 +543,7 @@ class Aliceblue(Broker):
549
543
 
550
544
  return orders_df[list(self.orders_schema.keys())].cast(self.orders_schema)
551
545
 
552
- def margins(self):
546
+ def margins(self) -> Dict[str, float]:
553
547
  margins = self.invoke_aliceblue_api(self.alice.get_balance)
554
548
 
555
549
  margins = [a for a in margins if a["segment"] == "ALL"][0]
@@ -567,14 +561,23 @@ class Aliceblue(Broker):
567
561
 
568
562
  return margins
569
563
 
570
- # TODO
571
564
  def invoke_aliceblue_api(self, fn: Callable, *args, **kwargs) -> Any:
572
565
  try:
573
566
  response = fn(*args, **kwargs)
574
567
 
575
568
  if "emsg" in response and "expired" in response["emsg"].lower():
576
569
  raise TokenException("Session expired")
577
- if "stat" in response and response["stat"].lower() == "not_ok":
570
+ elif (
571
+ "stat" in response
572
+ and response["stat"].lower() == "not_ok"
573
+ and (
574
+ "no data" in response["emsg"]
575
+ or "401" in response["emsg"]
576
+ or "404" in response["emsg"]
577
+ )
578
+ ):
579
+ return None
580
+ elif "stat" in response and response["stat"].lower() == "not_ok":
578
581
  raise InvalidArgumentException(response["emsg"])
579
582
  if response is None:
580
583
  raise InvalidArgumentException(
@@ -513,7 +513,7 @@ class AngelOne(Broker):
513
513
 
514
514
  return response
515
515
 
516
- def margins(self):
516
+ def margins(self) -> Dict[str, float]:
517
517
  api_margins = self.invoke_angelone_api(self.wrapper.rmsLimit)
518
518
 
519
519
  if "data" in api_margins and api_margins["data"] is None:
@@ -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
  # **
@@ -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
 
@@ -683,7 +683,7 @@ class Noren(Broker):
683
683
  stop_max_attempt_number=3,
684
684
  retry_on_exception=retry_exception,
685
685
  )
686
- def margins(self) -> Dict:
686
+ def margins(self) -> Dict[str, float]:
687
687
  api_margins = self.invoke_noren_api(self.api.get_limits)
688
688
 
689
689
  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) -> dict:
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
- )["result"]
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"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantplay
3
- Version: 2.0.28
3
+ Version: 2.0.29
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -42,17 +42,6 @@ quantplay/model/__init__.py
42
42
  quantplay/model/broker.py
43
43
  quantplay/model/generics.py
44
44
  quantplay/model/order_event.py
45
- quantplay/strategies/__init__.py
46
- quantplay/strategies/equities/__init__.py
47
- quantplay/strategies/equities/intraday/__init__.py
48
- quantplay/strategies/equities/overnight/__init__.py
49
- quantplay/strategies/futures/__init__.py
50
- quantplay/strategies/futures/overnight/__init__.py
51
- quantplay/strategies/options/__init__.py
52
- quantplay/strategies/options/intraday/__init__.py
53
- quantplay/strategies/options/intraday/ladder.py
54
- quantplay/strategies/options/intraday/musk.py
55
- quantplay/strategies/options/intraday/short_straddle.py
56
45
  quantplay/utils/__init__.py
57
46
  quantplay/utils/constant.py
58
47
  quantplay/utils/exchange.py
@@ -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.28",
24
+ version="2.0.29",
25
25
  setup_requires=["pytest-runner"],
26
26
  install_requires=requirements,
27
27
  tests_require=[],
File without changes
@@ -1,65 +0,0 @@
1
- from quantplay.service import market
2
- import pandas as pd
3
- import time
4
- from quantplay.broker.client import broker_client
5
-
6
- backtest_date = "2022-01-20"
7
-
8
- def load_data(data_date):
9
- # Load data
10
- data = market.data(interval="minute", symbols_by_security_type={"EQ": ["NIFTY BANK"]})
11
- data = data[data.date > "{} 08:15:00".format(data_date)]
12
- data = data[data.date < "{} 15:15:00".format(data_date)]
13
- data.loc[:, "day_of_week"] = data.date.dt.day_name()
14
- data = data[data.date.dt.hour < 17]
15
-
16
- # Add additional attributes
17
- data = market.add_expiry(data, security_type="OPT", days_offset=0)
18
-
19
- return data
20
-
21
- data = load_data(backtest_date)
22
-
23
- data_seq = data.to_dict('records')
24
-
25
- for d in data_seq:
26
- timestamp = d['date']
27
- broker_client.ping(timestamp)
28
- ltp = d['open']
29
- strike_gap = d['strike_gap']
30
- expiry = d['expiry_date']
31
- if timestamp.hour == 9 and timestamp.minute < 30:
32
- print("waiting for market to cool down")
33
- continue
34
-
35
- if timestamp.hour > 13:
36
- print("market is about to close, let's not place any orders")
37
- continue
38
-
39
- orders = broker_client.orders(tag="ladder")
40
-
41
- if len(orders) == 0:
42
- atm = int(round(ltp / strike_gap) * strike_gap)
43
- pe_symbol = broker_client.option_symbol("NIFTY BANK", expiry, atm, "PE")
44
- ce_symbol = broker_client.option_symbol("NIFTY BANK", expiry, atm, "CE")
45
-
46
- broker_client.execute_order(
47
- tradingsymbol=pe_symbol,
48
- exchange="NSE",
49
- quantity=100,
50
- order_type='MARKET',
51
- transaction_type='SELL',
52
- stoploss=0.8,
53
- tag="ladder",
54
- product="NRML"
55
- )
56
- broker_client.execute_order(
57
- tradingsymbol=ce_symbol,
58
- exchange="NSE",
59
- quantity=100,
60
- order_type='MARKET',
61
- transaction_type='SELL',
62
- stoploss=0.8,
63
- tag="ladder",
64
- product="NRML"
65
- )
@@ -1,72 +0,0 @@
1
- from quantplay.strategy.base import QuantplayAlgorithm
2
- from quantplay.utils.constant import TickInterval
3
- from quantplay.service import market
4
- from quantplay.order_execution.mean_price import MeanPriceExecutionAlgo
5
- import numpy as np
6
- import pandas as pd
7
-
8
-
9
- class Musk(QuantplayAlgorithm):
10
- def __init__(self):
11
-
12
- # Mandatory Attributes
13
- self.interval = TickInterval.minute
14
- self.entry_time = "09:29"
15
- self.exit_time = "15:15"
16
- self.strategy_trigger_times = [self.entry_time]
17
- self.exchange_to_trade_on = "NFO"
18
- self.option_nearest_expiry_offset = 0
19
- self.option_chain_depth = 0
20
- self.backtest_after_date = "2021-01-01"
21
- self.backtest_before_date = "2022-02-25"
22
- self.stream_symbols_by_security_type = {"EQ": ["NIFTY BANK"]}
23
- self.columns_for_uuid = ["date", "symbol"]
24
- self.exact_number_of_orders_per_uuid = 2
25
- self.strategy_type = "intraday"
26
- self.strategy_tag = "musk"
27
- self.execution_algo = MeanPriceExecutionAlgo(7)
28
-
29
- self.data_required_for_days = 20
30
-
31
- super(Musk, self).__init__()
32
-
33
- def get_trades(self, market_data):
34
- equity_data = market_data[(market_data.security_type == "EQ") & (market_data.symbol != "SBIN")]
35
-
36
- unique_equity_symbols = list(equity_data.symbol.unique())
37
- assert len(unique_equity_symbols) == 2
38
- assert set(unique_equity_symbols) == {"NIFTY 50", "NIFTY BANK"}
39
-
40
- trades = market.get_trades(equity_data, self.entry_time)
41
-
42
- trades = self.add_expiry(trades, security_type="OPT")
43
- trades.to_csv("/tmp/{}.csv".format(self.strategy_tag))
44
- trades = trades[trades.date.dt.year >= 2019]
45
-
46
- trades = trades[trades.strike_gap > 0]
47
- trades.loc[:, "atm_price"] = (
48
- round(trades.close / trades.strike_gap) * trades.strike_gap
49
- )
50
- trades.loc[:, "atm_price"] = trades.atm_price.astype(int)
51
-
52
- pe_trades = market.option_symbol(
53
- trades, price_column="atm_price", option_type="PE"
54
- )
55
- ce_trades = market.option_symbol(
56
- trades, price_column="atm_price", option_type="CE"
57
- )
58
-
59
- trades = pd.concat([pe_trades, ce_trades])
60
-
61
- trades.loc[:, "day_of_week"] = trades.date.dt.day_name()
62
- trades = trades[trades.day_of_week.isin(["Monday", "Tuesday", "Wednesday", "Thursday"])]
63
-
64
- trades.loc[:, "transaction_type"] = "SELL"
65
- trades.loc[:, "stoploss"] = np.where(trades.symbol == "NIFTY 50", 0.5, 0.8)
66
- trades.loc[:, "quantity"] = np.where(trades.symbol == "NIFTY 50", 100, 50)
67
-
68
- trades = self.filter_uuids_not_matching_count(trades)
69
-
70
- return trades
71
-
72
-
@@ -1,10 +0,0 @@
1
- from quantplay.service import market
2
-
3
- market.broker.execute_order(tradingsymbol="SBIN",
4
- exchange="NSE",
5
- quantity=1,
6
- order_type="MARKET",
7
- transaction_type="BUY",
8
- stoploss=0.03,
9
- tag='straddle',
10
- product="MIS")
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