onesecondtrader 0.11.0__py3-none-any.whl → 0.12.1__py3-none-any.whl

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.
@@ -1,2 +0,0 @@
1
- from .base_datafeed import BaseDatafeed as BaseDatafeed
2
- from .csv_datafeed import CSVDatafeed as CSVDatafeed
File without changes
@@ -0,0 +1,136 @@
1
+ """
2
+ This module provides the base class for all indicators.
3
+ """
4
+
5
+ import abc
6
+ import collections
7
+ import threading
8
+
9
+ import numpy as np
10
+ from onesecondtrader.core import models
11
+ from onesecondtrader.monitoring import console
12
+
13
+
14
+ class BaseIndicator(abc.ABC):
15
+ """
16
+ Base class for all indicators.
17
+
18
+ If new market data is received, the indicator is updated by calling the
19
+ `update(incoming_bar)` method.
20
+ When programming a new indicator, only the `name` property and the
21
+ `_compute_indicator()` method need to be implemented.
22
+
23
+ Examples:
24
+ >>> from onesecondtrader.indicators import base_indicator
25
+ >>> from onesecondtrader.core import models
26
+ >>> class DummyCloseIndicator(base_indicator.BaseIndicator):
27
+ ... @property
28
+ ... def name(self) -> str:
29
+ ... return "dummy_close_indicator"
30
+ ... def _compute_indicator(self, incoming_bar: models.Bar):
31
+ ... return incoming_bar.close
32
+ ...
33
+ >>> dummy_close_indicator = DummyCloseIndicator(max_history=10)
34
+ >>> incoming_bar = models.Bar(
35
+ ... open=100.0, high=101.0, low=99.0, close=100.5, volume=10000
36
+ ... )
37
+ >>> dummy_close_indicator.update(incoming_bar)
38
+ >>> dummy_close_indicator[0]
39
+ 100.5
40
+ >>> dummy_close_indicator[-1]
41
+ nan
42
+ >>> next_incoming_bar = models.Bar(
43
+ ... open=100.0, high=101.0, low=99.0, close=101.0, volume=10000
44
+ ... )
45
+ >>> dummy_close_indicator.update(next_incoming_bar)
46
+ >>> dummy_close_indicator[0]
47
+ 101.0
48
+ >>> dummy_close_indicator[-1]
49
+ 100.5
50
+ """
51
+
52
+ def __init__(self, max_history: int = 100) -> None:
53
+ """
54
+ Initialize the indicator with a maximum lookback history length.
55
+
56
+ Args:
57
+ max_history (int): Maximum lookback history length as number of periods.
58
+ Defaults to 100.
59
+
60
+ Attributes:
61
+ self._lock (threading.Lock): Lock to protect concurrent access to the
62
+ indicator's state.
63
+ self._history (collections.deque): Deque to store the lookback history.
64
+ """
65
+ if max_history < 1:
66
+ console.logger.warning(
67
+ f"max_history must be >= 1, got {max_history}; defaulting to 1"
68
+ )
69
+ max_history = 1
70
+ self._lock: threading.Lock = threading.Lock()
71
+
72
+ self._history: collections.deque[float] = collections.deque(maxlen=max_history)
73
+
74
+ @property
75
+ @abc.abstractmethod
76
+ def name(self) -> str:
77
+ """
78
+ Name of the indicator.
79
+ This property must be implemented by subclasses.
80
+
81
+ Returns:
82
+ str: Name of the indicator.
83
+ """
84
+ pass
85
+
86
+ @property
87
+ def latest(self) -> float:
88
+ """
89
+ The latest (most recent) indicator value.
90
+
91
+ Equivalent to self[0]. Returns numpy.nan when no value is available yet.
92
+ """
93
+ return self[0]
94
+
95
+ def update(self, incoming_bar: models.Bar) -> None:
96
+ """
97
+ Updates the indicator based on an incoming closed bar by calling
98
+ `self._compute_indicator()`.
99
+ """
100
+ new_value = self._compute_indicator(incoming_bar)
101
+ with self._lock:
102
+ self._history.append(new_value)
103
+
104
+ @abc.abstractmethod
105
+ def _compute_indicator(self, incoming_bar: models.Bar) -> float:
106
+ """
107
+ Computes the new indicator value based on an incoming closed bar.
108
+ This method must be implemented by subclasses.
109
+ """
110
+ pass
111
+
112
+ def __getitem__(self, index: int) -> float:
113
+ """
114
+ Return the indicator value at the given index with tolerant indexing.
115
+
116
+ Indexing rules:
117
+
118
+ - `0` returns the current (most recent) value
119
+ - `-1` returns the previous value, `-2` two periods back, and so on
120
+ - For convenience, a positive `k` behaves like `-k` (e.g., `1 == -1`,
121
+ `2 == -2`)
122
+ - Out-of-range indices return `np.nan` instead of raising an `IndexError`.
123
+ """
124
+ normalized: int
125
+ if index == 0:
126
+ normalized = -1
127
+ elif index > 0:
128
+ normalized = -(index + 1)
129
+ else:
130
+ normalized = index - 1
131
+
132
+ with self._lock:
133
+ try:
134
+ return self._history[normalized]
135
+ except IndexError:
136
+ return np.nan
@@ -1,7 +1,8 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: onesecondtrader
3
- Version: 0.11.0
3
+ Version: 0.12.1
4
4
  Summary: The Trading Infrastructure Toolkit for Python. Research, simulate, and deploy algorithmic trading strategies — all in one place.
5
+ License-File: LICENSE
5
6
  Author: Nils P. Kujath
6
7
  Author-email: 63961429+NilsKujath@users.noreply.github.com
7
8
  Requires-Python: >=3.11
@@ -9,6 +10,7 @@ Classifier: Programming Language :: Python :: 3
9
10
  Classifier: Programming Language :: Python :: 3.11
10
11
  Classifier: Programming Language :: Python :: 3.12
11
12
  Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
12
14
  Requires-Dist: pandas (>=2.3.1,<3.0.0)
13
15
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
14
16
  Description-Content-Type: text/markdown
@@ -2,9 +2,11 @@ onesecondtrader/__init__.py,sha256=TNqlT20sH46-J7F6giBxwWYG1-wFZZt7toDbZeQK6KQ,2
2
2
  onesecondtrader/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  onesecondtrader/core/models.py,sha256=I2NgWfZcvlyBPGUSsocrFrhP3KnLFJ-CFt8Cg4GOd0g,4185
4
4
  onesecondtrader/core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- onesecondtrader/datafeeds/__init__.py,sha256=0QmhgFEDi4LMP5uRwMCqCL6UWhxyyfQsr3gdnK_uDlA,109
5
+ onesecondtrader/datafeeds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  onesecondtrader/datafeeds/base_datafeed.py,sha256=QGXtkVUVN7PsDYeIH8h7Hi_kiDDFcqRyW8K8LzZkRTk,1394
7
7
  onesecondtrader/datafeeds/csv_datafeed.py,sha256=WMoZpoian_93CdAzo36hJoF15T0ywRADfuFQcfsPQNc,10957
8
+ onesecondtrader/indicators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ onesecondtrader/indicators/base_indicator.py,sha256=eGv5_WYOSsuLXX8MbnyE3_Y8owH-2bpUT_GczOXDHVE,4359
8
10
  onesecondtrader/messaging/__init__.py,sha256=9GBHlh6pXweknEacXVBvzpdoTJgVyb3ROLqe1Fhz2ww,179
9
11
  onesecondtrader/messaging/eventbus.py,sha256=R2K85INeYVwJ1tMOybC3WpRraK0ZKVe8WehCbAzzznU,19359
10
12
  onesecondtrader/messaging/events.py,sha256=eaWXQQIUnRNOR-9n5-6lyLbZ6bUtzjD4GI567U_vh4g,23625
@@ -12,7 +14,7 @@ onesecondtrader/monitoring/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
12
14
  onesecondtrader/monitoring/console.py,sha256=1mrojXkyL4ro7ebkvDMGNQiCL-93WEylRuwnfmEKzVs,299
13
15
  onesecondtrader/monitoring/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
16
  onesecondtrader/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- onesecondtrader-0.11.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
16
- onesecondtrader-0.11.0.dist-info/METADATA,sha256=v4ZOUo5XO9EHPPlzpHym0eYKP1H9zsnuDvyv9zlksjE,9565
17
- onesecondtrader-0.11.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
18
- onesecondtrader-0.11.0.dist-info/RECORD,,
17
+ onesecondtrader-0.12.1.dist-info/METADATA,sha256=saYuNOGorryGgxVFS3BArfldAK4uUtKWarPNjmKsa8Q,9638
18
+ onesecondtrader-0.12.1.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
19
+ onesecondtrader-0.12.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
20
+ onesecondtrader-0.12.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.3
2
+ Generator: poetry-core 2.2.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any