onesecondtrader 0.41.0__tar.gz → 0.43.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.
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/PKG-INFO +1 -1
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/pyproject.toml +2 -1
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/__init__.py +2 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/connectors/datafeeds/simulated.py +42 -11
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/events/requests.py +2 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/models/__init__.py +2 -1
- onesecondtrader-0.43.0/src/onesecondtrader/core/models/orders.py +27 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/models/records.py +2 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/strategies/base.py +8 -1
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/strategies/examples.py +4 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/dashboard/app.py +1301 -6
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/orchestrator/recorder.py +5 -2
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/orchestrator/schema.sql +5 -1
- onesecondtrader-0.41.0/src/onesecondtrader/core/models/orders.py +0 -15
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/LICENSE +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/README.md +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/connectors/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/connectors/brokers/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/connectors/brokers/ib.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/connectors/brokers/simulated.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/connectors/datafeeds/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/connectors/datafeeds/ib.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/connectors/gateways/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/connectors/gateways/ib.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/brokers/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/brokers/base.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/datafeeds/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/datafeeds/base.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/events/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/events/bases.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/events/market.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/events/responses.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/indicators/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/indicators/averages.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/indicators/bar.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/indicators/base.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/messaging/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/messaging/eventbus.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/messaging/subscriber.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/models/data.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/models/params.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/strategies/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/dashboard/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/dashboard/registry.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/orchestrator/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/orchestrator/orchestrator.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/secmaster/__init__.py +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/secmaster/schema.sql +0 -0
- {onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/secmaster/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: onesecondtrader
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.43.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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "onesecondtrader"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.43.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"}
|
|
@@ -64,6 +64,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
64
64
|
explicit_package_bases = true
|
|
65
65
|
mypy_path = "src"
|
|
66
66
|
namespace_packages = true
|
|
67
|
+
exclude = ["ignore/"]
|
|
67
68
|
|
|
68
69
|
[tool.pytest.ini_options]
|
|
69
70
|
testpaths = ["tests"]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
__all__ = [
|
|
2
|
+
"ActionType",
|
|
2
3
|
"BarPeriod",
|
|
3
4
|
"BarProcessed",
|
|
4
5
|
"BarReceived",
|
|
@@ -47,6 +48,7 @@ from onesecondtrader.core.indicators import (
|
|
|
47
48
|
Volume,
|
|
48
49
|
)
|
|
49
50
|
from onesecondtrader.core.models import (
|
|
51
|
+
ActionType,
|
|
50
52
|
BarPeriod,
|
|
51
53
|
FillRecord,
|
|
52
54
|
InputSource,
|
|
@@ -88,12 +88,16 @@ class SimulatedDatafeed(DatafeedBase):
|
|
|
88
88
|
|
|
89
89
|
cursor = self._connection.cursor()
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
if not
|
|
91
|
+
symbology_map = self._load_symbology(cursor, symbols)
|
|
92
|
+
if not symbology_map:
|
|
93
93
|
return
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
all_instrument_ids = set()
|
|
96
|
+
for entries in symbology_map.values():
|
|
97
|
+
for entry in entries:
|
|
98
|
+
all_instrument_ids.add(entry["instrument_id"])
|
|
99
|
+
|
|
100
|
+
id_list = list(all_instrument_ids)
|
|
97
101
|
rtype_list = list(set(rtype_by_symbol.values()))
|
|
98
102
|
|
|
99
103
|
placeholders_ids = ",".join("?" * len(id_list))
|
|
@@ -128,7 +132,10 @@ class SimulatedDatafeed(DatafeedBase):
|
|
|
128
132
|
break
|
|
129
133
|
|
|
130
134
|
instrument_id, rtype, ts_event, open_, high, low, close, volume = row
|
|
131
|
-
|
|
135
|
+
|
|
136
|
+
symbol = self._resolve_symbol_for_bar(
|
|
137
|
+
symbology_map, instrument_id, ts_event
|
|
138
|
+
)
|
|
132
139
|
if symbol is None:
|
|
133
140
|
continue
|
|
134
141
|
|
|
@@ -152,16 +159,40 @@ class SimulatedDatafeed(DatafeedBase):
|
|
|
152
159
|
)
|
|
153
160
|
self._event_bus.wait_until_system_idle()
|
|
154
161
|
|
|
155
|
-
def
|
|
162
|
+
def _load_symbology(
|
|
156
163
|
self, cursor: sqlite3.Cursor, symbols: list[str]
|
|
157
|
-
) -> dict[str,
|
|
164
|
+
) -> dict[str, list[dict]]:
|
|
158
165
|
placeholders = ",".join("?" * len(symbols))
|
|
159
166
|
query = f"""
|
|
160
|
-
SELECT symbol, instrument_id
|
|
167
|
+
SELECT symbol, instrument_id, start_date, end_date
|
|
161
168
|
FROM symbology
|
|
162
169
|
WHERE symbol IN ({placeholders})
|
|
163
|
-
|
|
164
|
-
HAVING start_date = MAX(start_date)
|
|
170
|
+
ORDER BY symbol, start_date
|
|
165
171
|
"""
|
|
166
172
|
cursor.execute(query, symbols)
|
|
167
|
-
|
|
173
|
+
|
|
174
|
+
result: dict[str, list[dict]] = {}
|
|
175
|
+
for row in cursor.fetchall():
|
|
176
|
+
symbol, instrument_id, start_date, end_date = row
|
|
177
|
+
start_ns = int(pd.Timestamp(start_date, tz="UTC").value)
|
|
178
|
+
end_ns = int(pd.Timestamp(end_date, tz="UTC").value)
|
|
179
|
+
if symbol not in result:
|
|
180
|
+
result[symbol] = []
|
|
181
|
+
result[symbol].append(
|
|
182
|
+
{
|
|
183
|
+
"instrument_id": instrument_id,
|
|
184
|
+
"start_ns": start_ns,
|
|
185
|
+
"end_ns": end_ns,
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
return result
|
|
189
|
+
|
|
190
|
+
def _resolve_symbol_for_bar(
|
|
191
|
+
self, symbology_map: dict[str, list[dict]], instrument_id: int, ts_event: int
|
|
192
|
+
) -> str | None:
|
|
193
|
+
for symbol, entries in symbology_map.items():
|
|
194
|
+
for entry in entries:
|
|
195
|
+
if entry["instrument_id"] == instrument_id:
|
|
196
|
+
if entry["start_ns"] <= ts_event < entry["end_ns"]:
|
|
197
|
+
return symbol
|
|
198
|
+
return None
|
{onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/events/requests.py
RENAMED
|
@@ -16,6 +16,8 @@ class OrderSubmission(bases.BrokerRequestEvent):
|
|
|
16
16
|
quantity: float
|
|
17
17
|
limit_price: float | None = None
|
|
18
18
|
stop_price: float | None = None
|
|
19
|
+
action: models.orders.ActionType | None = None
|
|
20
|
+
signal: str | None = None
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
@dataclasses.dataclass(kw_only=True, frozen=True)
|
{onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/models/__init__.py
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
__all__ = [
|
|
2
|
+
"ActionType",
|
|
2
3
|
"BarPeriod",
|
|
3
4
|
"InputSource",
|
|
4
5
|
"OrderSide",
|
|
@@ -9,6 +10,6 @@ __all__ = [
|
|
|
9
10
|
]
|
|
10
11
|
|
|
11
12
|
from .data import BarPeriod, InputSource
|
|
12
|
-
from .orders import OrderSide, OrderType
|
|
13
|
+
from .orders import ActionType, OrderSide, OrderType
|
|
13
14
|
from .records import OrderRecord, FillRecord
|
|
14
15
|
from .params import ParamSpec
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OrderType(enum.Enum):
|
|
7
|
+
LIMIT = enum.auto()
|
|
8
|
+
MARKET = enum.auto()
|
|
9
|
+
STOP = enum.auto()
|
|
10
|
+
STOP_LIMIT = enum.auto()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class OrderSide(enum.Enum):
|
|
14
|
+
BUY = enum.auto()
|
|
15
|
+
SELL = enum.auto()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ActionType(enum.Enum):
|
|
19
|
+
ENTRY = enum.auto()
|
|
20
|
+
ENTRY_LONG = enum.auto()
|
|
21
|
+
ENTRY_SHORT = enum.auto()
|
|
22
|
+
EXIT = enum.auto()
|
|
23
|
+
EXIT_LONG = enum.auto()
|
|
24
|
+
EXIT_SHORT = enum.auto()
|
|
25
|
+
ADD = enum.auto()
|
|
26
|
+
REDUCE = enum.auto()
|
|
27
|
+
REVERSE = enum.auto()
|
{onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/strategies/base.py
RENAMED
|
@@ -76,8 +76,9 @@ class StrategyBase(messaging.Subscriber, abc.ABC):
|
|
|
76
76
|
quantity: float,
|
|
77
77
|
limit_price: float | None = None,
|
|
78
78
|
stop_price: float | None = None,
|
|
79
|
+
action: models.ActionType | None = None,
|
|
80
|
+
signal: str | None = None,
|
|
79
81
|
) -> uuid.UUID:
|
|
80
|
-
# Uses bar timestamp for backtest compatibility; ts_created tracks real wall-clock time
|
|
81
82
|
order_id = uuid.uuid4()
|
|
82
83
|
|
|
83
84
|
event = events.OrderSubmission(
|
|
@@ -89,6 +90,8 @@ class StrategyBase(messaging.Subscriber, abc.ABC):
|
|
|
89
90
|
quantity=quantity,
|
|
90
91
|
limit_price=limit_price,
|
|
91
92
|
stop_price=stop_price,
|
|
93
|
+
action=action,
|
|
94
|
+
signal=signal,
|
|
92
95
|
)
|
|
93
96
|
|
|
94
97
|
order = models.OrderRecord(
|
|
@@ -99,6 +102,8 @@ class StrategyBase(messaging.Subscriber, abc.ABC):
|
|
|
99
102
|
quantity=quantity,
|
|
100
103
|
limit_price=limit_price,
|
|
101
104
|
stop_price=stop_price,
|
|
105
|
+
action=action,
|
|
106
|
+
signal=signal,
|
|
102
107
|
)
|
|
103
108
|
|
|
104
109
|
self._submitted_orders[order_id] = order
|
|
@@ -137,6 +142,8 @@ class StrategyBase(messaging.Subscriber, abc.ABC):
|
|
|
137
142
|
stop_price=(
|
|
138
143
|
stop_price if stop_price is not None else original_order.stop_price
|
|
139
144
|
),
|
|
145
|
+
action=original_order.action,
|
|
146
|
+
signal=original_order.signal,
|
|
140
147
|
filled_quantity=original_order.filled_quantity,
|
|
141
148
|
)
|
|
142
149
|
|
{onesecondtrader-0.41.0 → onesecondtrader-0.43.0}/src/onesecondtrader/core/strategies/examples.py
RENAMED
|
@@ -29,6 +29,8 @@ class SMACrossover(StrategyBase):
|
|
|
29
29
|
models.OrderType.MARKET,
|
|
30
30
|
models.OrderSide.BUY,
|
|
31
31
|
self.quantity, # type: ignore[attr-defined]
|
|
32
|
+
action=models.ActionType.ENTRY,
|
|
33
|
+
signal="sma_crossover_up",
|
|
32
34
|
)
|
|
33
35
|
|
|
34
36
|
if (
|
|
@@ -40,4 +42,6 @@ class SMACrossover(StrategyBase):
|
|
|
40
42
|
models.OrderType.MARKET,
|
|
41
43
|
models.OrderSide.SELL,
|
|
42
44
|
self.quantity, # type: ignore[attr-defined]
|
|
45
|
+
action=models.ActionType.EXIT,
|
|
46
|
+
signal="sma_crossover_down",
|
|
43
47
|
)
|