PyAlgoEngine 0.8.0a1__tar.gz → 0.8.0a2__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 (54) hide show
  1. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/PKG-INFO +1 -1
  2. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/PyAlgoEngine.egg-info/PKG-INFO +1 -1
  3. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/__init__.py +1 -1
  4. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/market_data_wrapper.py +70 -134
  5. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/LICENSE +0 -0
  6. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/PyAlgoEngine.egg-info/SOURCES.txt +0 -0
  7. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/PyAlgoEngine.egg-info/dependency_links.txt +0 -0
  8. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/PyAlgoEngine.egg-info/requires.txt +0 -0
  9. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/PyAlgoEngine.egg-info/top_level.txt +0 -0
  10. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/README.md +0 -0
  11. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/__init__.py +0 -0
  12. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/backtest/__init__.py +0 -0
  13. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/backtest/doc_server.py +0 -0
  14. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/backtest/tester.py +0 -0
  15. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/backtest/web_app.py +0 -0
  16. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/bokeh_server.py +0 -0
  17. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/demo/__init__.py +0 -0
  18. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/demo/test.py +0 -0
  19. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/sim_input/__init__.py +0 -0
  20. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/sim_input/client.py +0 -0
  21. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/sim_input/sim_keyboard.py +0 -0
  22. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/sim_input/sim_mouse.py +0 -0
  23. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/apps/sim_input/window.py +0 -0
  24. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/backtest/__init__.py +0 -0
  25. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/backtest/__main__.py +0 -0
  26. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/backtest/metrics.py +0 -0
  27. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/backtest/replay.py +0 -0
  28. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/backtest/sim_match.py +0 -0
  29. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/__init__.py +0 -0
  30. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/console_utils.py +0 -0
  31. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/finance_decimal.py +0 -0
  32. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/market_buffer.py +0 -0
  33. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/market_utils.py +0 -0
  34. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/market_utils_nt.py +0 -0
  35. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/market_utils_posix.py +0 -0
  36. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/technical_analysis.py +0 -0
  37. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/telemetrics.py +0 -0
  38. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/base/trade_utils.py +0 -0
  39. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/engine/__init__.py +0 -0
  40. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/engine/algo_engine.py +0 -0
  41. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/engine/event_engine.py +0 -0
  42. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/engine/market_engine.py +0 -0
  43. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/engine/trade_engine.py +0 -0
  44. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/monitor/__init__.py +0 -0
  45. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/monitor/advanced_data_interface.py +0 -0
  46. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/profile/__init__.py +0 -0
  47. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/profile/cn.py +0 -0
  48. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/strategy/__init__.py +0 -0
  49. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/strategy/strategy_engine.py +0 -0
  50. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/utils/__init__.py +0 -0
  51. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/utils/commit_regularizer.py +0 -0
  52. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/algo_engine/utils/data_utils.py +0 -0
  53. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/setup.cfg +0 -0
  54. {pyalgoengine-0.8.0a1 → pyalgoengine-0.8.0a2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAlgoEngine
3
- Version: 0.8.0a1
3
+ Version: 0.8.0a2
4
4
  Summary: Basic algo engine
5
5
  Home-page: https://github.com/BolunHan/PyAlgoEngine
6
6
  Author: Bolun.Han
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAlgoEngine
3
- Version: 0.8.0a1
3
+ Version: 0.8.0a2
4
4
  Summary: Basic algo engine
5
5
  Home-page: https://github.com/BolunHan/PyAlgoEngine
6
6
  Author: Bolun.Han
@@ -1,4 +1,4 @@
1
- __version__ = "0.8.0.alpha1"
1
+ __version__ = "0.8.0.alpha2"
2
2
 
3
3
  import logging
4
4
  import os
@@ -1,81 +1,67 @@
1
1
  import abc
2
2
  import datetime
3
3
  import enum
4
- import inspect
5
- from typing import TypeVar, Any, Self, Literal
6
4
  import logging
5
+ from typing import Self, Literal
6
+
7
+ import candlestick as candlestick_cython
7
8
  import market_data as market_data_cython
9
+ import transaction as transaction_cython
8
10
 
9
11
  LOGGER = logging.getLogger(__name__)
10
12
  from algo_engine.profile import PROFILE
11
13
 
12
14
 
15
+ class Direction(enum.IntEnum):
16
+ DIRECTION_UNKNOWN = 1
17
+ DIRECTION_SHORT = 0
18
+ DIRECTION_LONG = 2
19
+
20
+
21
+ class Offset(enum.IntEnum):
22
+ OFFSET_CANCEL = 0
23
+ OFFSET_ORDER = 4
24
+ OFFSET_OPEN = 8
25
+ OFFSET_CLOSE = 16
26
+
27
+
13
28
  class TransactionSide(enum.IntEnum):
14
- ShortOrder = AskOrder = Offer_to_Short = -3
15
- ShortOpen = Sell_to_Short = -2
16
- ShortFilled = LongClose = Sell_to_Unwind = ask = -1
17
- UNKNOWN = CANCEL = 0
18
- LongFilled = LongOpen = Buy_to_Long = bid = 1
19
- ShortClose = Buy_to_Cover = 2
20
- LongOrder = BidOrder = Bid_to_Long = 3
29
+ # Long Side
30
+ SIDE_LONG_OPEN = Direction.DIRECTION_LONG + Offset.OFFSET_OPEN # 2 + 8 = 10
31
+ SIDE_LONG_CLOSE = Direction.DIRECTION_LONG + Offset.OFFSET_CLOSE # 2 + 16 = 18
32
+ SIDE_LONG_CANCEL = Direction.DIRECTION_LONG + Offset.OFFSET_CANCEL # 2 + 0 = 2
21
33
 
22
- def __neg__(self) -> Self:
23
- """
24
- Get the opposite transaction side.
34
+ # Short Side
35
+ SIDE_SHORT_OPEN = Direction.DIRECTION_SHORT + Offset.OFFSET_OPEN # 0 + 8 = 8
36
+ SIDE_SHORT_CLOSE = Direction.DIRECTION_SHORT + Offset.OFFSET_CLOSE # 0 + 16 = 16
37
+ SIDE_SHORT_CANCEL = Direction.DIRECTION_SHORT + Offset.OFFSET_CANCEL # 0 + 0 = 0
25
38
 
26
- Returns:
27
- TransactionSide: The opposite transaction side.
28
- """
29
- if self is self.LongOpen:
30
- return self.LongClose
31
- elif self is self.LongClose:
32
- return self.LongOpen
33
- elif self is self.ShortOpen:
34
- return self.ShortClose
35
- elif self is self.ShortClose:
36
- return self.ShortOpen
37
- elif self is self.BidOrder:
38
- return self.AskOrder
39
- elif self is self.AskOrder:
40
- return self.BidOrder
41
- else:
42
- LOGGER.warning('No valid registered opposite trade side for {}'.format(self))
43
- return self.UNKNOWN
39
+ # Order
40
+ SIDE_BID = Direction.DIRECTION_LONG + Offset.OFFSET_ORDER # 2 + 4 = 6
41
+ SIDE_ASK = Direction.DIRECTION_SHORT + Offset.OFFSET_ORDER # 0 + 4 = 4
44
42
 
45
- @classmethod
46
- def from_offset(cls, direction: str, offset: str) -> Self:
47
- """
48
- Determine the transaction side from direction and offset.
43
+ # Generic Cancel
44
+ SIDE_CANCEL = Direction.DIRECTION_UNKNOWN + Offset.OFFSET_CANCEL # 1 + 0 = 1
49
45
 
50
- Args:
51
- direction (str): The trade direction (e.g., 'buy', 'sell').
52
- offset (str): The trade offset (e.g., 'open', 'close').
46
+ # Alias
47
+ SIDE_UNKNOWN = SIDE_CANCEL # 1
48
+ SIDE_LONG = SIDE_LONG_OPEN # 10
49
+ SIDE_SHORT = SIDE_SHORT_OPEN # 8
53
50
 
54
- Returns:
55
- TransactionSide: The corresponding transaction side.
51
+ # Backward compatibility
52
+ ShortOrder = AskOrder = Ask = SIDE_ASK
53
+ LongOrder = BidOrder = Bid = SIDE_BID
56
54
 
57
- Raises:
58
- ValueError: If the direction or offset is not recognized.
59
- """
60
- direction = direction.lower()
61
- offset = offset.lower()
62
-
63
- if direction in ['buy', 'long', 'b']:
64
- if offset in ['open', 'wind']:
65
- return cls.LongOpen
66
- elif offset in ['close', 'cover', 'unwind']:
67
- return cls.ShortOpen
68
- else:
69
- raise ValueError(f'Not recognized {direction} {offset}')
70
- elif direction in ['sell', 'short', 's']:
71
- if offset in ['open', 'wind']:
72
- return cls.ShortOpen
73
- elif offset in ['close', 'cover', 'unwind']:
74
- return cls.LongClose
75
- else:
76
- raise ValueError(f'Not recognized {direction} {offset}')
77
- else:
78
- raise ValueError(f'Not recognized {direction} {offset}')
55
+ ShortFilled = Unwind = Sell = SIDE_SHORT_CLOSE
56
+ LongFilled = LongOpen = Buy = SIDE_LONG_OPEN
57
+
58
+ ShortOpen = Short = SIDE_SHORT_OPEN
59
+ Cover = SIDE_LONG_CLOSE
60
+
61
+ UNKNOWN = CANCEL = SIDE_CANCEL
62
+
63
+ def __neg__(self) -> Self:
64
+ return self.__class__([market_data_cython.TransactionHelper.pyget_opposite(self.value)])
79
65
 
80
66
  @classmethod
81
67
  def _missing_(cls, value: str | int):
@@ -92,110 +78,61 @@ class TransactionSide(enum.IntEnum):
92
78
 
93
79
  match side_str:
94
80
  case 'long' | 'buy' | 'b':
95
- trade_side = cls.LongOpen
81
+ trade_side = cls.SIDE_LONG_OPEN
96
82
  case 'short' | 'sell' | 's':
97
- trade_side = cls.LongClose
83
+ trade_side = cls.SIDE_SHORT_CLOSE
98
84
  case 'short' | 'ss':
99
- trade_side = cls.ShortOpen
85
+ trade_side = cls.SIDE_SHORT_OPEN
100
86
  case 'cover' | 'bc':
101
- trade_side = cls.ShortClose
87
+ trade_side = cls.SIDE_LONG_CLOSE
102
88
  case 'ask':
103
- trade_side = cls.AskOrder
89
+ trade_side = cls.SIDE_ASK
104
90
  case 'bid':
105
- trade_side = cls.BidOrder
91
+ trade_side = cls.SIDE_BID
106
92
  case _:
107
93
  try:
108
94
  trade_side = cls.__getitem__(value)
109
95
  except Exception as _:
110
- trade_side = cls.UNKNOWN
96
+ trade_side = cls.SIDE_UNKNOWN
111
97
  LOGGER.warning('{} is not recognized, return TransactionSide.UNKNOWN'.format(value))
112
98
 
113
99
  return trade_side
114
100
 
115
101
  @property
116
102
  def sign(self) -> int:
117
- """
118
- Get the sign of the transaction side.
119
-
120
- Returns:
121
- int: 1 for buy/long, -1 for sell/short, 0 for unknown.
122
- """
123
- if self.value == self.Buy_to_Long.value or self.value == self.Buy_to_Cover.value:
124
- return 1
125
- elif self.value == self.Sell_to_Unwind.value or self.value == self.Sell_to_Short.value:
126
- return -1
127
- elif self.value == 0:
128
- return 0
129
- else:
130
- frame = inspect.currentframe()
131
- caller = inspect.getframeinfo(frame.f_back)
132
- LOGGER.warning(f"Requesting .sign of {self.name} is not recommended, use .order_sign instead.\nCalled from {caller.filename}, line {caller.lineno}.")
133
- return self.order_sign
103
+ return market_data_cython.TransactionHelper.pyget_sign(self.value)
134
104
 
135
105
  @property
136
- def order_sign(self) -> int:
106
+ def offset(self) -> Offset:
137
107
  """
138
- Get the order sign of the transaction side.
108
+ Get the offset of the transaction side.
139
109
 
140
110
  Returns:
141
- int: 1 for long orders, -1 for short orders, 0 for unknown.
111
+ int: The offset value, equivalent to the sign.
142
112
  """
143
- if self.value == self.LongOrder.value:
144
- return 1
145
- elif self.value == self.ShortOrder.value:
146
- return -1
147
- elif self.value == 0:
148
- return 0
149
- else:
150
- LOGGER.warning(f'Requesting .order_sign of {self.name} is not recommended, use .sign instead')
151
- return self.sign
113
+ return Offset(market_data_cython.TransactionHelper.pyget_offset(self.value))
152
114
 
153
115
  @property
154
- def offset(self) -> int:
116
+ def direction(self) -> Direction:
155
117
  """
156
118
  Get the offset of the transaction side.
157
119
 
158
120
  Returns:
159
121
  int: The offset value, equivalent to the sign.
160
122
  """
161
- return self.sign
123
+ return Direction(market_data_cython.TransactionHelper.pyget_direction(self.value))
162
124
 
163
125
  @property
164
126
  def side_name(self) -> str:
165
- """
166
- Get the name of the transaction side.
167
-
168
- Returns:
169
- str: 'Long', 'Short', 'ask', 'bid', or 'Unknown'.
170
- """
171
- if self.value == self.Buy_to_Long.value or self.value == self.Buy_to_Cover.value:
172
- return 'Long'
173
- elif self.value == self.Sell_to_Unwind.value or self.value == self.Sell_to_Short.value:
174
- return 'Short'
175
- elif self.value == self.Offer_to_Short.value:
176
- return 'ask'
177
- elif self.value == self.Bid_to_Long.value:
178
- return 'bid'
179
- else:
180
- return 'Unknown'
127
+ return market_data_cython.TransactionHelper.pyget_side_name(self.value)
181
128
 
182
129
  @property
183
130
  def offset_name(self) -> str:
184
- """
185
- Get the offset name of the transaction side.
131
+ return market_data_cython.TransactionHelper.pyget_offset_name(self.value)
186
132
 
187
- Returns:
188
- str: 'Open', 'Close', 'ask', 'bid', or 'Unknown'.
189
- """
190
- if self.value == self.Buy_to_Long.value or self.value == self.Sell_to_Short.value:
191
- return 'Open'
192
- elif self.value == self.Buy_to_Cover.value or self.value == self.Sell_to_Unwind.value:
193
- return 'Close'
194
- elif self.value == self.Offer_to_Short.value or self.value == self.Bid_to_Long.value:
195
- LOGGER.warning(f'Requesting offset of {self.name} is not supported, returns {self.side_name}')
196
- return self.side_name
197
- else:
198
- return 'Unknown'
133
+ @property
134
+ def direction_name(self) -> str:
135
+ return market_data_cython.TransactionHelper.pyget_direction_name(self.value)
199
136
 
200
137
 
201
138
  class OrderType(enum.IntEnum):
@@ -238,7 +175,7 @@ class MarketData(market_data_cython.MarketData, metaclass=abc.ABCMeta):
238
175
  return datetime.datetime.fromtimestamp(self.timestamp, tz=PROFILE.time_zone)
239
176
 
240
177
 
241
- class TransactionData(market_data_cython.TransactionData, MarketData):
178
+ class TransactionData(transaction_cython.TransactionData, MarketData):
242
179
  def __init__(
243
180
  self,
244
181
  ticker: str,
@@ -273,7 +210,7 @@ class TransactionData(market_data_cython.TransactionData, MarketData):
273
210
  return TransactionSide(super().side)
274
211
 
275
212
 
276
- class BarData(market_data_cython.BarData, MarketData):
213
+ class BarData(candlestick_cython.BarData, MarketData):
277
214
  def __init__(
278
215
  self,
279
216
  ticker: str,
@@ -357,7 +294,7 @@ class BarData(market_data_cython.BarData, MarketData):
357
294
  return datetime.timedelta(seconds=super().bar_span)
358
295
 
359
296
 
360
- class DailyBar(market_data_cython.BarData):
297
+ class DailyBar(candlestick_cython.BarData):
361
298
  def __init__(
362
299
  self,
363
300
  ticker: str,
@@ -380,7 +317,7 @@ class DailyBar(market_data_cython.BarData):
380
317
  bar_span = (market_date - start_date).days
381
318
  else:
382
319
  if isinstance(bar_span, datetime.timedelta):
383
- bar_span = bar_span.days()
320
+ bar_span = bar_span.days
384
321
  else:
385
322
  bar_span = float(bar_span)
386
323
 
@@ -471,7 +408,6 @@ class DailyBar(market_data_cython.BarData):
471
408
  raise ValueError(f'Invalid bar_span for {self.__class__.__name__}! Expect an int greater or equal to 1, got {super().bar_span}.')
472
409
 
473
410
 
474
-
475
411
  class TickDataLite(market_data_cython.TickDataLite, MarketData):
476
412
  """
477
413
  Python wrapper for TickDataLite Cython class.
File without changes
File without changes
File without changes
File without changes