onesecondtrader 0.14.2__tar.gz → 0.16.0__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 (29) hide show
  1. {onesecondtrader-0.14.2 → onesecondtrader-0.16.0}/PKG-INFO +2 -1
  2. {onesecondtrader-0.14.2 → onesecondtrader-0.16.0}/pyproject.toml +2 -1
  3. onesecondtrader-0.16.0/src/onesecondtrader/indicators.py +102 -0
  4. onesecondtrader-0.16.0/src/onesecondtrader/ontology.py +18 -0
  5. onesecondtrader-0.14.2/src/onesecondtrader/__init__.py +0 -12
  6. onesecondtrader-0.14.2/src/onesecondtrader/brokers/base_broker.py +0 -99
  7. onesecondtrader-0.14.2/src/onesecondtrader/brokers/simulated_broker.py +0 -10
  8. onesecondtrader-0.14.2/src/onesecondtrader/core/__init__.py +0 -0
  9. onesecondtrader-0.14.2/src/onesecondtrader/core/models.py +0 -188
  10. onesecondtrader-0.14.2/src/onesecondtrader/core/portfolio.py +0 -359
  11. onesecondtrader-0.14.2/src/onesecondtrader/core/py.typed +0 -0
  12. onesecondtrader-0.14.2/src/onesecondtrader/datafeeds/__init__.py +0 -0
  13. onesecondtrader-0.14.2/src/onesecondtrader/datafeeds/base_datafeed.py +0 -54
  14. onesecondtrader-0.14.2/src/onesecondtrader/datafeeds/csv_datafeed.py +0 -297
  15. onesecondtrader-0.14.2/src/onesecondtrader/indicators/__init__.py +0 -0
  16. onesecondtrader-0.14.2/src/onesecondtrader/indicators/base_indicator.py +0 -136
  17. onesecondtrader-0.14.2/src/onesecondtrader/indicators/moving_averages.py +0 -132
  18. onesecondtrader-0.14.2/src/onesecondtrader/messaging/__init__.py +0 -9
  19. onesecondtrader-0.14.2/src/onesecondtrader/messaging/eventbus.py +0 -499
  20. onesecondtrader-0.14.2/src/onesecondtrader/messaging/events.py +0 -868
  21. onesecondtrader-0.14.2/src/onesecondtrader/monitoring/__init__.py +0 -0
  22. onesecondtrader-0.14.2/src/onesecondtrader/monitoring/console.py +0 -14
  23. onesecondtrader-0.14.2/src/onesecondtrader/monitoring/py.typed +0 -0
  24. onesecondtrader-0.14.2/src/onesecondtrader/py.typed +0 -0
  25. onesecondtrader-0.14.2/src/onesecondtrader/strategies/__init__.py +0 -0
  26. onesecondtrader-0.14.2/src/onesecondtrader/strategies/base_strategy.py +0 -46
  27. {onesecondtrader-0.14.2 → onesecondtrader-0.16.0}/LICENSE +0 -0
  28. {onesecondtrader-0.14.2 → onesecondtrader-0.16.0}/README.md +0 -0
  29. {onesecondtrader-0.14.2/src/onesecondtrader/brokers → onesecondtrader-0.16.0/src/onesecondtrader}/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onesecondtrader
3
- Version: 0.14.2
3
+ Version: 0.16.0
4
4
  Summary: The Trading Infrastructure Toolkit for Python. Research, simulate, and deploy algorithmic trading strategies — all in one place.
5
5
  License-File: LICENSE
6
6
  Author: Nils P. Kujath
@@ -11,6 +11,7 @@ Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: Programming Language :: Python :: 3.12
12
12
  Classifier: Programming Language :: Python :: 3.13
13
13
  Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: matplotlib (>=3.10.7,<4.0.0)
14
15
  Requires-Dist: pandas (>=2.3.1,<3.0.0)
15
16
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
16
17
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "onesecondtrader"
3
- version = "0.14.2"
3
+ version = "0.16.0"
4
4
  description = "The Trading Infrastructure Toolkit for Python. Research, simulate, and deploy algorithmic trading strategies — all in one place."
5
5
  authors = [
6
6
  {name = "Nils P. Kujath",email = "63961429+NilsKujath@users.noreply.github.com"}
@@ -10,6 +10,7 @@ requires-python = ">=3.11"
10
10
  dependencies = [
11
11
  "pandas (>=2.3.1,<3.0.0)",
12
12
  "python-dotenv (>=1.0.0,<2.0.0)",
13
+ "matplotlib (>=3.10.7,<4.0.0)",
13
14
  ]
14
15
 
15
16
  [tool.poetry]
@@ -0,0 +1,102 @@
1
+ """
2
+ OneSecondTrader's library of pre-built indicators.
3
+ """
4
+
5
+ import abc
6
+ import enum
7
+ import numpy as np
8
+ import threading
9
+
10
+ from collections import deque
11
+ from onesecondtrader.ontology import Bar
12
+
13
+
14
+ class BaseIndicator(abc.ABC):
15
+ """
16
+ Base class for indicators. Subclasses must set the `name` property and implement
17
+ the `_compute_indicator()` method. See `SimpleMovingAverage` for an example.
18
+ """
19
+
20
+ def __init__(self, max_history: int = 100) -> None:
21
+ self._lock = threading.Lock()
22
+ self._history: deque[float] = deque(maxlen=max(1, int(max_history)))
23
+
24
+ @property
25
+ @abc.abstractmethod
26
+ def name(self) -> str:
27
+ pass
28
+
29
+ def update(self, incoming_bar: Bar) -> None:
30
+ _latest_value: float = self._compute_indicator(incoming_bar)
31
+ with self._lock:
32
+ self._history.append(_latest_value)
33
+
34
+ @abc.abstractmethod
35
+ def _compute_indicator(self, incoming_bar: Bar) -> float:
36
+ pass
37
+
38
+ @property
39
+ def latest(self) -> float:
40
+ with self._lock:
41
+ return self._history[-1] if self._history else np.nan
42
+
43
+ @property
44
+ def history(self) -> deque[float]:
45
+ return self._history
46
+
47
+
48
+ class InputSource(enum.Enum):
49
+ """
50
+ Enum of supported input sources for indicators. Indicators with a `input_source`
51
+ parameter can be configured to use one of these sources for their calculations.
52
+ """
53
+
54
+ OPEN = enum.auto()
55
+ HIGH = enum.auto()
56
+ LOW = enum.auto()
57
+ CLOSE = enum.auto()
58
+ VOLUME = enum.auto()
59
+
60
+
61
+ class SimpleMovingAverage(BaseIndicator):
62
+ """
63
+ Simple Moving Average (SMA) indicator. Can be configured to use different input
64
+ sources (see `InputSource` enum, default is `InputSource.CLOSE`).
65
+ """
66
+
67
+ def __init__(
68
+ self,
69
+ period: int = 200,
70
+ max_history: int = 100,
71
+ input_source: InputSource = InputSource.CLOSE,
72
+ ) -> None:
73
+ super().__init__(max_history=max_history)
74
+ self.period: int = max(1, int(period))
75
+ self.input_source: InputSource = input_source
76
+ self._window: deque[float] = deque(maxlen=self.period)
77
+
78
+ @property
79
+ def name(self) -> str:
80
+ return f"SMA_{self.period}_{self.input_source.name}"
81
+
82
+ def _compute_indicator(self, bar: Bar) -> float:
83
+ value: float = self._extract_input(bar)
84
+ self._window.append(value)
85
+ if len(self._window) < self.period:
86
+ return np.nan
87
+ return sum(self._window) / self.period
88
+
89
+ def _extract_input(self, bar: Bar) -> float:
90
+ match self.input_source:
91
+ case InputSource.OPEN:
92
+ return float(bar.open)
93
+ case InputSource.HIGH:
94
+ return float(bar.high)
95
+ case InputSource.LOW:
96
+ return float(bar.low)
97
+ case InputSource.CLOSE:
98
+ return float(bar.close)
99
+ case InputSource.VOLUME:
100
+ return float(bar.volume)
101
+ case _:
102
+ return float(bar.close)
@@ -0,0 +1,18 @@
1
+ """
2
+ Domain-specific data models that are used system-wide.
3
+ """
4
+
5
+ import dataclasses
6
+
7
+
8
+ @dataclasses.dataclass(slots=True)
9
+ class Bar:
10
+ """
11
+ Data model for OHLCV bar data.
12
+ """
13
+
14
+ open: float
15
+ high: float
16
+ low: float
17
+ close: float
18
+ volume: int
@@ -1,12 +0,0 @@
1
- """
2
- The Trading Infrastructure Toolkit for Python.
3
-
4
- Research, simulate, and deploy algorithmic trading strategies — all in one place.
5
- """
6
-
7
- from .monitoring.console import logger
8
-
9
-
10
- __all__ = [
11
- "logger",
12
- ]
@@ -1,99 +0,0 @@
1
- import abc
2
- from onesecondtrader import messaging
3
- from onesecondtrader.messaging import events
4
-
5
-
6
- class BaseBroker(abc.ABC):
7
- def __init__(self, event_bus: messaging.EventBus | None = None):
8
- self.event_bus: messaging.EventBus = (
9
- event_bus if event_bus else messaging.system_event_bus
10
- )
11
- self._is_connected: bool = False
12
-
13
- def connect(self) -> bool:
14
- if self._is_connected:
15
- return True
16
- self._subscribe_to_events()
17
- self._is_connected = True
18
- return True
19
-
20
- def disconnect(self) -> None:
21
- if not self._is_connected:
22
- return
23
- try:
24
- self.event_bus.unsubscribe(events.System.Shutdown, self.on_system_shutdown)
25
- finally:
26
- self._is_connected = False
27
-
28
- @property
29
- def is_connected(self) -> bool:
30
- return self._is_connected
31
-
32
- def _subscribe_to_events(self) -> None:
33
- """
34
- Subscribe to relevant events from the event bus.
35
- """
36
- self.event_bus.subscribe(events.System.Shutdown, self.on_system_shutdown)
37
- self.event_bus.subscribe(events.Strategy.SymbolRelease, self.on_symbol_release)
38
-
39
- def on_system_shutdown(self, event: events.Base.Event) -> None:
40
- """
41
- Handle system shutdown events (ignore unrelated events).
42
- """
43
- if not isinstance(event, events.System.Shutdown):
44
- return
45
- # Default no-op
46
- return
47
-
48
- def on_symbol_release(self, event: events.Base.Event) -> None:
49
- """
50
- Handle portfolio symbol release events (ignore unrelated events).
51
- Intended for brokers to perform any symbol-specific cleanup if necessary.
52
- Default implementation is a no-op.
53
- """
54
- if not isinstance(event, events.Strategy.SymbolRelease):
55
- return
56
- # Default no-op
57
- return
58
-
59
- def on_request_market_order(self, event: events.Request.MarketOrder) -> None:
60
- """
61
- Handle market order requests.
62
- """
63
- pass
64
-
65
- def on_request_limit_order(self, event: events.Request.LimitOrder) -> None:
66
- """
67
- Handle limit order requests.
68
- """
69
- pass
70
-
71
- def on_request_stop_order(self, event: events.Request.StopOrder) -> None:
72
- """
73
- Handle stop order requests.
74
- """
75
- pass
76
-
77
- def on_request_stop_limit_order(self, event: events.Request.StopLimitOrder) -> None:
78
- """
79
- Handle stop limit order requests.
80
- """
81
- pass
82
-
83
- def on_request_cancel_order(self, event: events.Request.CancelOrder) -> None:
84
- """
85
- Handle cancel order requests.
86
- """
87
- pass
88
-
89
- def on_request_flush_symbol(self, event: events.Request.FlushSymbol) -> None:
90
- """
91
- Handle flush symbol requests.
92
- """
93
- pass
94
-
95
- def on_request_flush_all(self, event: events.Request.FlushAll) -> None:
96
- """
97
- Handle flush all requests.
98
- """
99
- pass
@@ -1,10 +0,0 @@
1
- from onesecondtrader.brokers import base_broker
2
-
3
-
4
- class SimulatedBroker(base_broker.BaseBroker):
5
- """
6
- Simple simulated broker used as a safe default.
7
- """
8
-
9
- def __init__(self, event_bus=None):
10
- super().__init__(event_bus)
@@ -1,188 +0,0 @@
1
- from dataclasses import dataclass
2
- import enum
3
-
4
-
5
- @dataclass(frozen=True, slots=True)
6
- class Bar:
7
- """
8
- Class for representing a OHLC(V) bar of market data.
9
-
10
- Attributes:
11
- open (float): Open price
12
- high (float): High price
13
- low (float): Low price
14
- close (float): Close price
15
- volume (int | None): Volume
16
- """
17
-
18
- open: float
19
- high: float
20
- low: float
21
- close: float
22
- volume: int | None = None
23
-
24
-
25
- class Side(enum.Enum):
26
- """
27
- Enum for order sides.
28
- """
29
-
30
- BUY = enum.auto()
31
- SELL = enum.auto()
32
-
33
-
34
- class TimeInForce(enum.Enum):
35
- """
36
- Order time-in-force specifications.
37
-
38
- **Attributes:**
39
-
40
- | Enum | Value | Description |
41
- |------|-------|-------------|
42
- | `DAY` | `enum.auto()` | Valid until end of trading day |
43
- | `FOK` | `enum.auto()` | Fill entire order immediately or cancel (Fill-or-Kill) |
44
- | `GTC` | `enum.auto()` | Active until explicitly cancelled (Good-Till-Cancelled) |
45
- | `GTD` | `enum.auto()` | Active until specified date (Good-Till-Date) |
46
- | `IOC` | `enum.auto()` | Execute available quantity immediately, cancel rest (Immediate-or-Cancel) |
47
- """
48
-
49
- DAY = enum.auto()
50
- FOK = enum.auto()
51
- GTC = enum.auto()
52
- GTD = enum.auto()
53
- IOC = enum.auto()
54
-
55
-
56
- class OrderType(enum.Enum):
57
- """
58
- Enum for order types.
59
-
60
- **Attributes:**
61
-
62
- | Enum | Value | Description |
63
- |------|-------|-------------|
64
- | `MARKET` | `enum.auto()` | Market order |
65
- | `LIMIT` | `enum.auto()` | Limit order |
66
- | `STOP` | `enum.auto()` | Stop order |
67
- | `STOP_LIMIT` | `enum.auto()` | Stop-limit order |
68
- """
69
-
70
- MARKET = enum.auto()
71
- LIMIT = enum.auto()
72
- STOP = enum.auto()
73
- STOP_LIMIT = enum.auto()
74
-
75
-
76
- class OrderLifecycleState(enum.Enum):
77
- """
78
- Enum for order lifecycle states.
79
-
80
- **Attributes:**
81
-
82
- | Enum | Value | Description |
83
- |------|-------|-------------|
84
- | `PENDING` | `enum.auto()` | Order has been submitted, but not yet acknowledged by the brokers |
85
- | `OPEN` | `enum.auto()` | Order has been acknowledged by the brokers, but not yet filled or cancelled |
86
- | `FILLED` | `enum.auto()` | Order has been filled |
87
- | `CANCELLED` | `enum.auto()` | Order has been cancelled |
88
- """
89
-
90
- PENDING = enum.auto()
91
- OPEN = enum.auto()
92
- PARTIALLY_FILLED = enum.auto()
93
- FILLED = enum.auto()
94
- CANCELLED = enum.auto()
95
-
96
-
97
- class OrderRejectionReason(enum.Enum):
98
- """
99
- Enum for order rejection reasons.
100
-
101
- **Attributes:**
102
-
103
- | Enum | Value | Description |
104
- |------|-------|-------------|
105
- | `UNKNOWN` | `enum.auto()` | Unknown reason |
106
- | `NEGATIVE_QUANTITY` | `enum.auto()` | Negative quantity |
107
- """
108
-
109
- UNKNOWN = enum.auto()
110
- NEGATIVE_QUANTITY = enum.auto()
111
-
112
-
113
- class RecordType(enum.Enum):
114
- """
115
- Enum for Databento record types.
116
-
117
- **Attributes:**
118
-
119
- | Enum | Value | Description |
120
- |------|-------|-------------|
121
- | `OHLCV_1S` | `32` | 1-second bars |
122
- | `OHLCV_1M` | `33` | 1-minute bars |
123
- | `OHLCV_1H` | `34` | 1-hour bars |
124
- | `OHLCV_1D` | `35` | 1-day bars |
125
- """
126
-
127
- OHLCV_1S = 32
128
- OHLCV_1M = 33
129
- OHLCV_1H = 34
130
- OHLCV_1D = 35
131
-
132
- @classmethod
133
- def to_string(cls, rtype: int) -> str:
134
- match rtype:
135
- case cls.OHLCV_1S.value:
136
- return "1-second bars"
137
- case cls.OHLCV_1M.value:
138
- return "1-minute bars"
139
- case cls.OHLCV_1H.value:
140
- return "1-hour bars"
141
- case cls.OHLCV_1D.value:
142
- return "daily bars"
143
- case _:
144
- return f"unknown ({rtype})"
145
-
146
-
147
- class XMAMode(enum.Enum):
148
- """
149
- Enum for moving average modes.
150
-
151
- **Attributes:**
152
-
153
- | Enum | Value | Description |
154
- |------|-------|-------------|
155
- | `OPEN` | `enum.auto()` | Open price |
156
- | `HIGH` | `enum.auto()` | High price |
157
- | `LOW` | `enum.auto()` | Low price |
158
- | `CLOSE` | `enum.auto()` | Close price |
159
- | `TYPICAL_PRICE` | `enum.auto()` | Typical price ((H+ L + C) / 3) |
160
- | `WEIGHTED_CLOSE` | `enum.auto()` | Weighted close price ((H + L + 2*C) / 4) |
161
- """
162
-
163
- OPEN = enum.auto()
164
- HIGH = enum.auto()
165
- LOW = enum.auto()
166
- CLOSE = enum.auto()
167
- TYPICAL_PRICE = enum.auto()
168
- WEIGHTED_CLOSE = enum.auto()
169
-
170
-
171
- class Position:
172
- pass
173
-
174
-
175
- class StrategyShutdownMode(enum.Enum):
176
- """
177
- Enum for strategy shutdown modes.
178
-
179
- **Attributes:**
180
-
181
- | Enum | Value | Description |
182
- |------|-------|-------------|
183
- | `SOFT` | `enum.auto()` | Do not open new positions; wait until current positions close naturally |
184
- | `HARD` | `enum.auto()` | Close all positions immediately with market orders |
185
- """
186
-
187
- SOFT = enum.auto()
188
- HARD = enum.auto()