onesecondtrader 0.35.0__py3-none-any.whl → 0.36.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.
Files changed (39) hide show
  1. onesecondtrader/connectors/__init__.py +2 -0
  2. onesecondtrader/connectors/brokers/__init__.py +3 -0
  3. onesecondtrader/connectors/brokers/simulated.py +346 -0
  4. onesecondtrader/connectors/datafeeds/__init__.py +4 -0
  5. onesecondtrader/connectors/datafeeds/base.py +19 -0
  6. onesecondtrader/connectors/datafeeds/simulated.py +99 -0
  7. onesecondtrader/core/__init__.py +6 -0
  8. onesecondtrader/core/brokers/__init__.py +3 -0
  9. onesecondtrader/core/brokers/base.py +39 -0
  10. onesecondtrader/core/events/__init__.py +33 -0
  11. onesecondtrader/core/events/bases.py +29 -0
  12. onesecondtrader/core/events/market.py +22 -0
  13. onesecondtrader/core/events/requests.py +31 -0
  14. onesecondtrader/core/events/responses.py +54 -0
  15. onesecondtrader/core/indicators/__init__.py +13 -0
  16. onesecondtrader/core/indicators/averages.py +56 -0
  17. onesecondtrader/core/indicators/bar.py +47 -0
  18. onesecondtrader/core/indicators/base.py +60 -0
  19. onesecondtrader/core/messaging/__init__.py +7 -0
  20. onesecondtrader/core/messaging/eventbus.py +47 -0
  21. onesecondtrader/core/messaging/subscriber.py +69 -0
  22. onesecondtrader/core/models/__init__.py +12 -0
  23. onesecondtrader/core/models/data.py +18 -0
  24. onesecondtrader/core/models/orders.py +15 -0
  25. onesecondtrader/core/models/records.py +32 -0
  26. onesecondtrader/core/strategies/__init__.py +7 -0
  27. onesecondtrader/core/strategies/base.py +318 -0
  28. onesecondtrader/core/strategies/examples.py +35 -0
  29. onesecondtrader/dashboard/__init__.py +0 -0
  30. onesecondtrader/secmaster/__init__.py +5 -0
  31. onesecondtrader/secmaster/schema.sql +46 -0
  32. onesecondtrader/secmaster/utils.py +26 -0
  33. {onesecondtrader-0.35.0.dist-info → onesecondtrader-0.36.0.dist-info}/METADATA +1 -1
  34. onesecondtrader-0.36.0.dist-info/RECORD +62 -0
  35. onesecondtrader/observers/__init__.py +0 -5
  36. onesecondtrader/observers/csvbookkeeper.py +0 -180
  37. onesecondtrader-0.35.0.dist-info/RECORD +0 -32
  38. {onesecondtrader-0.35.0.dist-info → onesecondtrader-0.36.0.dist-info}/WHEEL +0 -0
  39. {onesecondtrader-0.35.0.dist-info → onesecondtrader-0.36.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,318 @@
1
+ from __future__ import annotations
2
+
3
+ import abc
4
+ import uuid
5
+ from types import SimpleNamespace
6
+
7
+ import pandas as pd
8
+
9
+ from onesecondtrader.core import events, indicators, messaging, models
10
+
11
+
12
+ class StrategyBase(messaging.Subscriber, abc.ABC):
13
+ symbols: list[str] = []
14
+ bar_period: models.BarPeriod = models.BarPeriod.SECOND
15
+
16
+ def __init__(self, event_bus: messaging.EventBus) -> None:
17
+ super().__init__(event_bus)
18
+ self._subscribe(
19
+ events.BarReceived,
20
+ events.OrderSubmissionAccepted,
21
+ events.OrderModificationAccepted,
22
+ events.OrderCancellationAccepted,
23
+ events.OrderSubmissionRejected,
24
+ events.OrderModificationRejected,
25
+ events.OrderCancellationRejected,
26
+ events.OrderFilled,
27
+ events.OrderExpired,
28
+ )
29
+
30
+ self._current_symbol: str = ""
31
+ self._current_ts: pd.Timestamp = pd.Timestamp.now(tz="UTC")
32
+ self._indicators: list[indicators.Indicator] = []
33
+
34
+ self._fills: dict[str, list[models.FillRecord]] = {}
35
+ self._positions: dict[str, float] = {}
36
+ self._avg_prices: dict[str, float] = {}
37
+ self._pending_orders: dict[uuid.UUID, models.OrderRecord] = {}
38
+ self._submitted_orders: dict[uuid.UUID, models.OrderRecord] = {}
39
+ self._submitted_modifications: dict[uuid.UUID, models.OrderRecord] = {}
40
+ self._submitted_cancellations: dict[uuid.UUID, models.OrderRecord] = {}
41
+
42
+ # OHLCV as indicators for history access: self.bar.close.history
43
+ self.bar = SimpleNamespace(
44
+ open=self.add_indicator(indicators.Open()),
45
+ high=self.add_indicator(indicators.High()),
46
+ low=self.add_indicator(indicators.Low()),
47
+ close=self.add_indicator(indicators.Close()),
48
+ volume=self.add_indicator(indicators.Volume()),
49
+ )
50
+
51
+ # Hook for subclasses to register indicators without overriding __init__
52
+ self.setup()
53
+
54
+ def add_indicator(self, ind: indicators.Indicator) -> indicators.Indicator:
55
+ self._indicators.append(ind)
56
+ return ind
57
+
58
+ @property
59
+ def position(self) -> float:
60
+ return self._positions.get(self._current_symbol, 0.0)
61
+
62
+ @property
63
+ def avg_price(self) -> float:
64
+ return self._avg_prices.get(self._current_symbol, 0.0)
65
+
66
+ def submit_order(
67
+ self,
68
+ order_type: models.OrderType,
69
+ side: models.OrderSide,
70
+ quantity: float,
71
+ limit_price: float | None = None,
72
+ stop_price: float | None = None,
73
+ ) -> uuid.UUID:
74
+ # Uses bar timestamp for backtest compatibility; ts_created tracks real wall-clock time
75
+ order_id = uuid.uuid4()
76
+
77
+ event = events.OrderSubmission(
78
+ ts_event=self._current_ts,
79
+ system_order_id=order_id,
80
+ symbol=self._current_symbol,
81
+ order_type=order_type,
82
+ side=side,
83
+ quantity=quantity,
84
+ limit_price=limit_price,
85
+ stop_price=stop_price,
86
+ )
87
+
88
+ order = models.OrderRecord(
89
+ order_id=order_id,
90
+ symbol=self._current_symbol,
91
+ order_type=order_type,
92
+ side=side,
93
+ quantity=quantity,
94
+ limit_price=limit_price,
95
+ stop_price=stop_price,
96
+ )
97
+
98
+ self._submitted_orders[order_id] = order
99
+ self._publish(event)
100
+ return order_id
101
+
102
+ def submit_modification(
103
+ self,
104
+ order_id: uuid.UUID,
105
+ quantity: float | None = None,
106
+ limit_price: float | None = None,
107
+ stop_price: float | None = None,
108
+ ) -> bool:
109
+ original_order = self._pending_orders.get(order_id)
110
+ if original_order is None:
111
+ return False
112
+
113
+ event = events.OrderModification(
114
+ ts_event=self._current_ts,
115
+ system_order_id=order_id,
116
+ symbol=original_order.symbol,
117
+ quantity=quantity,
118
+ limit_price=limit_price,
119
+ stop_price=stop_price,
120
+ )
121
+
122
+ modified_order = models.OrderRecord(
123
+ order_id=order_id,
124
+ symbol=original_order.symbol,
125
+ order_type=original_order.order_type,
126
+ side=original_order.side,
127
+ quantity=quantity if quantity is not None else original_order.quantity,
128
+ limit_price=(
129
+ limit_price if limit_price is not None else original_order.limit_price
130
+ ),
131
+ stop_price=(
132
+ stop_price if stop_price is not None else original_order.stop_price
133
+ ),
134
+ filled_quantity=original_order.filled_quantity,
135
+ )
136
+
137
+ self._submitted_modifications[order_id] = modified_order
138
+ self._publish(event)
139
+ return True
140
+
141
+ def submit_cancellation(self, order_id: uuid.UUID) -> bool:
142
+ original_order = self._pending_orders.get(order_id)
143
+ if original_order is None:
144
+ return False
145
+
146
+ event = events.OrderCancellation(
147
+ ts_event=self._current_ts,
148
+ system_order_id=order_id,
149
+ symbol=original_order.symbol,
150
+ )
151
+
152
+ self._submitted_cancellations[order_id] = original_order
153
+ self._publish(event)
154
+ return True
155
+
156
+ def _on_event(self, event: events.EventBase) -> None:
157
+ match event:
158
+ case events.BarReceived() as bar_event:
159
+ self._on_bar_received(bar_event)
160
+ case events.OrderSubmissionAccepted() as accepted:
161
+ self._on_order_submission_accepted(accepted)
162
+ case events.OrderModificationAccepted() as accepted:
163
+ self._on_order_modification_accepted(accepted)
164
+ case events.OrderCancellationAccepted() as accepted:
165
+ self._on_order_cancellation_accepted(accepted)
166
+ case events.OrderSubmissionRejected() as rejected:
167
+ self._on_order_submission_rejected(rejected)
168
+ case events.OrderModificationRejected() as rejected:
169
+ self._on_order_modification_rejected(rejected)
170
+ case events.OrderCancellationRejected() as rejected:
171
+ self._on_order_cancellation_rejected(rejected)
172
+ case events.OrderFilled() as filled:
173
+ self._on_order_filled(filled)
174
+ case events.OrderExpired() as expired:
175
+ self._on_order_expired(expired)
176
+ case _:
177
+ return
178
+
179
+ def _on_bar_received(self, event: events.BarReceived) -> None:
180
+ if event.symbol not in self.symbols:
181
+ return
182
+ if event.bar_period != self.bar_period:
183
+ return
184
+
185
+ self._current_symbol = event.symbol
186
+ self._current_ts = event.ts_event
187
+
188
+ for ind in self._indicators:
189
+ ind.update(event)
190
+
191
+ self._emit_processed_bar(event)
192
+ self.on_bar(event)
193
+
194
+ def _emit_processed_bar(self, event: events.BarReceived) -> None:
195
+ ohlcv_names = {"OPEN", "HIGH", "LOW", "CLOSE", "VOLUME"}
196
+
197
+ indicator_values = {
198
+ f"{ind.plot_at:02d}_{ind.name}": ind.latest
199
+ for ind in self._indicators
200
+ if ind.name not in ohlcv_names
201
+ }
202
+
203
+ processed_bar = events.BarProcessed(
204
+ ts_event=event.ts_event,
205
+ symbol=event.symbol,
206
+ bar_period=event.bar_period,
207
+ open=event.open,
208
+ high=event.high,
209
+ low=event.low,
210
+ close=event.close,
211
+ volume=event.volume,
212
+ indicators=indicator_values,
213
+ )
214
+
215
+ self._publish(processed_bar)
216
+
217
+ def _on_order_submission_accepted(
218
+ self, event: events.OrderSubmissionAccepted
219
+ ) -> None:
220
+ order = self._submitted_orders.pop(event.associated_order_id, None)
221
+ if order is not None:
222
+ self._pending_orders[event.associated_order_id] = order
223
+
224
+ def _on_order_modification_accepted(
225
+ self, event: events.OrderModificationAccepted
226
+ ) -> None:
227
+ modified_order = self._submitted_modifications.pop(
228
+ event.associated_order_id, None
229
+ )
230
+ if modified_order is not None:
231
+ self._pending_orders[event.associated_order_id] = modified_order
232
+
233
+ def _on_order_cancellation_accepted(
234
+ self, event: events.OrderCancellationAccepted
235
+ ) -> None:
236
+ self._submitted_cancellations.pop(event.associated_order_id, None)
237
+ self._pending_orders.pop(event.associated_order_id, None)
238
+
239
+ def _on_order_submission_rejected(
240
+ self, event: events.OrderSubmissionRejected
241
+ ) -> None:
242
+ self._submitted_orders.pop(event.associated_order_id, None)
243
+
244
+ def _on_order_modification_rejected(
245
+ self, event: events.OrderModificationRejected
246
+ ) -> None:
247
+ self._submitted_modifications.pop(event.associated_order_id, None)
248
+
249
+ def _on_order_cancellation_rejected(
250
+ self, event: events.OrderCancellationRejected
251
+ ) -> None:
252
+ self._submitted_cancellations.pop(event.associated_order_id, None)
253
+
254
+ def _on_order_filled(self, event: events.OrderFilled) -> None:
255
+ # Track partial fills: only remove order when fully filled
256
+ order = self._pending_orders.get(event.associated_order_id)
257
+ if order:
258
+ order.filled_quantity += event.quantity_filled
259
+ if order.filled_quantity >= order.quantity:
260
+ self._pending_orders.pop(event.associated_order_id)
261
+
262
+ fill = models.FillRecord(
263
+ fill_id=event.fill_id,
264
+ order_id=event.associated_order_id,
265
+ symbol=event.symbol,
266
+ side=event.side,
267
+ quantity=event.quantity_filled,
268
+ price=event.fill_price,
269
+ commission=event.commission,
270
+ ts_event=event.ts_event,
271
+ )
272
+
273
+ self._fills.setdefault(event.symbol, []).append(fill)
274
+ self._update_position(event)
275
+
276
+ def _update_position(self, event: events.OrderFilled) -> None:
277
+ symbol = event.symbol
278
+ fill_qty = event.quantity_filled
279
+ fill_price = event.fill_price
280
+
281
+ signed_qty = 0.0
282
+ match event.side:
283
+ case models.OrderSide.BUY:
284
+ signed_qty = fill_qty
285
+ case models.OrderSide.SELL:
286
+ signed_qty = -fill_qty
287
+
288
+ old_pos = self._positions.get(symbol, 0.0)
289
+ old_avg = self._avg_prices.get(symbol, 0.0)
290
+ new_pos = old_pos + signed_qty
291
+
292
+ if new_pos == 0.0:
293
+ new_avg = 0.0
294
+ elif old_pos == 0.0:
295
+ new_avg = fill_price
296
+ elif (old_pos > 0 and signed_qty > 0) or (old_pos < 0 and signed_qty < 0):
297
+ new_avg = (old_avg * abs(old_pos) + fill_price * abs(signed_qty)) / abs(
298
+ new_pos
299
+ )
300
+ else:
301
+ if abs(new_pos) <= abs(old_pos):
302
+ new_avg = old_avg
303
+ else:
304
+ new_avg = fill_price
305
+
306
+ self._positions[symbol] = new_pos
307
+ self._avg_prices[symbol] = new_avg
308
+
309
+ def _on_order_expired(self, event: events.OrderExpired) -> None:
310
+ self._pending_orders.pop(event.associated_order_id, None)
311
+
312
+ # Override to register indicators. Called at end of __init__.
313
+ def setup(self) -> None:
314
+ pass
315
+
316
+ @abc.abstractmethod
317
+ def on_bar(self, event: events.BarReceived) -> None:
318
+ pass
@@ -0,0 +1,35 @@
1
+ from onesecondtrader.core import events, indicators, models
2
+ from .base import StrategyBase
3
+
4
+
5
+ class SMACrossover(StrategyBase):
6
+ fast_period: int = 20
7
+ slow_period: int = 100
8
+ quantity: float = 1.0
9
+
10
+ def setup(self) -> None:
11
+ self.fast_sma = self.add_indicator(
12
+ indicators.SimpleMovingAverage(period=self.fast_period)
13
+ )
14
+ self.slow_sma = self.add_indicator(
15
+ indicators.SimpleMovingAverage(period=self.slow_period)
16
+ )
17
+
18
+ def on_bar(self, event: events.BarReceived) -> None:
19
+ if (
20
+ self.fast_sma[-2] <= self.slow_sma[-2]
21
+ and self.fast_sma.latest > self.slow_sma.latest
22
+ and self.position <= 0
23
+ ):
24
+ self.submit_order(
25
+ models.OrderType.MARKET, models.OrderSide.BUY, self.quantity
26
+ )
27
+
28
+ if (
29
+ self.fast_sma[-2] >= self.slow_sma[-2]
30
+ and self.fast_sma.latest < self.slow_sma.latest
31
+ and self.position >= 0
32
+ ):
33
+ self.submit_order(
34
+ models.OrderType.MARKET, models.OrderSide.SELL, self.quantity
35
+ )
File without changes
@@ -0,0 +1,5 @@
1
+ __all__ = [
2
+ "init_secmaster",
3
+ ]
4
+
5
+ from onesecondtrader.secmaster.utils import init_secmaster
@@ -0,0 +1,46 @@
1
+ -- Security Master Database Schema
2
+ --
3
+ -- Stores instrument metadata and OHLCV market data. Prices are stored as
4
+ -- fixed-point integers (scale factor $10^9$) to avoid floating-point errors.
5
+ -- Timestamps are nanoseconds since Unix epoch.
6
+
7
+ -- Data providers. Separated from instruments because the same symbol (e.g.,
8
+ -- `ESH5`) may exist across multiple vendors with different `instrument_id`s.
9
+ CREATE TABLE publishers (
10
+ publisher_id INTEGER PRIMARY KEY,
11
+ name TEXT NOT NULL UNIQUE,
12
+ dataset TEXT NOT NULL,
13
+ venue TEXT
14
+ );
15
+
16
+ -- Security/instrument metadata. The UNIQUE constraint on (`publisher_id`, `raw_symbol`)
17
+ -- allows the same symbol from different vendors while preventing duplicates.
18
+ CREATE TABLE instruments (
19
+ instrument_id INTEGER PRIMARY KEY,
20
+ publisher_id INTEGER NOT NULL,
21
+ raw_symbol TEXT NOT NULL,
22
+ instrument_class TEXT NOT NULL DEFAULT 'K',
23
+ exchange TEXT,
24
+ currency TEXT DEFAULT 'USD',
25
+ min_price_increment INTEGER,
26
+ ts_recv INTEGER NOT NULL,
27
+ FOREIGN KEY (publisher_id) REFERENCES publishers(publisher_id),
28
+ UNIQUE(publisher_id, raw_symbol)
29
+ );
30
+
31
+ -- OHLCV bar data. The primary key order (`instrument_id`, `rtype`, `ts_event`) ensures
32
+ -- bars for the same instrument/timeframe are contiguous on disk, making range
33
+ -- queries fast. `WITHOUT ROWID` stores data directly in the primary key B-tree,
34
+ -- eliminating the indirection of a separate rowid lookup.
35
+ CREATE TABLE ohlcv (
36
+ instrument_id INTEGER NOT NULL,
37
+ rtype INTEGER NOT NULL,
38
+ ts_event INTEGER NOT NULL,
39
+ open INTEGER NOT NULL,
40
+ high INTEGER NOT NULL,
41
+ low INTEGER NOT NULL,
42
+ close INTEGER NOT NULL,
43
+ volume INTEGER NOT NULL,
44
+ FOREIGN KEY (instrument_id) REFERENCES instruments(instrument_id),
45
+ PRIMARY KEY (instrument_id, rtype, ts_event)
46
+ ) WITHOUT ROWID;
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+
3
+ import pathlib
4
+ import sqlite3
5
+
6
+
7
+ def init_secmaster(db_path: pathlib.Path) -> None:
8
+ """Initialize a new secmaster database at the specified path.
9
+
10
+ Creates the database file with the schema defined in schema.sql (publishers, instruments,
11
+ and ohlcv tables) but does not populate any data.
12
+
13
+ Args:
14
+ db_path: Path where the database file will be created.
15
+
16
+ Raises:
17
+ FileExistsError: If a database already exists at the path.
18
+ """
19
+ if db_path.exists():
20
+ raise FileExistsError(f"Database already exists: {db_path}")
21
+ db_path.parent.mkdir(parents=True, exist_ok=True)
22
+ schema_path = pathlib.Path(__file__).parent / "schema.sql"
23
+ conn = sqlite3.connect(str(db_path))
24
+ conn.executescript(schema_path.read_text())
25
+ conn.commit()
26
+ conn.close()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onesecondtrader
3
- Version: 0.35.0
3
+ Version: 0.36.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
@@ -0,0 +1,62 @@
1
+ onesecondtrader/__init__.py,sha256=bzV-SaWcDnq7os8pUtsaq8GAsBWjxBDhkFvRs3Z9FJw,1008
2
+ onesecondtrader/brokers/__init__.py,sha256=YofzD0qlrfo_BzL6gwiHb9by7Webp36TQ_1O5EV0uzY,124
3
+ onesecondtrader/brokers/base.py,sha256=b6Xq2gBUdy3RTpnUfpUiNSXwbuq_bRIjXJ-s89Xu7nE,1345
4
+ onesecondtrader/brokers/simulated.py,sha256=pJvZ7b76xAs-NBbOX_v78IJgVrdnuTLCadqj8kYQ5sg,12694
5
+ onesecondtrader/connectors/__init__.py,sha256=TDV1mXCkNVuMS8FQWRts_6FDwBEeNciMqYtZb8HNl2w,120
6
+ onesecondtrader/connectors/brokers/__init__.py,sha256=O67ETIic6yrGDQp_wJSNTsjZ4Tt_3NGO3v4RJf3bm7Q,70
7
+ onesecondtrader/connectors/brokers/simulated.py,sha256=ck0gWdz88KSyEMkiHW2CP0vuLrBELBTz3KveYIwbLuI,12722
8
+ onesecondtrader/connectors/datafeeds/__init__.py,sha256=OzrPQcmdwzI6Fo8BONoWeJQtp0ttQ6TMYL6dUvvery4,113
9
+ onesecondtrader/connectors/datafeeds/base.py,sha256=hpffDlv5Z92OZnL_B3vs_rRmq7uRU4HCf8N6IZkRxmM,482
10
+ onesecondtrader/connectors/datafeeds/simulated.py,sha256=aMLSDu2CVaQcxxeWOcznFrfPgXq3icEB2rRe4KNK0Wg,3011
11
+ onesecondtrader/core/__init__.py,sha256=5T2eAX4I_yo2ku9zywhFvl628kPTINxoLY92u7x_gy0,324
12
+ onesecondtrader/core/brokers/__init__.py,sha256=mC-nNPdaT17oy-rjluwNvbKzxi5q8xxZ4mAkU7aJU0Y,55
13
+ onesecondtrader/core/brokers/base.py,sha256=n82DHGvqkP9c4ATW8qT9yosPRoRQGUrs1oveGASdhlY,1350
14
+ onesecondtrader/core/events/__init__.py,sha256=IOlFRdiOXz93SpvkpKL8wr1954d_8olKSB1n9mlTL3Y,898
15
+ onesecondtrader/core/events/bases.py,sha256=g-ykq2jgcitIAueRurUlqAq0jINQwuhSWi_khAniPHw,662
16
+ onesecondtrader/core/events/market.py,sha256=UY04TH6G-98NgYPEvBQSY92_ddeiT4yNwaUXnHdongQ,514
17
+ onesecondtrader/core/events/requests.py,sha256=7cnt7TiuE7yl9ezFruIixY0v5A-mzZDWdoTBkAcVff0,836
18
+ onesecondtrader/core/events/responses.py,sha256=biHIFa6usnsgSEX9bh2zOs1zB00I7HVSS01Dh_pZISE,1441
19
+ onesecondtrader/core/indicators/__init__.py,sha256=hRg3FCP1FT7LYOLzztybWn48gTR5QvewzzdELPYbdoY,239
20
+ onesecondtrader/core/indicators/averages.py,sha256=sCAIJrOYhtkwO5MkS2vx-4CfzHIVLJZpwYDzwv1GZ7Y,1905
21
+ onesecondtrader/core/indicators/bar.py,sha256=9NUckrLO1AhyO3uTJlNCL2_Pqge58x5S_TcSz4qrk-c,1120
22
+ onesecondtrader/core/indicators/base.py,sha256=_2pJ7PS0MRUz85UT0YpvzJ5V6ce60koT8MbjoerZ9eM,1894
23
+ onesecondtrader/core/messaging/__init__.py,sha256=vMRDabHBgse_vZRTRFtnU8M8v2sY_o4pHjGzgu3hp3E,115
24
+ onesecondtrader/core/messaging/eventbus.py,sha256=SaXLRoqz9tWBBlyEo0ry1HHr_8azj2U2dEaQEnr3PNo,1581
25
+ onesecondtrader/core/messaging/subscriber.py,sha256=Sp77pB6bGyW57FlV0rdzAWy1Jv_nHA77YEtN64spZjs,2111
26
+ onesecondtrader/core/models/__init__.py,sha256=7amHCQ6BAhHKps0ke63E-zh8IJNmkdDogZq-PfBukMs,249
27
+ onesecondtrader/core/models/data.py,sha256=fBmddVl6EXYC5u2UnvQ59DXAXeZeIb48KP1ZdeTL52A,322
28
+ onesecondtrader/core/models/orders.py,sha256=y6Ar-6fMqaOd_hRnRGvfWUF0Z13H_2hfTOW3ROOk0A8,254
29
+ onesecondtrader/core/models/records.py,sha256=vdCWBtoDQs5R4iB_8_3fXkxWEvoCxOssk9XBnS4l7Vk,599
30
+ onesecondtrader/core/strategies/__init__.py,sha256=Nq1n6HCdZ-GKkpn4WAlKxconPnOmeVKo0nhTk0J1ybA,121
31
+ onesecondtrader/core/strategies/base.py,sha256=wZMjPu4sSMclvoyMptIZKllaqFkRrA06CZ5EG7uQ-Uo,11211
32
+ onesecondtrader/core/strategies/examples.py,sha256=j4K092_qt0bcvajp-i4ugrGqzbaFebYX6rBbtZawtvE,1124
33
+ onesecondtrader/dashboard/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ onesecondtrader/datafeeds/__init__.py,sha256=zSj1cQhBS-Z5271ICsmGc_zq-1fOd8yLQ7c4F0oJIVk,124
35
+ onesecondtrader/datafeeds/base.py,sha256=bSIHBlZ8kbJ4rTZrUMiMgl8_j0Kqe6Eh2hNX5E3DhHU,477
36
+ onesecondtrader/datafeeds/simulated.py,sha256=mbnEh0jjgZWRDhRLIASMbUpV1ybQktBA8opTv6nj33s,3006
37
+ onesecondtrader/events/__init__.py,sha256=IOlFRdiOXz93SpvkpKL8wr1954d_8olKSB1n9mlTL3Y,898
38
+ onesecondtrader/events/bases.py,sha256=g-ykq2jgcitIAueRurUlqAq0jINQwuhSWi_khAniPHw,662
39
+ onesecondtrader/events/market.py,sha256=IfHuIGfp_IUiw-dFay4c4RYmkoNzshxbhuWTglBqfN0,509
40
+ onesecondtrader/events/requests.py,sha256=2KXwSckiar9-fy8wkN3vcSIeOkeBfeo_XhUhrNKEd2Q,831
41
+ onesecondtrader/events/responses.py,sha256=w_BH1nkkPyxQjh30EXEVFcUGDoMprFc2PuAaqpVrQ8A,1436
42
+ onesecondtrader/indicators/__init__.py,sha256=hRg3FCP1FT7LYOLzztybWn48gTR5QvewzzdELPYbdoY,239
43
+ onesecondtrader/indicators/averages.py,sha256=DpRRdY5G5ze3jwNOV19PPjV6slA0IEeOOla67yChi2Y,1900
44
+ onesecondtrader/indicators/bar.py,sha256=0H07mKNiUx5cE1fQvx1oPVY0R_MXcmAAgsLek175vTk,1115
45
+ onesecondtrader/indicators/base.py,sha256=64HJD8JWBnUdR7PLd02N3hbNrRfKMjWHEKGeSyMRms8,1889
46
+ onesecondtrader/messaging/__init__.py,sha256=vMRDabHBgse_vZRTRFtnU8M8v2sY_o4pHjGzgu3hp3E,115
47
+ onesecondtrader/messaging/eventbus.py,sha256=Y8VbDZlEz8Q6KcCkfXRKsVIixsctBMRW1a5ANw297Ls,1576
48
+ onesecondtrader/messaging/subscriber.py,sha256=ImpFmu5IstLXLoKVMaebmLp5MXN6225vHLdTL1ZOPvw,2106
49
+ onesecondtrader/models/__init__.py,sha256=7amHCQ6BAhHKps0ke63E-zh8IJNmkdDogZq-PfBukMs,249
50
+ onesecondtrader/models/data.py,sha256=fBmddVl6EXYC5u2UnvQ59DXAXeZeIb48KP1ZdeTL52A,322
51
+ onesecondtrader/models/orders.py,sha256=y6Ar-6fMqaOd_hRnRGvfWUF0Z13H_2hfTOW3ROOk0A8,254
52
+ onesecondtrader/models/records.py,sha256=vdCWBtoDQs5R4iB_8_3fXkxWEvoCxOssk9XBnS4l7Vk,599
53
+ onesecondtrader/secmaster/__init__.py,sha256=HUpfkdWpz6t5YO0QgiEyM5MU32RQNGv9lfsvdE8HHZQ,96
54
+ onesecondtrader/secmaster/schema.sql,sha256=NHHBb86cwZYtSZbOWlBgXd8dQsi5B26KZC-OR5sytAU,1802
55
+ onesecondtrader/secmaster/utils.py,sha256=82DUBbzdGbNmQHewhC2qmcbbarnrr4g9PhEsucxbT4Y,831
56
+ onesecondtrader/strategies/__init__.py,sha256=5TlEckz3RnwZTs1Isj0wJ_9Og5R9MMXBL90Vu9b45io,126
57
+ onesecondtrader/strategies/base.py,sha256=kIi6by4Y8YuB9gPMPMr2Unm5_i9SGAANyiW2UaHiRO0,11206
58
+ onesecondtrader/strategies/sma_crossover.py,sha256=s2u_uL_D5CrZTACiAbojnrLrLf4jqIPdfOCiNDEIsDA,1119
59
+ onesecondtrader-0.36.0.dist-info/METADATA,sha256=BaNIEbmpAsU8S94iLlVRUiabpgeTIJ8p6BwBcyTQ78s,9682
60
+ onesecondtrader-0.36.0.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
61
+ onesecondtrader-0.36.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
62
+ onesecondtrader-0.36.0.dist-info/RECORD,,
@@ -1,5 +0,0 @@
1
- __all__ = [
2
- "CSVBookkeeper",
3
- ]
4
-
5
- from .csvbookkeeper import CSVBookkeeper