onesecondtrader 0.14.1__tar.gz → 0.14.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.
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/PKG-INFO +1 -1
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/pyproject.toml +1 -1
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/core/portfolio.py +113 -102
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/messaging/events.py +29 -1
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/LICENSE +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/README.md +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/__init__.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/brokers/__init__.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/brokers/base_broker.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/brokers/simulated_broker.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/core/__init__.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/core/models.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/core/py.typed +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/datafeeds/__init__.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/datafeeds/base_datafeed.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/datafeeds/csv_datafeed.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/indicators/__init__.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/indicators/base_indicator.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/indicators/moving_averages.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/messaging/__init__.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/messaging/eventbus.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/monitoring/__init__.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/monitoring/console.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/monitoring/py.typed +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/py.typed +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/strategies/__init__.py +0 -0
- {onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/strategies/base_strategy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: onesecondtrader
|
|
3
|
-
Version: 0.14.
|
|
3
|
+
Version: 0.14.2
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "onesecondtrader"
|
|
3
|
-
version = "0.14.
|
|
3
|
+
version = "0.14.2"
|
|
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"}
|
|
@@ -47,8 +47,9 @@ class Portfolio:
|
|
|
47
47
|
self._symbol_owner (dict[str, base_strategy.Strategy]): Exclusive symbol
|
|
48
48
|
ownership map; each symbol is owned by at most one strategy instance at
|
|
49
49
|
a time.
|
|
50
|
-
self.
|
|
51
|
-
are still active but marked for removal once all symbols
|
|
50
|
+
self.strategy_removal_pending (set[base_strategy.Strategy]): Set of
|
|
51
|
+
strategies that are still active but marked for removal once all symbols
|
|
52
|
+
are released.
|
|
52
53
|
self.broker (base_broker.BaseBroker | None): Instantiated broker; may be
|
|
53
54
|
disconnected if connect failed.
|
|
54
55
|
"""
|
|
@@ -69,11 +70,12 @@ class Portfolio:
|
|
|
69
70
|
# KEEP TRACK OF STRATEGIES AND SYMBOL OWNERSHIP
|
|
70
71
|
# ------------------------------------------------------------------------------
|
|
71
72
|
self._strategies: set[base_strategy.Strategy] = set()
|
|
73
|
+
self.strategy_removal_pending: set[base_strategy.Strategy] = set()
|
|
72
74
|
self._symbol_owner: dict[str, base_strategy.Strategy] = {}
|
|
73
|
-
self._removal_pending: set[base_strategy.Strategy] = set()
|
|
74
75
|
|
|
75
76
|
# INITIALIZE BROKER
|
|
76
77
|
# ------------------------------------------------------------------------------
|
|
78
|
+
# TODO Decouple by also doing this via an event
|
|
77
79
|
self.broker: base_broker.BaseBroker | None = None
|
|
78
80
|
if broker_class is None or not issubclass(broker_class, base_broker.BaseBroker):
|
|
79
81
|
broker_name = (
|
|
@@ -167,13 +169,23 @@ class Portfolio:
|
|
|
167
169
|
"use Portfolio.assign_symbols(...) after resolving. "
|
|
168
170
|
f"non_conflicting={non_conflicting}, conflicts={conflicting}"
|
|
169
171
|
)
|
|
172
|
+
return False
|
|
170
173
|
else:
|
|
171
|
-
|
|
174
|
+
for sym in symbols_list:
|
|
175
|
+
self._symbol_owner[sym] = strategy_instance
|
|
176
|
+
self.event_bus.publish(
|
|
177
|
+
events.Strategy.SymbolAssignment(
|
|
178
|
+
strategy=strategy_instance,
|
|
179
|
+
symbol_list=symbols_list,
|
|
180
|
+
)
|
|
181
|
+
)
|
|
182
|
+
return True
|
|
183
|
+
|
|
172
184
|
return True
|
|
173
185
|
|
|
174
186
|
def remove_strategy(
|
|
175
187
|
self,
|
|
176
|
-
|
|
188
|
+
strategy_instance: base_strategy.Strategy,
|
|
177
189
|
shutdown_mode: StrategyShutdownMode = StrategyShutdownMode.SOFT,
|
|
178
190
|
) -> bool:
|
|
179
191
|
"""
|
|
@@ -182,93 +194,90 @@ class Portfolio:
|
|
|
182
194
|
for open positions to close naturally and release symbols once they are flat).
|
|
183
195
|
|
|
184
196
|
Args:
|
|
185
|
-
|
|
197
|
+
strategy_instance (base_strategy.Strategy): Strategy instance to remove.
|
|
186
198
|
shutdown_mode (StrategyShutdownMode): Shutdown mode to use. Defaults to
|
|
187
199
|
StrategyShutdownMode.SOFT.
|
|
188
200
|
"""
|
|
189
201
|
|
|
190
|
-
# IF STRATEGY IS REGISTERED, MARK IT FOR REMOVAL
|
|
202
|
+
# IF STRATEGY IS REGISTERED, MARK IT FOR REMOVAL AND PUBLISH STOP TRADING EVENT
|
|
191
203
|
# ------------------------------------------------------------------------------
|
|
192
204
|
with self._lock:
|
|
193
|
-
if
|
|
205
|
+
if strategy_instance not in self._strategies:
|
|
194
206
|
console.logger.warning("remove_strategy: strategy not registered")
|
|
195
207
|
return False
|
|
196
|
-
self.
|
|
208
|
+
self.strategy_removal_pending.add(strategy_instance)
|
|
197
209
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
try:
|
|
206
|
-
if bool(strategy.is_flat()):
|
|
207
|
-
# If the strategy is already flat and owns no symbols, deregister now
|
|
208
|
-
with self._lock:
|
|
209
|
-
has_owned_left = any(
|
|
210
|
-
owner is strategy for owner in self._symbol_owner.values()
|
|
211
|
-
)
|
|
212
|
-
if not has_owned_left:
|
|
213
|
-
if strategy in self._strategies:
|
|
214
|
-
self._strategies.remove(strategy)
|
|
215
|
-
self._removal_pending.discard(strategy)
|
|
216
|
-
console.logger.info(
|
|
217
|
-
f"Strategy {getattr(strategy, 'name', type(strategy).__name__)} removed: flat and no symbols owned"
|
|
218
|
-
)
|
|
219
|
-
return True
|
|
220
|
-
except Exception:
|
|
221
|
-
console.logger.warning(
|
|
222
|
-
"remove_strategy: strategy does not implement is_flat; will wait for symbol releases"
|
|
210
|
+
# PUBLISH STOP TRADING REQUEST TO EVENT BUS
|
|
211
|
+
# ------------------------------------------------------------------------------
|
|
212
|
+
self.event_bus.publish(
|
|
213
|
+
events.Strategy.StopTrading(
|
|
214
|
+
strategy=strategy_instance,
|
|
215
|
+
shutdown_mode=shutdown_mode,
|
|
223
216
|
)
|
|
224
|
-
|
|
217
|
+
)
|
|
218
|
+
return True
|
|
225
219
|
|
|
226
220
|
def assign_symbols(
|
|
227
|
-
self,
|
|
228
|
-
|
|
229
|
-
symbols: Iterable[str],
|
|
230
|
-
) -> tuple[list[str], list[str]]:
|
|
221
|
+
self, strategy_instance: base_strategy.Strategy, symbols: Iterable[str]
|
|
222
|
+
):
|
|
231
223
|
"""
|
|
232
|
-
Assign symbols to a strategy
|
|
224
|
+
Assign a list of symbols to a strategy.
|
|
233
225
|
|
|
234
|
-
|
|
235
|
-
|
|
226
|
+
Args:
|
|
227
|
+
strategy_instance (base_strategy.Strategy): Strategy instance to assign
|
|
228
|
+
symbols to.
|
|
229
|
+
symbols (Iterable[str]): List of symbols to assign.
|
|
236
230
|
"""
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return [], list(symbols)
|
|
240
|
-
symbols_list = list(
|
|
241
|
-
dict.fromkeys(s.strip() for s in symbols if s and s.strip())
|
|
242
|
-
)
|
|
243
|
-
if not symbols_list:
|
|
244
|
-
return [], []
|
|
245
|
-
accepted: list[str] = []
|
|
246
|
-
conflicts: list[str] = []
|
|
231
|
+
# IF STRATEGY IS REGISTERED, MARK IT FOR REMOVAL AND PUBLISH STOP TRADING EVENT
|
|
232
|
+
# ------------------------------------------------------------------------------
|
|
247
233
|
with self._lock:
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if
|
|
258
|
-
|
|
259
|
-
|
|
234
|
+
if strategy_instance not in self._strategies:
|
|
235
|
+
console.logger.warning("remove_strategy: strategy not registered")
|
|
236
|
+
return False
|
|
237
|
+
self.strategy_removal_pending.add(strategy_instance)
|
|
238
|
+
|
|
239
|
+
# ASSIGN SYMBOLS IF PROVIDED AND NO CONFLICTS EXIST, ELSE LOG WARNING
|
|
240
|
+
# ------------------------------------------------------------------------------
|
|
241
|
+
# TODO This is an repetition of the same logic as in add_strategy; refactor
|
|
242
|
+
|
|
243
|
+
if symbols is not None:
|
|
244
|
+
# Create an ordered list of unique, non-empty, trimmed symbols
|
|
245
|
+
symbols_list = list(
|
|
246
|
+
dict.fromkeys(s.strip() for s in symbols if s and s.strip())
|
|
260
247
|
)
|
|
261
|
-
|
|
248
|
+
|
|
249
|
+
# Check for conflicts, claim symbols for strategy if no conflicts arise
|
|
250
|
+
if symbols_list:
|
|
251
|
+
non_conflicting: list[str] = []
|
|
252
|
+
conflicting: list[str] = []
|
|
253
|
+
with self._lock:
|
|
254
|
+
for sym in symbols_list:
|
|
255
|
+
owner = self._symbol_owner.get(sym)
|
|
256
|
+
if owner is None or owner is strategy_instance:
|
|
257
|
+
non_conflicting.append(sym)
|
|
258
|
+
else:
|
|
259
|
+
conflicting.append(sym)
|
|
260
|
+
if conflicting:
|
|
261
|
+
console.logger.warning(
|
|
262
|
+
"assign_symbols: symbols not assigned due to conflicts; "
|
|
263
|
+
"use Portfolio.assign_symbols(...) after resolving. "
|
|
264
|
+
f"non_conflicting={non_conflicting}, conflicts={conflicting}"
|
|
265
|
+
)
|
|
266
|
+
return False
|
|
267
|
+
else:
|
|
268
|
+
for sym in symbols_list:
|
|
269
|
+
self._symbol_owner[sym] = strategy_instance
|
|
270
|
+
self.event_bus.publish(
|
|
271
|
+
events.Strategy.SymbolAssignment(
|
|
272
|
+
strategy=strategy_instance,
|
|
273
|
+
symbol_list=symbols_list,
|
|
274
|
+
)
|
|
275
|
+
)
|
|
276
|
+
return True
|
|
262
277
|
|
|
263
278
|
def unassign_symbols(
|
|
264
279
|
self, strategy: base_strategy.Strategy, symbols: Iterable[str]
|
|
265
280
|
) -> list[str]:
|
|
266
|
-
"""
|
|
267
|
-
Release symbol ownership from a strategy.
|
|
268
|
-
|
|
269
|
-
Returns:
|
|
270
|
-
list[str]: Symbols actually unassigned.
|
|
271
|
-
"""
|
|
272
281
|
if not isinstance(strategy, base_strategy.Strategy):
|
|
273
282
|
console.logger.error(
|
|
274
283
|
"unassign_symbols: strategy must inherit from Strategy"
|
|
@@ -296,23 +305,38 @@ class Portfolio:
|
|
|
296
305
|
with self._lock:
|
|
297
306
|
return self._symbol_owner.get(symbol)
|
|
298
307
|
|
|
299
|
-
def
|
|
300
|
-
self, strategy: base_strategy.Strategy, symbols: Iterable[str]
|
|
301
|
-
) -> list[str]:
|
|
308
|
+
def on_symbol_release(self, event: events.Base.Event) -> None:
|
|
302
309
|
"""
|
|
303
|
-
|
|
310
|
+
Handle symbol release events. Ignores unrelated event types.
|
|
304
311
|
|
|
305
|
-
If
|
|
306
|
-
|
|
307
|
-
deregistered.
|
|
312
|
+
If a symbol is released, it is unassigned from the strategy that owns it
|
|
313
|
+
(inside the symbol_owner registry). If the strategy is marked for removal and
|
|
314
|
+
has no more symbols assigned to it, it is automatically deregistered.
|
|
308
315
|
"""
|
|
309
|
-
|
|
316
|
+
|
|
317
|
+
# IGNORE UNRELATED EVENT TYPES
|
|
318
|
+
# ------------------------------------------------------------------------------
|
|
319
|
+
if not isinstance(event, events.Strategy.SymbolRelease):
|
|
320
|
+
return
|
|
321
|
+
|
|
322
|
+
# IF STRATEGY IS REGISTERED, RELEASE SYMBOL FROM STRATEGY
|
|
323
|
+
# ------------------------------------------------------------------------------
|
|
324
|
+
# TODO This needs reworking; this will be the same logic as unassig_symbols
|
|
325
|
+
strategy = event.strategy
|
|
326
|
+
with self._lock:
|
|
327
|
+
if strategy not in self._strategies:
|
|
328
|
+
console.logger.warning("on_symbol_release: strategy not registered")
|
|
329
|
+
return
|
|
330
|
+
removed = self.unassign_symbols(strategy, [event.symbol])
|
|
310
331
|
if not removed:
|
|
311
|
-
|
|
312
|
-
|
|
332
|
+
console.logger.warning(
|
|
333
|
+
f"on_symbol_release: symbol {event.symbol} not owned by "
|
|
334
|
+
f"{getattr(event.strategy, 'name', type(event.strategy).__name__)}"
|
|
335
|
+
)
|
|
336
|
+
return
|
|
313
337
|
pending = False
|
|
314
338
|
with self._lock:
|
|
315
|
-
pending = strategy in self.
|
|
339
|
+
pending = strategy in self.strategy_removal_pending
|
|
316
340
|
has_owned_left = any(
|
|
317
341
|
owner is strategy for owner in self._symbol_owner.values()
|
|
318
342
|
)
|
|
@@ -322,27 +346,14 @@ class Portfolio:
|
|
|
322
346
|
with self._lock:
|
|
323
347
|
if strategy in self._strategies:
|
|
324
348
|
self._strategies.remove(strategy)
|
|
325
|
-
self.
|
|
349
|
+
self.strategy_removal_pending.discard(strategy)
|
|
326
350
|
console.logger.info(
|
|
327
|
-
f"Strategy {getattr(strategy, 'name', type(strategy).__name__)}
|
|
351
|
+
f"Strategy {getattr(strategy, 'name', type(strategy).__name__)} "
|
|
352
|
+
f"removed: all symbols released and flat"
|
|
328
353
|
)
|
|
329
354
|
except Exception:
|
|
330
355
|
pass
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
Handle symbol release events. Ignores unrelated event types.
|
|
336
|
-
"""
|
|
337
|
-
if not isinstance(event, events.Strategy.SymbolRelease):
|
|
338
|
-
return
|
|
339
|
-
strategy = event.strategy
|
|
340
|
-
with self._lock:
|
|
341
|
-
if strategy not in self._strategies:
|
|
342
|
-
console.logger.warning("on_symbol_release: strategy not registered")
|
|
343
|
-
return
|
|
344
|
-
removed = self.release_symbols_from_strategy(strategy, [event.symbol])
|
|
345
|
-
if not removed:
|
|
346
|
-
console.logger.warning(
|
|
347
|
-
f"on_symbol_release: symbol {event.symbol} not owned by {getattr(event.strategy, 'name', type(event.strategy).__name__)}"
|
|
348
|
-
)
|
|
356
|
+
console.logger.info(
|
|
357
|
+
f"on_symbol_release: symbol {event.symbol} released from "
|
|
358
|
+
f"{getattr(event.strategy, 'name', type(event.strategy).__name__)}"
|
|
359
|
+
)
|
|
@@ -86,13 +86,16 @@ Dataclass field validation logic is grouped under the `_Validate` namespace.
|
|
|
86
86
|
style D1 fill:#6F42C1,fill-opacity:0.3
|
|
87
87
|
|
|
88
88
|
E1[events.Strategy.SymbolRelease]
|
|
89
|
-
E2[events.Strategy.
|
|
89
|
+
E2[events.Strategy.SymbolAssignment]
|
|
90
|
+
E3[events.Strategy.StopTrading]
|
|
90
91
|
|
|
91
92
|
R5 --> E1
|
|
92
93
|
R5 --> E2
|
|
94
|
+
R5 --> E3
|
|
93
95
|
|
|
94
96
|
style E1 fill:#6F42C1,fill-opacity:0.3
|
|
95
97
|
style E2 fill:#6F42C1,fill-opacity:0.3
|
|
98
|
+
style E3 fill:#6F42C1,fill-opacity:0.3
|
|
96
99
|
|
|
97
100
|
subgraph Market ["Market Update Event Messages"]
|
|
98
101
|
R1
|
|
@@ -159,10 +162,12 @@ Dataclass field validation logic is grouped under the `_Validate` namespace.
|
|
|
159
162
|
R5
|
|
160
163
|
E1
|
|
161
164
|
E2
|
|
165
|
+
E3
|
|
162
166
|
|
|
163
167
|
subgraph StrategyNamespace ["events.Strategy Namespace"]
|
|
164
168
|
E1
|
|
165
169
|
E2
|
|
170
|
+
E3
|
|
166
171
|
end
|
|
167
172
|
|
|
168
173
|
end
|
|
@@ -778,6 +783,29 @@ class Strategy:
|
|
|
778
783
|
super().__post_init__()
|
|
779
784
|
_Validate.symbol(self.symbol, "Strategy.SymbolRelease")
|
|
780
785
|
|
|
786
|
+
@dataclasses.dataclass(kw_only=True, frozen=True)
|
|
787
|
+
class SymbolAssignment(Base.Strategy):
|
|
788
|
+
"""
|
|
789
|
+
Event message to indicate that a symbol should be assigned to a strategy.
|
|
790
|
+
|
|
791
|
+
Attributes:
|
|
792
|
+
symbol_list (list[str]): List of symbols to be assigned.
|
|
793
|
+
|
|
794
|
+
Examples:
|
|
795
|
+
>>> from onesecondtrader.messaging import events
|
|
796
|
+
>>> event = events.Strategy.SymbolAssignment(
|
|
797
|
+
... strategy=my_strategy,
|
|
798
|
+
... symbol=["AAPL"],
|
|
799
|
+
... )
|
|
800
|
+
"""
|
|
801
|
+
|
|
802
|
+
symbol_list: list[str]
|
|
803
|
+
|
|
804
|
+
def __post_init__(self) -> None:
|
|
805
|
+
super().__post_init__()
|
|
806
|
+
for symbol in self.symbol_list:
|
|
807
|
+
_Validate.symbol(symbol, "Strategy.SymbolAssignment")
|
|
808
|
+
|
|
781
809
|
@dataclasses.dataclass(kw_only=True, frozen=True)
|
|
782
810
|
class StopTrading(Base.Strategy):
|
|
783
811
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/brokers/base_broker.py
RENAMED
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/brokers/simulated_broker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/datafeeds/base_datafeed.py
RENAMED
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/datafeeds/csv_datafeed.py
RENAMED
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/indicators/__init__.py
RENAMED
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/indicators/base_indicator.py
RENAMED
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/indicators/moving_averages.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/monitoring/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/strategies/__init__.py
RENAMED
|
File without changes
|
{onesecondtrader-0.14.1 → onesecondtrader-0.14.2}/src/onesecondtrader/strategies/base_strategy.py
RENAMED
|
File without changes
|