onesecondtrader 0.22.0__py3-none-any.whl → 0.49.0__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.
- onesecondtrader/events/__init__.py +8 -0
- onesecondtrader/events/base.py +21 -0
- onesecondtrader/events/market/__init__.py +7 -0
- onesecondtrader/events/market/bar_processed.py +29 -0
- onesecondtrader/events/market/bar_received.py +34 -0
- onesecondtrader/events/orders/__init__.py +9 -0
- onesecondtrader/events/orders/base.py +30 -0
- onesecondtrader/events/orders/expirations.py +23 -0
- onesecondtrader/events/orders/fills.py +41 -0
- onesecondtrader/events/requests/__init__.py +11 -0
- onesecondtrader/events/requests/base.py +25 -0
- onesecondtrader/events/requests/order_cancellation.py +21 -0
- onesecondtrader/events/requests/order_modification.py +26 -0
- onesecondtrader/events/requests/order_submission.py +35 -0
- onesecondtrader/events/responses/__init__.py +14 -0
- onesecondtrader/events/responses/base.py +26 -0
- onesecondtrader/events/responses/cancellations.py +42 -0
- onesecondtrader/events/responses/modifications.py +43 -0
- onesecondtrader/events/responses/orders.py +42 -0
- onesecondtrader/indicators/__init__.py +17 -0
- onesecondtrader/indicators/base.py +142 -0
- onesecondtrader/indicators/market_fields.py +166 -0
- onesecondtrader/indicators/moving_averages.py +104 -0
- onesecondtrader/models/__init__.py +23 -0
- onesecondtrader/models/bar_fields.py +23 -0
- onesecondtrader/models/bar_period.py +21 -0
- onesecondtrader/models/order_types.py +21 -0
- onesecondtrader/models/rejection_reasons.py +48 -0
- onesecondtrader/models/trade_sides.py +20 -0
- {onesecondtrader-0.22.0.dist-info → onesecondtrader-0.49.0.dist-info}/METADATA +8 -2
- onesecondtrader-0.49.0.dist-info/RECORD +34 -0
- {onesecondtrader-0.22.0.dist-info → onesecondtrader-0.49.0.dist-info}/WHEEL +1 -1
- onesecondtrader/brokers.py +0 -92
- onesecondtrader/core.py +0 -260
- onesecondtrader/datafeeds.py +0 -173
- onesecondtrader/indicators.py +0 -106
- onesecondtrader-0.22.0.dist-info/RECORD +0 -9
- {onesecondtrader-0.22.0.dist-info → onesecondtrader-0.49.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
import collections
|
|
5
|
+
import threading
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from onesecondtrader import events
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class IndicatorBase(abc.ABC):
|
|
13
|
+
"""
|
|
14
|
+
Base class for scalar technical indicators with per-symbol history.
|
|
15
|
+
|
|
16
|
+
The class provides a thread-safe mechanism for storing and retrieving indicator values computed from incoming market bars, keyed by symbol.
|
|
17
|
+
It does not manage input windows or rolling computation state.
|
|
18
|
+
|
|
19
|
+
Subclasses define a stable indicator identifier via the `name` property and implement `_compute_indicator`, which computes a single scalar value per incoming bar.
|
|
20
|
+
Indicators with multiple conceptual outputs must be implemented as multiple single-output indicators (e.g. Bollinger Bands must be implemented via three separate indicators `BBUpper`, `BBMiddle`, and `BBLower`).
|
|
21
|
+
|
|
22
|
+
The update mechanism is thread-safe.
|
|
23
|
+
Indicator computation is performed outside the internal lock.
|
|
24
|
+
Subclasses that maintain internal state are responsible for ensuring its thread safety and must not access `_history_data`.
|
|
25
|
+
|
|
26
|
+
Indicator values are stored per symbol in bounded FIFO buffers.
|
|
27
|
+
Missing data and out-of-bounds access yield `numpy.nan`.
|
|
28
|
+
|
|
29
|
+
The `plot_at` attribute is an opaque identifier forwarded to the charting backend and has no intrinsic meaning within the indicator subsystem.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, max_history: int = 100, plot_at: int = 99) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Parameters:
|
|
35
|
+
max_history:
|
|
36
|
+
Maximum number of indicator values retained per symbol.
|
|
37
|
+
Cannot be less than 1.
|
|
38
|
+
plot_at:
|
|
39
|
+
Opaque plotting identifier forwarded to the charting backend.
|
|
40
|
+
"""
|
|
41
|
+
self._lock = threading.Lock()
|
|
42
|
+
self._max_history = max(1, int(max_history))
|
|
43
|
+
self._history_data: dict[str, collections.deque[float]] = {}
|
|
44
|
+
self._plot_at = plot_at
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
@abc.abstractmethod
|
|
48
|
+
def name(self) -> str:
|
|
49
|
+
"""
|
|
50
|
+
Canonical indicator name.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Stable identifier used for charting and downstream integration.
|
|
54
|
+
"""
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
@abc.abstractmethod
|
|
58
|
+
def _compute_indicator(self, incoming_bar: events.market.BarReceived) -> float:
|
|
59
|
+
"""
|
|
60
|
+
Compute the indicator value for a single market bar.
|
|
61
|
+
|
|
62
|
+
This method is executed outside the internal lock.
|
|
63
|
+
Implementations must not access `_history_data` and must ensure thread safety of any internal computation state.
|
|
64
|
+
|
|
65
|
+
Parameters:
|
|
66
|
+
incoming_bar:
|
|
67
|
+
Market bar used as input for indicator computation.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Computed indicator value.
|
|
71
|
+
"""
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
def update(self, incoming_bar: events.market.BarReceived) -> None:
|
|
75
|
+
"""
|
|
76
|
+
Update the indicator with a new market bar.
|
|
77
|
+
|
|
78
|
+
The computed value is appended to the per-symbol history buffer.
|
|
79
|
+
|
|
80
|
+
Parameters:
|
|
81
|
+
incoming_bar:
|
|
82
|
+
Market bar triggering the update.
|
|
83
|
+
"""
|
|
84
|
+
symbol = incoming_bar.symbol
|
|
85
|
+
|
|
86
|
+
value = self._compute_indicator(incoming_bar)
|
|
87
|
+
|
|
88
|
+
with self._lock:
|
|
89
|
+
if symbol not in self._history_data:
|
|
90
|
+
self._history_data[symbol] = collections.deque(maxlen=self._max_history)
|
|
91
|
+
|
|
92
|
+
self._history_data[symbol].append(value)
|
|
93
|
+
|
|
94
|
+
def latest(self, symbol: str) -> float:
|
|
95
|
+
"""
|
|
96
|
+
Return the most recent indicator value for a symbol.
|
|
97
|
+
|
|
98
|
+
Parameters:
|
|
99
|
+
symbol:
|
|
100
|
+
Symbol identifier.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Most recent value, or `numpy.nan` if unavailable.
|
|
104
|
+
"""
|
|
105
|
+
return self[symbol, -1]
|
|
106
|
+
|
|
107
|
+
def __getitem__(self, key: tuple[str, int]) -> float:
|
|
108
|
+
"""
|
|
109
|
+
Retrieve an indicator value by symbol and index.
|
|
110
|
+
|
|
111
|
+
Indexing follows standard Python sequence semantics.
|
|
112
|
+
Negative indices refer to positions relative to the most recent value.
|
|
113
|
+
|
|
114
|
+
Parameters:
|
|
115
|
+
key:
|
|
116
|
+
`(symbol, index)` pair specifying the symbol and history offset.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Indicator value at the specified position, or `numpy.nan` if unavailable.
|
|
120
|
+
"""
|
|
121
|
+
symbol, index = key
|
|
122
|
+
|
|
123
|
+
with self._lock:
|
|
124
|
+
history = self._history_data.get(symbol)
|
|
125
|
+
|
|
126
|
+
if history is None:
|
|
127
|
+
return np.nan
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
return history[index]
|
|
131
|
+
except IndexError:
|
|
132
|
+
return np.nan
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def plot_at(self) -> int:
|
|
136
|
+
"""
|
|
137
|
+
Plotting identifier.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Opaque identifier consumed by the charting backend.
|
|
141
|
+
"""
|
|
142
|
+
return self._plot_at
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from onesecondtrader import events, indicators
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Open(indicators.IndicatorBase):
|
|
9
|
+
"""
|
|
10
|
+
Open price indicator.
|
|
11
|
+
|
|
12
|
+
This indicator exposes the open price of each incoming market bar as a scalar time series.
|
|
13
|
+
Values are stored per symbol and can be accessed historically via the indicator interface.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def name(self) -> str:
|
|
18
|
+
"""
|
|
19
|
+
Canonical indicator name.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
Fixed identifier for the open price indicator.
|
|
23
|
+
"""
|
|
24
|
+
return "OPEN"
|
|
25
|
+
|
|
26
|
+
def _compute_indicator(self, incoming_bar: events.market.BarReceived) -> float:
|
|
27
|
+
"""
|
|
28
|
+
Extract the open price from an incoming market bar.
|
|
29
|
+
|
|
30
|
+
Parameters:
|
|
31
|
+
incoming_bar:
|
|
32
|
+
Market bar used as input.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Open price of the bar.
|
|
36
|
+
"""
|
|
37
|
+
return incoming_bar.open
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class High(indicators.IndicatorBase):
|
|
41
|
+
"""
|
|
42
|
+
High price indicator.
|
|
43
|
+
|
|
44
|
+
This indicator exposes the high price of each incoming market bar as a scalar time series.
|
|
45
|
+
Values are stored per symbol and can be accessed historically via the indicator interface.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def name(self) -> str:
|
|
50
|
+
"""
|
|
51
|
+
Canonical indicator name.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Fixed identifier for the high price indicator.
|
|
55
|
+
"""
|
|
56
|
+
return "HIGH"
|
|
57
|
+
|
|
58
|
+
def _compute_indicator(self, incoming_bar: events.market.BarReceived) -> float:
|
|
59
|
+
"""
|
|
60
|
+
Extract the high price from an incoming market bar.
|
|
61
|
+
|
|
62
|
+
Parameters:
|
|
63
|
+
incoming_bar:
|
|
64
|
+
Market bar used as input.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
High price of the bar.
|
|
68
|
+
"""
|
|
69
|
+
return incoming_bar.high
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Low(indicators.IndicatorBase):
|
|
73
|
+
"""
|
|
74
|
+
Low price indicator.
|
|
75
|
+
|
|
76
|
+
This indicator exposes the low price of each incoming market bar as a scalar time series.
|
|
77
|
+
Values are stored per symbol and can be accessed historically via the indicator interface.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def name(self) -> str:
|
|
82
|
+
"""
|
|
83
|
+
Canonical indicator name.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Fixed identifier for the low price indicator.
|
|
87
|
+
"""
|
|
88
|
+
return "LOW"
|
|
89
|
+
|
|
90
|
+
def _compute_indicator(self, incoming_bar: events.market.BarReceived) -> float:
|
|
91
|
+
"""
|
|
92
|
+
Extract the low price from an incoming market bar.
|
|
93
|
+
|
|
94
|
+
Parameters:
|
|
95
|
+
incoming_bar:
|
|
96
|
+
Market bar used as input.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Low price of the bar.
|
|
100
|
+
"""
|
|
101
|
+
return incoming_bar.low
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class Close(indicators.IndicatorBase):
|
|
105
|
+
"""
|
|
106
|
+
Close price indicator.
|
|
107
|
+
|
|
108
|
+
This indicator exposes the close price of each incoming market bar as a scalar time series.
|
|
109
|
+
Values are stored per symbol and can be accessed historically via the indicator interface.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def name(self) -> str:
|
|
114
|
+
"""
|
|
115
|
+
Canonical indicator name.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Fixed identifier for the close price indicator.
|
|
119
|
+
"""
|
|
120
|
+
return "CLOSE"
|
|
121
|
+
|
|
122
|
+
def _compute_indicator(self, incoming_bar: events.market.BarReceived) -> float:
|
|
123
|
+
"""
|
|
124
|
+
Extract the close price from an incoming market bar.
|
|
125
|
+
|
|
126
|
+
Parameters:
|
|
127
|
+
incoming_bar:
|
|
128
|
+
Market bar used as input.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Close price of the bar.
|
|
132
|
+
"""
|
|
133
|
+
return incoming_bar.close
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class Volume(indicators.IndicatorBase):
|
|
137
|
+
"""
|
|
138
|
+
Volume indicator.
|
|
139
|
+
|
|
140
|
+
This indicator exposes the traded volume of each incoming market bar as a scalar time series.
|
|
141
|
+
Values are stored per symbol and can be accessed historically via the indicator interface.
|
|
142
|
+
Missing volume values yield `numpy.nan`.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def name(self) -> str:
|
|
147
|
+
"""
|
|
148
|
+
Canonical indicator name.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
Fixed identifier for the volume indicator.
|
|
152
|
+
"""
|
|
153
|
+
return "VOLUME"
|
|
154
|
+
|
|
155
|
+
def _compute_indicator(self, incoming_bar: events.market.BarReceived) -> float:
|
|
156
|
+
"""
|
|
157
|
+
Extract the volume from an incoming market bar.
|
|
158
|
+
|
|
159
|
+
Parameters:
|
|
160
|
+
incoming_bar:
|
|
161
|
+
Market bar used as input.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Volume of the bar, or `numpy.nan` if unavailable.
|
|
165
|
+
"""
|
|
166
|
+
return float(incoming_bar.volume) if incoming_bar.volume is not None else np.nan
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import collections
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from onesecondtrader import events, indicators, models
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SimpleMovingAverage(indicators.IndicatorBase):
|
|
10
|
+
"""
|
|
11
|
+
Simple Moving Average (SMA) indicator.
|
|
12
|
+
|
|
13
|
+
This indicator computes the arithmetic mean of a selected bar field over a fixed rolling window.
|
|
14
|
+
One scalar value is produced per incoming bar and stored per symbol.
|
|
15
|
+
|
|
16
|
+
The rolling window is maintained independently for each symbol.
|
|
17
|
+
Until the window is fully populated, the indicator yields `numpy.nan`.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
period: int = 200,
|
|
23
|
+
max_history: int = 100,
|
|
24
|
+
bar_field: models.BarField = models.BarField.CLOSE,
|
|
25
|
+
plot_at: int = 0,
|
|
26
|
+
) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Parameters:
|
|
29
|
+
period:
|
|
30
|
+
Window size used to compute the moving average.
|
|
31
|
+
max_history:
|
|
32
|
+
Maximum number of computed indicator values retained per symbol.
|
|
33
|
+
bar_field:
|
|
34
|
+
Bar field used as the input series.
|
|
35
|
+
plot_at:
|
|
36
|
+
Opaque plotting identifier forwarded to the charting backend.
|
|
37
|
+
"""
|
|
38
|
+
super().__init__(max_history=max_history, plot_at=plot_at)
|
|
39
|
+
|
|
40
|
+
self.period: int = max(1, int(period))
|
|
41
|
+
self.bar_field: models.BarField = bar_field
|
|
42
|
+
self._window: dict[str, collections.deque[float]] = {}
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def name(self) -> str:
|
|
46
|
+
"""
|
|
47
|
+
Canonical indicator name.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Identifier encoding the indicator type, period, and bar field.
|
|
51
|
+
"""
|
|
52
|
+
return f"SMA_{self.period}_{self.bar_field.name}"
|
|
53
|
+
|
|
54
|
+
def _compute_indicator(self, incoming_bar: events.market.BarReceived) -> float:
|
|
55
|
+
"""
|
|
56
|
+
Compute the simple moving average for a single received bar.
|
|
57
|
+
|
|
58
|
+
Parameters:
|
|
59
|
+
incoming_bar:
|
|
60
|
+
Market bar used as input for the computation.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Simple moving average value, or `numpy.nan` if the rolling window is not yet fully populated.
|
|
64
|
+
"""
|
|
65
|
+
symbol = incoming_bar.symbol
|
|
66
|
+
if symbol not in self._window:
|
|
67
|
+
self._window[symbol] = collections.deque(maxlen=self.period)
|
|
68
|
+
|
|
69
|
+
window = self._window[symbol]
|
|
70
|
+
value = self._extract_field(incoming_bar)
|
|
71
|
+
window.append(value)
|
|
72
|
+
|
|
73
|
+
if len(window) < self.period:
|
|
74
|
+
return np.nan
|
|
75
|
+
return sum(window) / self.period
|
|
76
|
+
|
|
77
|
+
def _extract_field(self, incoming_bar: events.market.BarReceived) -> float:
|
|
78
|
+
"""
|
|
79
|
+
Extract the configured bar field from an incoming bar.
|
|
80
|
+
|
|
81
|
+
Parameters:
|
|
82
|
+
incoming_bar:
|
|
83
|
+
Market bar providing the input data.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Extracted field value, or `numpy.nan` if unavailable.
|
|
87
|
+
"""
|
|
88
|
+
match self.bar_field:
|
|
89
|
+
case models.BarField.OPEN:
|
|
90
|
+
return incoming_bar.open
|
|
91
|
+
case models.BarField.HIGH:
|
|
92
|
+
return incoming_bar.high
|
|
93
|
+
case models.BarField.LOW:
|
|
94
|
+
return incoming_bar.low
|
|
95
|
+
case models.BarField.CLOSE:
|
|
96
|
+
return incoming_bar.close
|
|
97
|
+
case models.BarField.VOLUME:
|
|
98
|
+
return (
|
|
99
|
+
float(incoming_bar.volume)
|
|
100
|
+
if incoming_bar.volume is not None
|
|
101
|
+
else np.nan
|
|
102
|
+
)
|
|
103
|
+
case _:
|
|
104
|
+
return incoming_bar.close
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Defines the fundamental domain concepts used throughout the trading system.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .bar_fields import BarField
|
|
6
|
+
from .bar_period import BarPeriod
|
|
7
|
+
from .order_types import OrderType
|
|
8
|
+
from .rejection_reasons import (
|
|
9
|
+
OrderRejectionReason,
|
|
10
|
+
CancellationRejectionReason,
|
|
11
|
+
ModificationRejectionReason,
|
|
12
|
+
)
|
|
13
|
+
from .trade_sides import TradeSide
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"BarField",
|
|
17
|
+
"BarPeriod",
|
|
18
|
+
"OrderType",
|
|
19
|
+
"TradeSide",
|
|
20
|
+
"OrderRejectionReason",
|
|
21
|
+
"CancellationRejectionReason",
|
|
22
|
+
"ModificationRejectionReason",
|
|
23
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BarField(enum.Enum):
|
|
7
|
+
"""
|
|
8
|
+
Enumeration of bar fields used as indicator inputs.
|
|
9
|
+
|
|
10
|
+
| Value | Semantics |
|
|
11
|
+
|----------|------------------------------------|
|
|
12
|
+
| `OPEN` | Bar's opening value. |
|
|
13
|
+
| `HIGH` | Bar's highest value. |
|
|
14
|
+
| `LOW` | Bar's lowest value. |
|
|
15
|
+
| `CLOSE` | Bar's closing value. |
|
|
16
|
+
| `VOLUME` | Bar's traded volume. |
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
OPEN = enum.auto()
|
|
20
|
+
HIGH = enum.auto()
|
|
21
|
+
LOW = enum.auto()
|
|
22
|
+
CLOSE = enum.auto()
|
|
23
|
+
VOLUME = enum.auto()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BarPeriod(enum.Enum):
|
|
7
|
+
"""
|
|
8
|
+
Enumeration of bar aggregation periods.
|
|
9
|
+
|
|
10
|
+
| Value | Semantics |
|
|
11
|
+
|----------|----------------------|
|
|
12
|
+
| `SECOND` | Duration of 1 second.|
|
|
13
|
+
| `MINUTE` | Duration of 1 minute.|
|
|
14
|
+
| `HOUR` | Duration of 1 hour. |
|
|
15
|
+
| `DAY` | Duration of 1 day. |
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
SECOND = enum.auto()
|
|
19
|
+
MINUTE = enum.auto()
|
|
20
|
+
HOUR = enum.auto()
|
|
21
|
+
DAY = enum.auto()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OrderType(enum.Enum):
|
|
7
|
+
"""
|
|
8
|
+
Enumeration of order execution types.
|
|
9
|
+
|
|
10
|
+
| Value | Semantics |
|
|
11
|
+
|--------------|-------------------------------------------------------------|
|
|
12
|
+
| `LIMIT` | Executable only at the specified limit price or better. |
|
|
13
|
+
| `MARKET` | Executable immediately at the best available market price. |
|
|
14
|
+
| `STOP` | Becomes a market order once the stop price is reached. |
|
|
15
|
+
| `STOP_LIMIT` | Becomes a limit order once the stop price is reached. |
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
LIMIT = enum.auto()
|
|
19
|
+
MARKET = enum.auto()
|
|
20
|
+
STOP = enum.auto()
|
|
21
|
+
STOP_LIMIT = enum.auto()
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OrderRejectionReason(enum.Enum):
|
|
7
|
+
"""
|
|
8
|
+
Enumeration of canonical order rejection reasons.
|
|
9
|
+
|
|
10
|
+
This enumeration defines the system-level classification of order rejection causes.
|
|
11
|
+
It provides a stable, broker-agnostic taxonomy for programmatic handling of rejected orders.
|
|
12
|
+
|
|
13
|
+
| Value | Semantics |
|
|
14
|
+
|-----------|---------------------------------------------------------------------------|
|
|
15
|
+
| `UNKNOWN` | The rejection reason could not be classified into a known category. |
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
UNKNOWN = enum.auto()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ModificationRejectionReason(enum.Enum):
|
|
22
|
+
"""
|
|
23
|
+
Enumeration of canonical order modification rejection reasons.
|
|
24
|
+
|
|
25
|
+
This enumeration defines the system-level classification of reasons for which an order modification request may be rejected by a broker.
|
|
26
|
+
It provides a stable, broker-agnostic taxonomy intended for programmatic handling and observability of modification rejections.
|
|
27
|
+
|
|
28
|
+
| Value | Semantics |
|
|
29
|
+
|-----------|----------------------------------------------------------------------------------|
|
|
30
|
+
| `UNKNOWN` | The modification rejection reason could not be classified into a known category. |
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
UNKNOWN = enum.auto()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class CancellationRejectionReason(enum.Enum):
|
|
37
|
+
"""
|
|
38
|
+
Enumeration of canonical order cancellation rejection reasons.
|
|
39
|
+
|
|
40
|
+
This enumeration defines the system-level classification of reasons for which an order cancellation request may be rejected by a broker.
|
|
41
|
+
It provides a stable, broker-agnostic taxonomy intended for programmatic handling and observability of cancellation rejections.
|
|
42
|
+
|
|
43
|
+
| Value | Semantics |
|
|
44
|
+
|-----------|----------------------------------------------------------------------------------|
|
|
45
|
+
| `UNKNOWN` | The cancellation rejection reason could not be classified into a known category. |
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
UNKNOWN = enum.auto()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TradeSide(enum.Enum):
|
|
7
|
+
"""
|
|
8
|
+
Enumeration of trade direction.
|
|
9
|
+
|
|
10
|
+
`TradeSide` specifies the direction of change applied to the (net) signed position
|
|
11
|
+
quantity from the perspective of the trading account.
|
|
12
|
+
|
|
13
|
+
| Value | Semantics |
|
|
14
|
+
|---------|------------------------------------------------|
|
|
15
|
+
| `BUY` | Increases the signed position quantity. |
|
|
16
|
+
| `SELL` | Decreases the signed position quantity. |
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
BUY = enum.auto()
|
|
20
|
+
SELL = enum.auto()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: onesecondtrader
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.49.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,9 +11,15 @@ 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: databento (>=0.69.0,<0.70.0)
|
|
15
|
+
Requires-Dist: fastapi (>=0.128.0,<0.129.0)
|
|
16
|
+
Requires-Dist: ib-async (>=2.1.0,<3.0.0)
|
|
14
17
|
Requires-Dist: matplotlib (>=3.10.7,<4.0.0)
|
|
18
|
+
Requires-Dist: mplfinance (>=0.12.10b0,<0.13.0)
|
|
15
19
|
Requires-Dist: pandas (>=2.3.1,<3.0.0)
|
|
16
20
|
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
21
|
+
Requires-Dist: tqdm (>=4.67.1,<5.0.0)
|
|
22
|
+
Requires-Dist: uvicorn (>=0.40.0,<0.41.0)
|
|
17
23
|
Description-Content-Type: text/markdown
|
|
18
24
|
|
|
19
25
|
# OneSecondTrader
|
|
@@ -111,7 +117,7 @@ graph TD
|
|
|
111
117
|
B["<b>Code Quality Checks</b><br/>• Ruff Check & Format<br/>• MyPy Type Checking<br/>• Tests & Doctests"]
|
|
112
118
|
C["<b>Security Checks</b><br/>• Gitleaks Secret Detection"]
|
|
113
119
|
D["<b>File Validation</b><br/>• YAML/TOML/JSON Check<br/>• End-of-file Fixer<br/>• Large Files Check<br/>• Merge Conflict Check<br/>• Debug Statements Check"]
|
|
114
|
-
E["<b>Generate
|
|
120
|
+
E["<b>Generate Reference Documentation</b> via <kbd>scripts/generate_reference_docs.py</kbd><br/>• Auto-generate docs<br/>• Stage changes"]
|
|
115
121
|
end
|
|
116
122
|
B --> C --> D --> E
|
|
117
123
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
onesecondtrader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
onesecondtrader/events/__init__.py,sha256=1T7hJA6afxClEXvvnbXtHu9iMyhduRdJZWlg4ObWaKE,222
|
|
3
|
+
onesecondtrader/events/base.py,sha256=WpLo1bSKJe7Poh2IuDDCiBYZo9vE8mkq3cQlUpyTXsY,850
|
|
4
|
+
onesecondtrader/events/market/__init__.py,sha256=49z6maexBIDkAjIfkLbYzSZWEbyTpQ_HEEgT0eacrDo,132
|
|
5
|
+
onesecondtrader/events/market/bar_processed.py,sha256=NsCDGC21ykmioJoITspoAuz5mesKP0_hkM4UumWk1eU,1993
|
|
6
|
+
onesecondtrader/events/market/bar_received.py,sha256=_LJEZ7P-AfYQEIkXYNt-toO9_WG_XTS2Y86tb-qdOVU,1961
|
|
7
|
+
onesecondtrader/events/orders/__init__.py,sha256=IgVmiVUGMwDlFnL1ItAgvPwmkqEMJDLgQK8aJIKQ1Ic,164
|
|
8
|
+
onesecondtrader/events/orders/base.py,sha256=3zTY8JMkXiOV35k0tp6rZZ9X7pDN40Btm0SFT5Mq3nw,1650
|
|
9
|
+
onesecondtrader/events/orders/expirations.py,sha256=nW_28REmNNyxLpKzkAhwnC_mMqw00SqRediiZW8Zyz8,1465
|
|
10
|
+
onesecondtrader/events/orders/fills.py,sha256=IDSCR7__AAPWm69noV9TeE2C8LukZv-ju8yjDfgmA9w,2772
|
|
11
|
+
onesecondtrader/events/requests/__init__.py,sha256=PWVAjNdgHWZArWXz9HU7E-6ZgMdfCpn4wAJiM9a5q6E,325
|
|
12
|
+
onesecondtrader/events/requests/base.py,sha256=XXdiOy946hW3LmF7lMShi10kPtGftl928aPMDwEdnao,1084
|
|
13
|
+
onesecondtrader/events/requests/order_cancellation.py,sha256=X_ZMOx09gz0Hf8hvDE1OahqK1SoH4nw9IOMJIdbbTKs,1029
|
|
14
|
+
onesecondtrader/events/requests/order_modification.py,sha256=Tks2mXn1bkuOVLsk98tTk3E2CTld6SF1IwmkCvGvsc8,1538
|
|
15
|
+
onesecondtrader/events/requests/order_submission.py,sha256=ejLBEWJ7pzhXWcTncK1x_ZJfcaC21CnuEz00wvi1q-8,2155
|
|
16
|
+
onesecondtrader/events/responses/__init__.py,sha256=ihg3zxjygLi-sA6wIbsm163ic8346WiAVtztb6ONy_4,409
|
|
17
|
+
onesecondtrader/events/responses/base.py,sha256=tXOP3lvd6EqpC7NbfIJinUCI-KMz6xsR1YSQw5qNddk,1241
|
|
18
|
+
onesecondtrader/events/responses/cancellations.py,sha256=HWF15Flz2JNOaZvArAjl9jLAt1NrQxB3MASG-0A2Z2Y,2941
|
|
19
|
+
onesecondtrader/events/responses/modifications.py,sha256=ZQyehdwgAIg6HMmpQ5T_bWZ7yc4nfSeVwAGQ3T2O5-A,2968
|
|
20
|
+
onesecondtrader/events/responses/orders.py,sha256=enkIUYRw9G3bzAq-it20XvXBew2gLg1mAm44m-12bns,2786
|
|
21
|
+
onesecondtrader/indicators/__init__.py,sha256=i-syRqCdQdC2BLL-7bDBcdl2Mll1LgE7hi2GleCJ4HI,366
|
|
22
|
+
onesecondtrader/indicators/base.py,sha256=iGfgOj1B_LRGBeh7VjM5OjxoYnSxV7JZUP1C3O_dfmE,4653
|
|
23
|
+
onesecondtrader/indicators/market_fields.py,sha256=Znyii0egBkJT3CFlYhQ5ArRNidmBLF0TzgCr2AWu5CA,4306
|
|
24
|
+
onesecondtrader/indicators/moving_averages.py,sha256=Ej3Vg-K4Kf93J3MS6av2J8FRP1Kqx4G6yNZj1QfE9lU,3411
|
|
25
|
+
onesecondtrader/models/__init__.py,sha256=XWL6aNLwAA2JQMoqK2PY-_CwigV0ighx4zwGQVdmtCs,529
|
|
26
|
+
onesecondtrader/models/bar_fields.py,sha256=GnLBL08ueUr35w2dAbKwOBWrdBS98OC9r0T2NifwTH8,646
|
|
27
|
+
onesecondtrader/models/bar_period.py,sha256=J8ncVtcAxR52uD0nbC8Knds_GUP5wiuNj5rAKq4vv-4,475
|
|
28
|
+
onesecondtrader/models/order_types.py,sha256=SiJamarLQ7zkHzHLLbd86I_TeZrQJ4QEIMqNHj4dxXU,737
|
|
29
|
+
onesecondtrader/models/rejection_reasons.py,sha256=BToLmPholsP9GcLGZ874nQJpehZ1yB1SFyYqlf3AOwc,2127
|
|
30
|
+
onesecondtrader/models/trade_sides.py,sha256=Pf9BpxoUxqgKC_EKAExfSqgfIIK9NW-RpJES0XHRF-8,583
|
|
31
|
+
onesecondtrader-0.49.0.dist-info/METADATA,sha256=EFqtCI8r8EWYjn-l1LOkaWIsF0QrUZyq1UFA2WI56Dk,9951
|
|
32
|
+
onesecondtrader-0.49.0.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
|
|
33
|
+
onesecondtrader-0.49.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
34
|
+
onesecondtrader-0.49.0.dist-info/RECORD,,
|