tradx 0.9__tar.gz → 0.9.2__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 (59) hide show
  1. {tradx-0.9 → tradx-0.9.2}/PKG-INFO +1 -1
  2. tradx-0.9.2/examples/example3.py +329 -0
  3. {tradx-0.9 → tradx-0.9.2}/pyproject.toml +1 -1
  4. {tradx-0.9 → tradx-0.9.2}/test/test_candleData.py +1 -1
  5. {tradx-0.9 → tradx-0.9.2}/test/test_ltpData.py +1 -1
  6. {tradx-0.9 → tradx-0.9.2}/test/test_ltpPartailData.py +1 -1
  7. {tradx-0.9 → tradx-0.9.2}/test/test_marketDepthData.py +1 -1
  8. {tradx-0.9 → tradx-0.9.2}/test/test_marketStatusData.py +1 -1
  9. {tradx-0.9 → tradx-0.9.2}/test/test_openInterestData.py +1 -1
  10. {tradx-0.9 → tradx-0.9.2}/test/test_openInterestPartialData.py +1 -1
  11. {tradx-0.9 → tradx-0.9.2}/test/test_option.py +1 -1
  12. {tradx-0.9 → tradx-0.9.2}/test/test_orderEvent.py +1 -1
  13. {tradx-0.9 → tradx-0.9.2}/test/test_positionEvent.py +1 -1
  14. {tradx-0.9 → tradx-0.9.2}/test/test_touchLineData.py +1 -1
  15. {tradx-0.9 → tradx-0.9.2}/test/test_tradeConversionEvent.py +1 -1
  16. {tradx-0.9 → tradx-0.9.2}/test/test_tradeEvent.py +1 -1
  17. {tradx-0.9 → tradx-0.9.2}/.gitignore +0 -0
  18. {tradx-0.9 → tradx-0.9.2}/.vscode/settings.json +0 -0
  19. {tradx-0.9 → tradx-0.9.2}/README.md +0 -0
  20. {tradx-0.9 → tradx-0.9.2}/examples/example1.log +0 -0
  21. {tradx-0.9 → tradx-0.9.2}/examples/example1.py +0 -0
  22. {tradx-0.9 → tradx-0.9.2}/examples/example2.log +0 -0
  23. {tradx-0.9 → tradx-0.9.2}/examples/example2.py +0 -0
  24. {tradx-0.9 → tradx-0.9.2}/src/tradx/__init__.py +0 -0
  25. {tradx-0.9 → tradx-0.9.2}/src/tradx/algoContainer.py +0 -0
  26. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/baseAlgo.py +0 -0
  27. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/interactive/order.py +0 -0
  28. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/interactive/orderEvent.py +0 -0
  29. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/interactive/position.py +0 -0
  30. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/interactive/positionEvent.py +0 -0
  31. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/interactive/tradeConversionEvent.py +0 -0
  32. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/interactive/tradeEvent.py +0 -0
  33. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/candleData.py +0 -0
  34. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/cmInstrument.py +0 -0
  35. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/futureInstrument.py +0 -0
  36. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/index.py +0 -0
  37. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/instrumentPropertyChangeData.py +0 -0
  38. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/ltpData.py +0 -0
  39. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/ltpPartialData.py +0 -0
  40. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/marketDepthData.py +0 -0
  41. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/marketStatusData.py +0 -0
  42. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/openInterestData.py +0 -0
  43. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/openInterestPartialData.py +0 -0
  44. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/optionsInstrument.py +0 -0
  45. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/touchLineData.py +0 -0
  46. {tradx-0.9 → tradx-0.9.2}/src/tradx/baseClass/market/touchLinePartialData.py +0 -0
  47. {tradx-0.9 → tradx-0.9.2}/src/tradx/constants/holidays.py +0 -0
  48. {tradx-0.9 → tradx-0.9.2}/src/tradx/dualHashMap.py +0 -0
  49. {tradx-0.9 → tradx-0.9.2}/src/tradx/interactiveEngine.py +0 -0
  50. {tradx-0.9 → tradx-0.9.2}/src/tradx/logger/logger.py +0 -0
  51. {tradx-0.9 → tradx-0.9.2}/src/tradx/logger/logger2.py +0 -0
  52. {tradx-0.9 → tradx-0.9.2}/src/tradx/marketDataEngine.py +0 -0
  53. {tradx-0.9 → tradx-0.9.2}/src/tradx/py.typed +0 -0
  54. {tradx-0.9 → tradx-0.9.2}/test/test_interactiveEngine.log +0 -0
  55. {tradx-0.9 → tradx-0.9.2}/test/test_interactiveEngine.py +0 -0
  56. {tradx-0.9 → tradx-0.9.2}/test/test_logger.log +0 -0
  57. {tradx-0.9 → tradx-0.9.2}/test/test_logger.py +0 -0
  58. {tradx-0.9 → tradx-0.9.2}/test/test_marketDataEngine.log +0 -0
  59. {tradx-0.9 → tradx-0.9.2}/test/test_marketDataEngine.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tradx
3
- Version: 0.9
3
+ Version: 0.9.2
4
4
  Summary: A Package Designed to simplify strategy development on package xts-api-client
5
5
  Author-email: "jatin.kumawat" <jatin.kumawat@rmoneyindia.com>
6
6
  Requires-Python: >=3.12
@@ -0,0 +1,329 @@
1
+ # Importing modules from tradx
2
+ from tradx.marketDataEngine import marketDataEngine
3
+ from tradx.interactiveEngine import interactiveEngine
4
+ from tradx.baseClass.baseAlgo import BaseAlgo
5
+ from tradx.baseClass.market.candleData import CandleData
6
+ from tradx.baseClass.market.index import Index
7
+ from tradx.baseClass.market.optionsInstrument import OptionsInstrument, OptionType
8
+ from tradx.baseClass.interactive.orderEvent import OrderEvent
9
+ from tradx.baseClass.interactive.tradeEvent import TradeEvent
10
+ from tradx.baseClass.interactive.order import Order
11
+ from tradx.baseClass.interactive.position import Position
12
+ from tradx.logger.logger import setup_user_logger
13
+ from tradx.constants.holidays import holidays
14
+
15
+ # Importing other necessary modules
16
+ import asyncio
17
+ import os
18
+ from apscheduler.schedulers.asyncio import AsyncIOScheduler
19
+ from datetime import datetime, timedelta
20
+ from typing import List, Any
21
+ from decimal import Decimal
22
+
23
+ """
24
+ This script demonstrates the implementation of two example algorithmic trading strategies using the `tradx` library.
25
+ It includes the following components:
26
+ Classes:
27
+ - Example1: An example trading algorithm that places a market order on current week expiry nifty call at-the-money.
28
+ Functions:
29
+ - main: The main asynchronous function that initializes the trading environment, sets up logging, and schedules the execution of the example algorithms.
30
+ Usage:
31
+ - The script loads environment variables from a .env file.
32
+ - It sets up a user logger to log trading activities.
33
+ - It initializes the market data engine and interactive engine using API keys and other configurations from the environment variables.
34
+ - It creates instances of Example1 and Example2 algorithms.
35
+ - It schedules the initialization and liquidation of the algorithms using the AsyncIOScheduler.
36
+ - It waits for user input to exit the script.
37
+ Dependencies:
38
+ - tradx.marketDataEngine
39
+ - tradx.interactiveEngine
40
+ - tradx.baseClass.baseAlgo
41
+ - tradx.baseClass.candleData
42
+ - tradx.baseClass.orderEvent
43
+ - tradx.baseClass.tradeEvent
44
+ - tradx.baseClass.order
45
+ - tradx.baseClass.position
46
+ - tradx.logger.logger
47
+ - asyncio
48
+ - os
49
+ - dotenv
50
+ - apscheduler.schedulers.asyncio
51
+ - datetime
52
+ To run the script, execute it as a standalone Python file.
53
+ """
54
+
55
+
56
+ async def exit_input(
57
+ exit_event: asyncio.Event,
58
+ ):
59
+ """Waits for user input to exit the program."""
60
+ x = ""
61
+ event_wait_task = asyncio.ensure_future(exit_event.wait())
62
+ while x != "exit" and (not exit_event.is_set()):
63
+ try:
64
+ io_task = asyncio.ensure_future(ainput("Type 'exit' to exit\n"))
65
+ done, pending = await asyncio.wait(
66
+ [io_task, event_wait_task], return_when=asyncio.FIRST_COMPLETED
67
+ )
68
+ if event_wait_task in done:
69
+ io_task.cancel()
70
+ else:
71
+ x = done.pop().result()
72
+ if x == "exit":
73
+ exit_event.set()
74
+ except asyncio.CancelledError:
75
+ pass
76
+ print("Gracefully exiting the algorithm.")
77
+ exit_event.set()
78
+
79
+
80
+ class SIndex:
81
+ """Class to manage index options and calculate strike prices based on given values and strike gaps."""
82
+
83
+ def __init__(
84
+ self,
85
+ symbol: Index,
86
+ strikegap: Decimal,
87
+ value: Decimal,
88
+ lot_size: int,
89
+ optionChain: List[OptionsInstrument] = [],
90
+ ) -> None:
91
+ self._symbol: Index = symbol
92
+ self._strikegap: Decimal = strikegap
93
+ self._value: Decimal = value
94
+ self._lot_size: int = lot_size
95
+ self._strike: int = 0
96
+ self._prev_strike: int = None # To store the previous strike value
97
+ self._optionChain: List[OptionsInstrument] = optionChain
98
+
99
+ @property
100
+ def symbol(self) -> Index:
101
+ return self._symbol
102
+
103
+ @property
104
+ def lot_size(self) -> int:
105
+ return self._lot_size
106
+
107
+ @symbol.setter
108
+ def symbol(self, value) -> None:
109
+ if not isinstance(value, Index):
110
+ raise ValueError("Symbol must be a tradx.baseClass.Index.Index")
111
+ self._symbol = value
112
+
113
+ @property
114
+ def strikegap(self) -> Decimal:
115
+ return self._strikegap
116
+
117
+ @strikegap.setter
118
+ def strikegap(self, value) -> None:
119
+ self._strikegap = value
120
+
121
+ @property
122
+ def value(self) -> Decimal:
123
+ return self._value
124
+
125
+ @value.setter
126
+ def value(self, value: Any) -> None:
127
+ """
128
+ Sets the value and calculates the strike price based on the given value.
129
+ Args:
130
+ value (Any): The value to be set. It will be converted to a Decimal.
131
+ Sets:
132
+ self._value (Decimal): The value converted to a Decimal.
133
+ self._strike (int): The calculated strike price based on the value and strike gap.
134
+ """
135
+
136
+ self._value = Decimal(value)
137
+ strike = int(self._strikegap * round(self._value / self._strikegap))
138
+ self._strike = strike
139
+
140
+ @property
141
+ def strike(self) -> int:
142
+ return self._strike
143
+
144
+ @property
145
+ def previous_strike(self) -> int:
146
+ """Returns the previous calculated strike value."""
147
+ return self._previous_strike
148
+
149
+ @property
150
+ def has_changed(self) -> bool:
151
+ """Checks if the strike value has changed."""
152
+ return self.previous_strike != self.strike
153
+
154
+ @property
155
+ def optionChain(self) -> List[OptionsInstrument]:
156
+ return self._optionChain
157
+
158
+ @optionChain.setter
159
+ def optionChain(self, value: List[OptionsInstrument]) -> None:
160
+ if not isinstance(value, List):
161
+ raise ValueError("OptionChain must be a list")
162
+ self._optionChain = value
163
+
164
+ def search_option(
165
+ self,
166
+ StrikePrice: int = None,
167
+ OptionType: int = None,
168
+ ExchangeInstrumentID: int = None,
169
+ ) -> List[OptionsInstrument]:
170
+ """
171
+ Search for options based on specified criteria.
172
+ Args:
173
+ StrikePrice (int, optional): The strike price of the option. Must be an integer.
174
+ OptionType (int, optional): The type of the option. Must be an integer.
175
+ Returns:
176
+ List[OptionsInstrument]: A list of options that match the specified criteria.
177
+ If no criteria are specified, returns the entire option chain.
178
+ Raises:
179
+ AssertionError: If StrikePrice or OptionType are not integers.
180
+ """
181
+ assert StrikePrice is None or isinstance(
182
+ StrikePrice, int
183
+ ), "StrikePrice must be an integer"
184
+ assert OptionType is None or isinstance(
185
+ OptionType, int
186
+ ), "OptionType must be an integer"
187
+
188
+ criteria = {
189
+ "StrikePrice": StrikePrice,
190
+ "OptionType": OptionType,
191
+ "ExchangeInstrumentID": ExchangeInstrumentID,
192
+ }
193
+ criteria = {k: v for k, v in criteria.items() if v is not None}
194
+
195
+ if not criteria:
196
+ return self._optionChain
197
+
198
+ results = self._optionChain
199
+ for key, value in criteria.items():
200
+ results = [option for option in results if getattr(option, key) == value]
201
+
202
+ return results
203
+
204
+ def update_previous(self) -> None:
205
+ self._previous_strike = self._strike
206
+
207
+ def end(self) -> None:
208
+ self._optionChain.clear()
209
+
210
+
211
+ class Example1(BaseAlgo):
212
+ def __init__(
213
+ self, marketDataEngine: marketDataEngine, interactiveEngine: interactiveEngine
214
+ ):
215
+ super().__init__(marketDataEngine, interactiveEngine)
216
+ self.nifty = SIndex(None, 50, 0, 75)
217
+ self.marketDataEngine = marketDataEngine
218
+ self.interactiveEngine = interactiveEngine
219
+
220
+ async def initialize(self):
221
+ options = await self.marketDataEngine.option_search(
222
+ UnderlyingIndexName=self.nifty.symbol.Name, minimumExpiry=True
223
+ )
224
+ self.nifty.optionChain = options
225
+ instruments = []
226
+ instruments.append(
227
+ {
228
+ "exchangeSegment": self.nifty.symbol.ExchangeSegment,
229
+ "exchangeInstrumentID": self.nifty.symbol.ExchangeInstrumentID,
230
+ }
231
+ )
232
+ _list = await self.marketDataEngine.fetch_ltp(instruments)
233
+ nifty_index_data = next(
234
+ item
235
+ for item in _list
236
+ if item.ExchangeInstrumentID == self.nifty.symbol.ExchangeInstrumentID
237
+ )
238
+ self.nifty.value = nifty_index_data.LastTradedPrice
239
+ print(f"Nifty index value: {self.nifty.value}")
240
+ instruments.clear()
241
+ nifty_call_atm = self.nifty.search_option(
242
+ StrikePrice=self.nifty.strike,
243
+ OptionType=OptionType.CE.value,
244
+ )[0]
245
+ asyncio.ensure_future(
246
+ self.interactiveEngine.market_order(
247
+ self.interactiveEngine.xt.EXCHANGE_NSEFO,
248
+ nifty_call_atm.ExchangeInstrumentID,
249
+ "NRML",
250
+ -1 * self.nifty.lot_size,
251
+ self.order_no(),
252
+ )
253
+ )
254
+
255
+ async def deinitialize(self):
256
+ asyncio.ensure_future(self.unsubscribe())
257
+
258
+ async def on_barData(self, data: CandleData):
259
+ """Expected Bar data here."""
260
+ self.marketDataEngine.user_logger.info(
261
+ f"Received the bar: {data}", caller=f"{self.__class__.__name__}.on_data"
262
+ )
263
+
264
+ async def on_orderEvent(self, order: OrderEvent):
265
+ self.interactiveEngine.user_logger.info(
266
+ f"Received order event: {order}",
267
+ caller=f"{self.__class__.__name__}.on_orderEvent",
268
+ )
269
+
270
+ async def on_tradeEvent(self, trade: TradeEvent):
271
+ self.interactiveEngine.user_logger.info(
272
+ f"Received trade event: {trade}",
273
+ caller=f"{self.__class__.__name__}.on_tradeEvent",
274
+ )
275
+
276
+ async def subscribe(self): ...
277
+ async def unsubscribe(self): ...
278
+
279
+
280
+
281
+ async def main():
282
+ log_file_path = os.path.join(os.path.dirname(__file__), "TEST.log")
283
+ if os.path.exists(log_file_path):
284
+ os.remove(log_file_path)
285
+ user_logger = setup_user_logger(log_file_path)
286
+ scheduler = AsyncIOScheduler()
287
+ scheduler.start()
288
+ exit_event = asyncio.Event()
289
+ tradeObject = marketDataEngine(
290
+ "MARKETDATA_API_KEY",
291
+ "MARKETDATA_API_SECRET",
292
+ "SOURCE",
293
+ "ROOT",
294
+ user_logger,
295
+ )
296
+
297
+ interactiveObj = interactiveEngine(
298
+ "INTERACTIVE_API_KEY",
299
+ "INTERACTIVE_API_SECRET",
300
+ "SOURCE",
301
+ "ROOT",
302
+ user_logger,
303
+ )
304
+
305
+ await interactiveObj.initialize()
306
+ await tradeObject.loadMaster()
307
+ algo1 = Example1(tradeObject, interactiveObj)
308
+ scheduler.add_job(
309
+ algo1.initialize, "date", run_date=datetime.now() + timedelta(seconds=20)
310
+ )
311
+ scheduler.add_job(
312
+ algo1.liquidateIntraday(), "date", run_date=datetime.now() + timedelta(seconds=40)
313
+ )
314
+
315
+ _input_task = asyncio.ensure_future(exit_input(exit_event))
316
+ await exit_event.wait()
317
+ await tradeObject.shutdown()
318
+ await interactiveObj.shutdown()
319
+
320
+
321
+ if __name__ == "__main__":
322
+ try:
323
+ """Entering only if today is not a holiday"""
324
+ _today = datetime.today().date()
325
+ if _today in holidays:
326
+ os._exit(0)
327
+ asyncio.run(main())
328
+ except KeyboardInterrupt:
329
+ print("\n❌ Exiting...")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tradx"
3
- version = "0.9"
3
+ version = "0.9.2"
4
4
  description = "A Package Designed to simplify strategy development on package xts-api-client"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.candleData import CandleData
1
+ from tradx.baseClass.market.candleData import CandleData
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.ltpData import LtpData
1
+ from tradx.baseClass.market.ltpData import LtpData
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.ltpPartialData import LtpPartialData
1
+ from tradx.baseClass.market.ltpPartialData import LtpPartialData
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.marketDepthData import MarketDepthData
1
+ from tradx.baseClass.market.marketDepthData import MarketDepthData
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.marketStatusData import MarketStatusData
1
+ from tradx.baseClass.market.marketStatusData import MarketStatusData
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.openInterestData import OpenInterestData
1
+ from tradx.baseClass.market.openInterestData import OpenInterestData
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.openInterestPartialData import OpenInterestPartialData
1
+ from tradx.baseClass.market.openInterestPartialData import OpenInterestPartialData
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,5 +1,5 @@
1
1
  import pandas as pd
2
- from tradx.baseClass.optionsInstrument import OptionManager
2
+ from tradx.baseClass.market.optionsInstrument import OptionManager
3
3
  from datetime import datetime
4
4
 
5
5
 
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.orderEvent import OrderEvent
1
+ from tradx.baseClass.interactive.orderEvent import OrderEvent
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.positionEvent import PositionEvent
1
+ from tradx.baseClass.interactive.positionEvent import PositionEvent
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.touchLineData import TouchLineData
1
+ from tradx.baseClass.market.touchLineData import TouchLineData
2
2
 
3
3
 
4
4
  def test_fromString_1():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.tradeConversionEvent import TradeConversionEvent
1
+ from tradx.baseClass.interactive.tradeConversionEvent import TradeConversionEvent
2
2
 
3
3
 
4
4
  def test_fromString():
@@ -1,4 +1,4 @@
1
- from tradx.baseClass.tradeEvent import TradeEvent
1
+ from tradx.baseClass.interactive.tradeEvent import TradeEvent
2
2
 
3
3
 
4
4
  def test_fromString():
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