quantplay 2.1.141__tar.gz → 2.1.142__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 (100) hide show
  1. {quantplay-2.1.141 → quantplay-2.1.142}/PKG-INFO +1 -1
  2. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/zerodha.py +28 -14
  3. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay.egg-info/PKG-INFO +1 -1
  4. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay.egg-info/SOURCES.txt +1 -0
  5. {quantplay-2.1.141 → quantplay-2.1.142}/setup.py +1 -1
  6. quantplay-2.1.142/tests/test_zerodha_positions_add_ltp.py +73 -0
  7. {quantplay-2.1.141 → quantplay-2.1.142}/README.md +0 -0
  8. {quantplay-2.1.141 → quantplay-2.1.142}/pyproject.toml +0 -0
  9. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/__init__.py +0 -0
  10. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/__init__.py +0 -0
  11. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/aliceblue.py +0 -0
  12. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/aliceblue_utils/__init__.py +0 -0
  13. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/aliceblue_utils/aliceblue_oauth.py +0 -0
  14. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/aliceblue_v2.py +0 -0
  15. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/angelone.py +0 -0
  16. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/angelone_utils/__init__.py +0 -0
  17. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/angelone_utils/angeloneWS.py +0 -0
  18. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/auto_login/__init__.py +0 -0
  19. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/breeze/__init__.py +0 -0
  20. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/breeze/breeze_utils.py +0 -0
  21. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/broker_factory.py +0 -0
  22. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/dhan.py +0 -0
  23. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/finvasia_utils/__init__.py +0 -0
  24. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/finvasia_utils/fa_noren.py +0 -0
  25. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/finvasia_utils/finvasia_oauth.py +0 -0
  26. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/five_paisa.py +0 -0
  27. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/flattrade.py +0 -0
  28. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/ft_utils/__init__.py +0 -0
  29. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/ft_utils/flattrade_utils.py +0 -0
  30. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/ft_utils/ft_noren.py +0 -0
  31. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/generics/__init__.py +0 -0
  32. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/generics/broker.py +0 -0
  33. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/icici_direct.py +0 -0
  34. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/iifl_xts.py +0 -0
  35. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/jainam_xts.py +0 -0
  36. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/kite_utils.py +0 -0
  37. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/kotak.py +0 -0
  38. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/kotak_utils/__init__.py +0 -0
  39. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/kotak_utils/kotak_ws.py +0 -0
  40. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/kotak_utils/kotak_ws_lib.py +0 -0
  41. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/motilal.py +0 -0
  42. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/noren.py +0 -0
  43. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/shoonya.py +0 -0
  44. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/uplink/__init__.py +0 -0
  45. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/uplink/uplink_utils.py +0 -0
  46. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/upstox.py +0 -0
  47. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/xts.py +0 -0
  48. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/xts_utils/Connect.py +0 -0
  49. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/xts_utils/Exception.py +0 -0
  50. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
  51. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/xts_utils/__init__.py +0 -0
  52. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/xts_utils_v2/ConnectV2.py +0 -0
  53. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/xts_utils_v2/InteractiveSocketClientV2.py +0 -0
  54. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/broker/xts_utils_v2/__init__.py +0 -0
  55. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/core/__init__.py +0 -0
  56. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/core/strategy.py +0 -0
  57. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/exception/__init__.py +0 -0
  58. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/exception/exceptions.py +0 -0
  59. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/indicator/__init__.py +0 -0
  60. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/indicator/iv.py +0 -0
  61. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/model/__init__.py +0 -0
  62. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/model/broker.py +0 -0
  63. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/model/broker_response.py +0 -0
  64. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/model/generics.py +0 -0
  65. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/model/instrument_data.py +0 -0
  66. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/model/order_event.py +0 -0
  67. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/py.typed +0 -0
  68. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/strategy/__init__.py +0 -0
  69. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/strategy/iv_spike.py +0 -0
  70. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/strategy/obuy.py +0 -0
  71. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/utils/__init__.py +0 -0
  72. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/utils/caching.py +0 -0
  73. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/utils/constant.py +0 -0
  74. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/utils/exchange.py +0 -0
  75. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/utils/number_utils.py +0 -0
  76. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/utils/pickle_utils.py +0 -0
  77. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/utils/redaction.py +0 -0
  78. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/utils/selenium_utils.py +0 -0
  79. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/wrapper/__init__.py +0 -0
  80. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/wrapper/aws/__init__.py +0 -0
  81. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/wrapper/aws/s3.py +0 -0
  82. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay/wrapper/redis.py +0 -0
  83. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay.egg-info/dependency_links.txt +0 -0
  84. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay.egg-info/requires.txt +0 -0
  85. {quantplay-2.1.141 → quantplay-2.1.142}/quantplay.egg-info/top_level.txt +0 -0
  86. {quantplay-2.1.141 → quantplay-2.1.142}/setup.cfg +0 -0
  87. {quantplay-2.1.141 → quantplay-2.1.142}/tests/__init__.py +0 -0
  88. {quantplay-2.1.141 → quantplay-2.1.142}/tests/conftest.py +0 -0
  89. {quantplay-2.1.141 → quantplay-2.1.142}/tests/test_aliceblue_unified.py +0 -0
  90. {quantplay-2.1.141 → quantplay-2.1.142}/tests/test_deltax_positions.py +0 -0
  91. {quantplay-2.1.141 → quantplay-2.1.142}/tests/test_deltax_root_url.py +0 -0
  92. {quantplay-2.1.141 → quantplay-2.1.142}/tests/test_jainam_xts.py +0 -0
  93. {quantplay-2.1.141 → quantplay-2.1.142}/tests/test_kotak_order_feed_url.py +0 -0
  94. {quantplay-2.1.141 → quantplay-2.1.142}/tests/test_log_redaction.py +0 -0
  95. {quantplay-2.1.141 → quantplay-2.1.142}/tests/test_motilal_login.py +0 -0
  96. {quantplay-2.1.141 → quantplay-2.1.142}/tests/test_sub_client_all_types.py +0 -0
  97. {quantplay-2.1.141 → quantplay-2.1.142}/tests/test_xts_v2_modify_order.py +0 -0
  98. {quantplay-2.1.141 → quantplay-2.1.142}/tests/wrapper/__init__.py +0 -0
  99. {quantplay-2.1.141 → quantplay-2.1.142}/tests/wrapper/aws/__init__.py +0 -0
  100. {quantplay-2.1.141 → quantplay-2.1.142}/tests/wrapper/aws/s3_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quantplay
3
- Version: 2.1.141
3
+ Version: 2.1.142
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -461,26 +461,40 @@ class Zerodha(Broker):
461
461
  positions_df = positions_df.with_columns(
462
462
  (pl.col("exchange") + ":" + pl.col("tradingsymbol")).alias("exchange_symbol")
463
463
  )
464
- symbols = (
465
- positions_df.select(pl.col("exchange_symbol").unique()).to_series().to_list()
466
- )
467
- symbol_ltps = self.get_ltps(symbols)
468
- ltp_map: dict[str, float] = {}
469
- for exchange_symbol in symbol_ltps:
470
- ltp_map[exchange_symbol] = float(symbol_ltps[exchange_symbol]["last_price"])
464
+ if add_ltp:
465
+ symbols = (
466
+ positions_df.select(pl.col("exchange_symbol").unique())
467
+ .to_series()
468
+ .to_list()
469
+ )
470
+ symbol_ltps = self.get_ltps(symbols)
471
+ ltp_map: dict[str, float] = {}
472
+ for exchange_symbol in symbol_ltps:
473
+ ltp_map[exchange_symbol] = float(
474
+ symbol_ltps[exchange_symbol]["last_price"]
475
+ )
471
476
 
472
- positions_df = positions_df.with_columns(
473
- pl.col("exchange_symbol")
474
- .replace_strict(ltp_map, default=0.0)
475
- .cast(pl.Float64)
476
- .alias("ltp")
477
- )
477
+ positions_df = positions_df.with_columns(
478
+ pl.col("exchange_symbol")
479
+ .replace_strict(ltp_map, default=0.0)
480
+ .cast(pl.Float64)
481
+ .alias("ltp")
482
+ )
483
+ else:
484
+ # kite.ltp() needs a paid market-data subscription; callers that only
485
+ # display positions skip it and fill live prices themselves.
486
+ positions_df = positions_df.with_columns(
487
+ pl.lit(None).cast(pl.Float64).alias("ltp")
488
+ )
478
489
 
479
490
  positions_df = positions_df.with_columns(
480
491
  (pl.col("sell_value") - pl.col("buy_value")).alias("pnl")
481
492
  )
482
493
  positions_df = positions_df.with_columns(
483
- (pl.col("quantity") * pl.col("ltp") + pl.col("pnl")).alias("pnl")
494
+ pl.when(pl.col("quantity") == 0)
495
+ .then(pl.col("pnl"))
496
+ .otherwise(pl.col("quantity") * pl.col("ltp") + pl.col("pnl"))
497
+ .alias("pnl")
484
498
  )
485
499
 
486
500
  positions_df = positions_df.with_columns(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quantplay
3
- Version: 2.1.141
3
+ Version: 2.1.142
4
4
  Summary: This python package will be stored in AWS CodeArtifact
5
5
  Home-page:
6
6
  Author:
@@ -92,6 +92,7 @@ tests/test_log_redaction.py
92
92
  tests/test_motilal_login.py
93
93
  tests/test_sub_client_all_types.py
94
94
  tests/test_xts_v2_modify_order.py
95
+ tests/test_zerodha_positions_add_ltp.py
95
96
  tests/wrapper/__init__.py
96
97
  tests/wrapper/aws/__init__.py
97
98
  tests/wrapper/aws/s3_test.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.1.141",
24
+ version="2.1.142",
25
25
  install_requires=requirements,
26
26
  tests_require=[],
27
27
  packages=find_packages(),
@@ -0,0 +1,73 @@
1
+ from typing import Any
2
+ from unittest.mock import MagicMock
3
+
4
+ import polars as pl
5
+ import pytest
6
+
7
+ from quantplay.broker.zerodha import Zerodha
8
+ from quantplay.exception.exceptions import TokenException
9
+
10
+
11
+ def _position(symbol: str, quantity: int, buy: float, sell: float) -> dict[str, Any]:
12
+ return {
13
+ "tradingsymbol": symbol,
14
+ "exchange": "NFO",
15
+ "product": "NRML",
16
+ "quantity": quantity,
17
+ "average_price": 100.0,
18
+ "buy_quantity": 50,
19
+ "sell_quantity": 50 - quantity,
20
+ "buy_value": buy,
21
+ "sell_value": sell,
22
+ "buy_price": 100.0,
23
+ "sell_price": 100.0,
24
+ }
25
+
26
+
27
+ @pytest.fixture
28
+ def broker() -> Zerodha:
29
+ zerodha = object.__new__(Zerodha)
30
+ zerodha.wrapper = MagicMock()
31
+ zerodha.invoke_kite_api = MagicMock( # type: ignore[method-assign]
32
+ return_value={
33
+ "net": [
34
+ _position("NIFTY26N0624000CE", 50, 5000.0, 0.0),
35
+ _position("NIFTY26N0624000PE", 0, 5000.0, 6000.0),
36
+ ]
37
+ }
38
+ )
39
+ zerodha.symbol_attribute = MagicMock(return_value=123) # type: ignore[method-assign]
40
+ return zerodha
41
+
42
+
43
+ def test_add_ltp_false_skips_market_data_call(broker: Zerodha) -> None:
44
+ # kite.ltp() fails without a market-data subscription; add_ltp=False must not call it
45
+ broker.get_ltps = MagicMock( # type: ignore[method-assign]
46
+ side_effect=TokenException("LTP Calls Require Market Data Subscription")
47
+ )
48
+
49
+ positions = broker.positions(add_ltp=False)
50
+
51
+ broker.get_ltps.assert_not_called()
52
+ rows = {r["tradingsymbol"]: r for r in positions.to_dicts()}
53
+ assert rows["NIFTY26N0624000CE"]["ltp"] is None
54
+ assert rows["NIFTY26N0624000CE"]["pnl"] is None
55
+ assert rows["NIFTY26N0624000PE"]["ltp"] is None
56
+ assert rows["NIFTY26N0624000PE"]["pnl"] == 1000.0
57
+
58
+
59
+ def test_add_ltp_true_unchanged(broker: Zerodha) -> None:
60
+ broker.get_ltps = MagicMock( # type: ignore[method-assign]
61
+ return_value={
62
+ "NFO:NIFTY26N0624000CE": {"last_price": 120.0},
63
+ "NFO:NIFTY26N0624000PE": {"last_price": 80.0},
64
+ }
65
+ )
66
+
67
+ positions = broker.positions(add_ltp=True)
68
+
69
+ rows = {r["tradingsymbol"]: r for r in positions.to_dicts()}
70
+ assert rows["NIFTY26N0624000CE"]["ltp"] == 120.0
71
+ assert rows["NIFTY26N0624000CE"]["pnl"] == 50 * 120.0 - 5000.0
72
+ assert rows["NIFTY26N0624000PE"]["pnl"] == 1000.0
73
+ assert positions.schema == pl.Schema(broker.positions_schema)
File without changes
File without changes
File without changes