onesecondtrader 0.41.0__py3-none-any.whl → 0.44.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 (55) hide show
  1. onesecondtrader/__init__.py +0 -58
  2. onesecondtrader/models/__init__.py +11 -0
  3. onesecondtrader/models/bar_fields.py +23 -0
  4. onesecondtrader/models/bar_period.py +21 -0
  5. onesecondtrader/models/order_types.py +21 -0
  6. onesecondtrader/models/trade_sides.py +20 -0
  7. {onesecondtrader-0.41.0.dist-info → onesecondtrader-0.44.0.dist-info}/METADATA +2 -2
  8. onesecondtrader-0.44.0.dist-info/RECORD +10 -0
  9. onesecondtrader/connectors/__init__.py +0 -3
  10. onesecondtrader/connectors/brokers/__init__.py +0 -4
  11. onesecondtrader/connectors/brokers/ib.py +0 -418
  12. onesecondtrader/connectors/brokers/simulated.py +0 -349
  13. onesecondtrader/connectors/datafeeds/__init__.py +0 -4
  14. onesecondtrader/connectors/datafeeds/ib.py +0 -286
  15. onesecondtrader/connectors/datafeeds/simulated.py +0 -167
  16. onesecondtrader/connectors/gateways/__init__.py +0 -3
  17. onesecondtrader/connectors/gateways/ib.py +0 -314
  18. onesecondtrader/core/__init__.py +0 -7
  19. onesecondtrader/core/brokers/__init__.py +0 -3
  20. onesecondtrader/core/brokers/base.py +0 -46
  21. onesecondtrader/core/datafeeds/__init__.py +0 -3
  22. onesecondtrader/core/datafeeds/base.py +0 -32
  23. onesecondtrader/core/events/__init__.py +0 -33
  24. onesecondtrader/core/events/bases.py +0 -29
  25. onesecondtrader/core/events/market.py +0 -22
  26. onesecondtrader/core/events/requests.py +0 -31
  27. onesecondtrader/core/events/responses.py +0 -54
  28. onesecondtrader/core/indicators/__init__.py +0 -13
  29. onesecondtrader/core/indicators/averages.py +0 -56
  30. onesecondtrader/core/indicators/bar.py +0 -47
  31. onesecondtrader/core/indicators/base.py +0 -60
  32. onesecondtrader/core/messaging/__init__.py +0 -7
  33. onesecondtrader/core/messaging/eventbus.py +0 -47
  34. onesecondtrader/core/messaging/subscriber.py +0 -69
  35. onesecondtrader/core/models/__init__.py +0 -14
  36. onesecondtrader/core/models/data.py +0 -18
  37. onesecondtrader/core/models/orders.py +0 -15
  38. onesecondtrader/core/models/params.py +0 -21
  39. onesecondtrader/core/models/records.py +0 -32
  40. onesecondtrader/core/strategies/__init__.py +0 -7
  41. onesecondtrader/core/strategies/base.py +0 -324
  42. onesecondtrader/core/strategies/examples.py +0 -43
  43. onesecondtrader/dashboard/__init__.py +0 -3
  44. onesecondtrader/dashboard/app.py +0 -1677
  45. onesecondtrader/dashboard/registry.py +0 -100
  46. onesecondtrader/orchestrator/__init__.py +0 -7
  47. onesecondtrader/orchestrator/orchestrator.py +0 -105
  48. onesecondtrader/orchestrator/recorder.py +0 -196
  49. onesecondtrader/orchestrator/schema.sql +0 -208
  50. onesecondtrader/secmaster/__init__.py +0 -6
  51. onesecondtrader/secmaster/schema.sql +0 -740
  52. onesecondtrader/secmaster/utils.py +0 -737
  53. onesecondtrader-0.41.0.dist-info/RECORD +0 -49
  54. {onesecondtrader-0.41.0.dist-info → onesecondtrader-0.44.0.dist-info}/WHEEL +0 -0
  55. {onesecondtrader-0.41.0.dist-info → onesecondtrader-0.44.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,167 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import os
4
- import sqlite3
5
- import threading
6
-
7
- import pandas as pd
8
-
9
- from onesecondtrader.core import events, messaging, models
10
- from onesecondtrader.core.datafeeds import DatafeedBase
11
-
12
- _RTYPE_MAP = {
13
- models.BarPeriod.SECOND: 32,
14
- models.BarPeriod.MINUTE: 33,
15
- models.BarPeriod.HOUR: 34,
16
- models.BarPeriod.DAY: 35,
17
- }
18
-
19
- _PRICE_SCALE = 1e9
20
-
21
-
22
- class SimulatedDatafeed(DatafeedBase):
23
- db_path: str = ""
24
- start_ts: int | None = None
25
- end_ts: int | None = None
26
-
27
- def __init__(self, event_bus: messaging.EventBus) -> None:
28
- super().__init__(event_bus)
29
- self._db_path = self.db_path or os.environ.get(
30
- "SECMASTER_DB_PATH", "secmaster.db"
31
- )
32
- self._connected = False
33
- self._subscriptions: set[tuple[str, models.BarPeriod]] = set()
34
- self._connection: sqlite3.Connection | None = None
35
- self._thread: threading.Thread | None = None
36
- self._stop_event = threading.Event()
37
-
38
- def connect(self) -> None:
39
- if self._connected:
40
- return
41
- self._connection = sqlite3.connect(self._db_path, check_same_thread=False)
42
- self._connected = True
43
-
44
- def disconnect(self) -> None:
45
- if not self._connected:
46
- return
47
- self._stop_event.set()
48
- if self._thread and self._thread.is_alive():
49
- self._thread.join()
50
- if self._connection:
51
- self._connection.close()
52
- self._connection = None
53
- self._connected = False
54
-
55
- def subscribe(self, symbol: str, bar_period: models.BarPeriod) -> None:
56
- self._subscriptions.add((symbol, bar_period))
57
-
58
- def unsubscribe(self, symbol: str, bar_period: models.BarPeriod) -> None:
59
- self._subscriptions.discard((symbol, bar_period))
60
-
61
- def wait_until_complete(self) -> None:
62
- if not self._subscriptions:
63
- return
64
- if self._thread is None or not self._thread.is_alive():
65
- self._stop_event.clear()
66
- self._thread = threading.Thread(
67
- target=self._stream,
68
- name=self.__class__.__name__,
69
- daemon=False,
70
- )
71
- self._thread.start()
72
- self._thread.join()
73
-
74
- def _stream(self) -> None:
75
- if not self._connection:
76
- return
77
-
78
- subscriptions = list(self._subscriptions)
79
- if not subscriptions:
80
- return
81
-
82
- symbol_rtype_pairs = [
83
- (symbol, _RTYPE_MAP[bar_period]) for symbol, bar_period in subscriptions
84
- ]
85
- rtype_by_symbol = {symbol: rtype for symbol, rtype in symbol_rtype_pairs}
86
- bar_period_by_symbol = {symbol: bp for symbol, bp in subscriptions}
87
- symbols = list(rtype_by_symbol.keys())
88
-
89
- cursor = self._connection.cursor()
90
-
91
- instrument_ids = self._resolve_instrument_ids(cursor, symbols)
92
- if not instrument_ids:
93
- return
94
-
95
- instrument_to_symbol = {v: k for k, v in instrument_ids.items()}
96
- id_list = list(instrument_ids.values())
97
- rtype_list = list(set(rtype_by_symbol.values()))
98
-
99
- placeholders_ids = ",".join("?" * len(id_list))
100
- placeholders_rtypes = ",".join("?" * len(rtype_list))
101
-
102
- date_filter = ""
103
- params = id_list + rtype_list
104
- if self.start_ts is not None:
105
- date_filter += " AND ts_event >= ?"
106
- params.append(self.start_ts)
107
- if self.end_ts is not None:
108
- date_filter += " AND ts_event <= ?"
109
- params.append(self.end_ts)
110
-
111
- query = f"""
112
- SELECT instrument_id, rtype, ts_event, open, high, low, close, volume
113
- FROM ohlcv
114
- WHERE instrument_id IN ({placeholders_ids})
115
- AND rtype IN ({placeholders_rtypes})
116
- {date_filter}
117
- ORDER BY ts_event
118
- """
119
-
120
- cursor.execute(query, params)
121
-
122
- while True:
123
- if self._stop_event.is_set():
124
- return
125
-
126
- row = cursor.fetchone()
127
- if row is None:
128
- break
129
-
130
- instrument_id, rtype, ts_event, open_, high, low, close, volume = row
131
- symbol = instrument_to_symbol.get(instrument_id)
132
- if symbol is None:
133
- continue
134
-
135
- expected_rtype = rtype_by_symbol.get(symbol)
136
- if rtype != expected_rtype:
137
- continue
138
-
139
- bar_period = bar_period_by_symbol[symbol]
140
-
141
- self._publish(
142
- events.BarReceived(
143
- ts_event=pd.Timestamp(ts_event, unit="ns", tz="UTC"),
144
- symbol=symbol,
145
- bar_period=bar_period,
146
- open=open_ / _PRICE_SCALE,
147
- high=high / _PRICE_SCALE,
148
- low=low / _PRICE_SCALE,
149
- close=close / _PRICE_SCALE,
150
- volume=volume,
151
- )
152
- )
153
- self._event_bus.wait_until_system_idle()
154
-
155
- def _resolve_instrument_ids(
156
- self, cursor: sqlite3.Cursor, symbols: list[str]
157
- ) -> dict[str, int]:
158
- placeholders = ",".join("?" * len(symbols))
159
- query = f"""
160
- SELECT symbol, instrument_id
161
- FROM symbology
162
- WHERE symbol IN ({placeholders})
163
- GROUP BY symbol
164
- HAVING start_date = MAX(start_date)
165
- """
166
- cursor.execute(query, symbols)
167
- return {row[0]: row[1] for row in cursor.fetchall()}
@@ -1,3 +0,0 @@
1
- __all__ = ["IBGateway", "make_contract"]
2
-
3
- from .ib import IBGateway, make_contract
@@ -1,314 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- import logging
5
- import os
6
- import sqlite3
7
- import threading
8
- import time
9
-
10
- from ib_async import Contract, Forex, Future, IB, Option, Stock
11
-
12
- _logger = logging.getLogger(__name__)
13
-
14
- _INSTRUMENT_CLASS_MAP = {
15
- "K": "STK",
16
- "F": "FUT",
17
- "C": "OPT",
18
- "P": "OPT",
19
- "X": "CASH",
20
- }
21
-
22
-
23
- def make_contract(
24
- symbol: str, db_connection: sqlite3.Connection | None = None
25
- ) -> Contract:
26
- """
27
- Resolve a symbol string to an IB Contract.
28
-
29
- Resolution priority:
30
- 1. Explicit format with colons (e.g., ``"AAPL:STK:USD:SMART"``)
31
- 2. Secmaster database lookup (if db_connection provided)
32
- 3. Default: US stock on SMART routing
33
-
34
- Args:
35
- symbol: Symbol string, either simple (``"AAPL"``) or qualified
36
- (``"AAPL:STK:USD:SMART"``).
37
- db_connection: Optional SQLite connection to secmaster database.
38
-
39
- Returns:
40
- An ib_async Contract object.
41
- """
42
- if ":" in symbol:
43
- return _parse_qualified_symbol(symbol)
44
-
45
- if db_connection:
46
- row = _query_instrument(symbol, db_connection)
47
- if row:
48
- return _row_to_contract(row)
49
-
50
- return Stock(symbol, "SMART", "USD")
51
-
52
-
53
- def _parse_qualified_symbol(symbol: str) -> Contract:
54
- parts = symbol.split(":")
55
- sec_type = parts[1].upper() if len(parts) > 1 else "STK"
56
- currency = parts[2] if len(parts) > 2 else "USD"
57
- exchange = parts[3] if len(parts) > 3 else "SMART"
58
-
59
- if sec_type == "STK":
60
- return Stock(parts[0], exchange, currency)
61
- elif sec_type == "CASH":
62
- return Forex(pair=f"{parts[0]}{currency}")
63
- elif sec_type == "FUT":
64
- expiry = parts[4] if len(parts) > 4 else ""
65
- return Future(parts[0], expiry, exchange, currency)
66
- elif sec_type == "OPT":
67
- expiry = parts[4] if len(parts) > 4 else ""
68
- strike = float(parts[5]) if len(parts) > 5 else 0.0
69
- right = parts[6] if len(parts) > 6 else "C"
70
- return Option(parts[0], expiry, strike, right, exchange, currency)
71
- else:
72
- return Stock(parts[0], exchange, currency)
73
-
74
-
75
- def _query_instrument(symbol: str, db_connection: sqlite3.Connection) -> tuple | None:
76
- cursor = db_connection.cursor()
77
- cursor.execute(
78
- """
79
- SELECT raw_symbol, instrument_class, currency, exchange,
80
- expiration, strike_price
81
- FROM instruments
82
- WHERE raw_symbol = ?
83
- ORDER BY expiration DESC
84
- LIMIT 1
85
- """,
86
- (symbol,),
87
- )
88
- return cursor.fetchone()
89
-
90
-
91
- def _row_to_contract(row: tuple) -> Contract:
92
- raw_symbol, instrument_class, currency, exchange, expiration, strike = row
93
- currency = currency or "USD"
94
- exchange = exchange or "SMART"
95
- sec_type = _INSTRUMENT_CLASS_MAP.get(instrument_class, "STK")
96
-
97
- if sec_type == "STK":
98
- return Stock(raw_symbol, exchange, currency)
99
- elif sec_type == "CASH":
100
- return Forex(pair=f"{raw_symbol}{currency}")
101
- elif sec_type == "FUT":
102
- expiry = str(expiration) if expiration else ""
103
- return Future(raw_symbol, expiry, exchange, currency)
104
- elif sec_type == "OPT":
105
- expiry = str(expiration) if expiration else ""
106
- strike_val = float(strike) / 1e9 if strike else 0.0
107
- right = "C" if instrument_class == "C" else "P"
108
- return Option(raw_symbol, expiry, strike_val, right, exchange, currency)
109
- else:
110
- return Stock(raw_symbol, exchange, currency)
111
-
112
-
113
- class IBGateway:
114
- """
115
- Shared gateway for IB connectivity with automatic reconnection.
116
-
117
- The gateway manages a single IB connection shared by multiple components
118
- (datafeed, broker). It handles:
119
-
120
- - Reference counting for connect/disconnect
121
- - Automatic reconnection on disconnect
122
- - Running an asyncio event loop in a background thread
123
-
124
- Reconnection Behavior:
125
- When the connection is lost, the gateway will automatically attempt
126
- to reconnect after a configurable delay. Components that registered
127
- reconnect callbacks will be notified after successful reconnection
128
- so they can restore their subscriptions.
129
-
130
- Environment Variables:
131
- - ``IB_HOST``: Host address (default: 127.0.0.1)
132
- - ``IB_PORT``: Port number (default: 4001 for gateway, 7497 for TWS)
133
- - ``IB_CLIENT_ID``: Client ID (default: 1)
134
- - ``IB_RECONNECT_DELAY``: Seconds to wait before reconnecting (default: 5)
135
- - ``IB_MAX_RECONNECT_ATTEMPTS``: Max reconnect attempts, 0=infinite (default: 0)
136
- """
137
-
138
- def __init__(self) -> None:
139
- self._host = os.environ.get("IB_HOST", "127.0.0.1")
140
- self._port = int(os.environ.get("IB_PORT", "4001"))
141
- self._client_id = int(os.environ.get("IB_CLIENT_ID", "1"))
142
- self._reconnect_delay = float(os.environ.get("IB_RECONNECT_DELAY", "5"))
143
- self._max_reconnect_attempts = int(
144
- os.environ.get("IB_MAX_RECONNECT_ATTEMPTS", "0")
145
- )
146
- self._ib = IB()
147
- self._ref_count = 0
148
- self._lock = threading.Lock()
149
- self._loop: asyncio.AbstractEventLoop | None = None
150
- self._loop_thread: threading.Thread | None = None
151
- self._reconnect_callbacks: list = []
152
- self._disconnect_callbacks: list = []
153
- self._reconnecting = False
154
- self._should_reconnect = True
155
- self._reconnect_attempts = 0
156
-
157
- def _run_loop(self) -> None:
158
- self._loop = asyncio.new_event_loop()
159
- asyncio.set_event_loop(self._loop)
160
- self._loop.run_forever()
161
-
162
- def run_coro(self, coro):
163
- if self._loop is None:
164
- raise RuntimeError("Gateway not connected")
165
- future = asyncio.run_coroutine_threadsafe(coro, self._loop)
166
- return future.result()
167
-
168
- def acquire(self) -> None:
169
- with self._lock:
170
- if self._ref_count == 0:
171
- _logger.info("Connecting to IB at %s:%d", self._host, self._port)
172
- self._should_reconnect = True
173
- self._reconnect_attempts = 0
174
- self._loop_thread = threading.Thread(
175
- target=self._run_loop, daemon=True, name="IBGatewayLoop"
176
- )
177
- self._loop_thread.start()
178
- while self._loop is None:
179
- time.sleep(0.01)
180
- self._ib.disconnectedEvent += self._on_disconnected
181
- self.run_coro(
182
- self._ib.connectAsync(
183
- self._host, self._port, clientId=self._client_id
184
- )
185
- )
186
- _logger.info("Connected to IB")
187
- self._ref_count += 1
188
-
189
- def release(self) -> None:
190
- with self._lock:
191
- self._ref_count -= 1
192
- if self._ref_count == 0:
193
- _logger.info("Disconnecting from IB")
194
- self._should_reconnect = False
195
- self._ib.disconnectedEvent -= self._on_disconnected
196
- self._ib.disconnect()
197
- if self._loop:
198
- self._loop.call_soon_threadsafe(self._loop.stop)
199
- if self._loop_thread:
200
- self._loop_thread.join()
201
- self._loop = None
202
- self._loop_thread = None
203
- self._reconnect_callbacks.clear()
204
- self._disconnect_callbacks.clear()
205
- _logger.info("Disconnected from IB")
206
-
207
- def register_reconnect_callback(self, callback) -> None:
208
- """
209
- Register a callback to be called after successful reconnection.
210
-
211
- The callback should restore any subscriptions or state that was lost
212
- during the disconnect.
213
- """
214
- if callback not in self._reconnect_callbacks:
215
- self._reconnect_callbacks.append(callback)
216
-
217
- def unregister_reconnect_callback(self, callback) -> None:
218
- if callback in self._reconnect_callbacks:
219
- self._reconnect_callbacks.remove(callback)
220
-
221
- def register_disconnect_callback(self, callback) -> None:
222
- """
223
- Register a callback to be called when disconnection is detected.
224
-
225
- The callback can be used to pause operations or notify the system.
226
- """
227
- if callback not in self._disconnect_callbacks:
228
- self._disconnect_callbacks.append(callback)
229
-
230
- def unregister_disconnect_callback(self, callback) -> None:
231
- if callback in self._disconnect_callbacks:
232
- self._disconnect_callbacks.remove(callback)
233
-
234
- def _on_disconnected(self) -> None:
235
- if not self._should_reconnect or self._reconnecting:
236
- return
237
-
238
- _logger.warning("IB connection lost")
239
- for callback in self._disconnect_callbacks:
240
- try:
241
- callback()
242
- except Exception:
243
- _logger.exception("Error in disconnect callback")
244
-
245
- if self._loop:
246
- asyncio.run_coroutine_threadsafe(self._reconnect_async(), self._loop)
247
-
248
- async def _reconnect_async(self) -> None:
249
- if self._reconnecting:
250
- return
251
- self._reconnecting = True
252
-
253
- while self._should_reconnect:
254
- self._reconnect_attempts += 1
255
- if (
256
- self._max_reconnect_attempts > 0
257
- and self._reconnect_attempts > self._max_reconnect_attempts
258
- ):
259
- _logger.error(
260
- "Max reconnect attempts (%d) reached, giving up",
261
- self._max_reconnect_attempts,
262
- )
263
- self._reconnecting = False
264
- return
265
-
266
- _logger.info(
267
- "Reconnecting to IB (attempt %d) in %.1fs",
268
- self._reconnect_attempts,
269
- self._reconnect_delay,
270
- )
271
- await asyncio.sleep(self._reconnect_delay)
272
-
273
- if not self._should_reconnect:
274
- break
275
-
276
- try:
277
- await self._ib.connectAsync(
278
- self._host, self._port, clientId=self._client_id
279
- )
280
- _logger.info("Reconnected to IB")
281
- self._reconnect_attempts = 0
282
- self._reconnecting = False
283
-
284
- for callback in self._reconnect_callbacks:
285
- try:
286
- callback()
287
- except Exception:
288
- _logger.exception("Error in reconnect callback")
289
- return
290
- except Exception as e:
291
- _logger.warning("Reconnect failed: %s", e)
292
- continue
293
-
294
- self._reconnecting = False
295
-
296
- @property
297
- def ib(self) -> IB:
298
- return self._ib
299
-
300
- @property
301
- def is_connected(self) -> bool:
302
- return self._ib.isConnected()
303
-
304
-
305
- _gateway: IBGateway | None = None
306
- _gateway_lock = threading.Lock()
307
-
308
-
309
- def _get_gateway() -> IBGateway:
310
- global _gateway
311
- with _gateway_lock:
312
- if _gateway is None:
313
- _gateway = IBGateway()
314
- return _gateway
@@ -1,7 +0,0 @@
1
- from onesecondtrader.core import brokers as brokers
2
- from onesecondtrader.core import datafeeds as datafeeds
3
- from onesecondtrader.core import events as events
4
- from onesecondtrader.core import indicators as indicators
5
- from onesecondtrader.core import messaging as messaging
6
- from onesecondtrader.core import models as models
7
- from onesecondtrader.core import strategies as strategies
@@ -1,3 +0,0 @@
1
- __all__ = ["BrokerBase"]
2
-
3
- from .base import BrokerBase
@@ -1,46 +0,0 @@
1
- import abc
2
-
3
- from onesecondtrader.core import events, messaging
4
-
5
-
6
- class BrokerBase(messaging.Subscriber):
7
- def __init__(self, event_bus: messaging.EventBus) -> None:
8
- super().__init__(event_bus)
9
- self._subscribe(
10
- events.requests.OrderSubmission,
11
- events.requests.OrderCancellation,
12
- events.requests.OrderModification,
13
- )
14
-
15
- @abc.abstractmethod
16
- def connect(self) -> None:
17
- pass
18
-
19
- def disconnect(self) -> None:
20
- self.shutdown()
21
-
22
- def _on_event(self, event: events.bases.EventBase) -> None:
23
- match event:
24
- case events.requests.OrderSubmission() as submit_order:
25
- self._on_submit_order(submit_order)
26
- case events.requests.OrderCancellation() as cancel_order:
27
- self._on_cancel_order(cancel_order)
28
- case events.requests.OrderModification() as modify_order:
29
- self._on_modify_order(modify_order)
30
- case _:
31
- return
32
-
33
- @abc.abstractmethod
34
- def _on_submit_order(self, event: events.requests.OrderSubmission) -> None:
35
- pass
36
-
37
- @abc.abstractmethod
38
- def _on_cancel_order(self, event: events.requests.OrderCancellation) -> None:
39
- pass
40
-
41
- @abc.abstractmethod
42
- def _on_modify_order(self, event: events.requests.OrderModification) -> None:
43
- pass
44
-
45
- def _respond(self, response_event: events.bases.BrokerResponseEvent) -> None:
46
- self._publish(response_event)
@@ -1,3 +0,0 @@
1
- __all__ = ["DatafeedBase"]
2
-
3
- from .base import DatafeedBase
@@ -1,32 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import abc
4
-
5
- from onesecondtrader.core import events, messaging, models
6
-
7
-
8
- class DatafeedBase(abc.ABC):
9
- def __init__(self, event_bus: messaging.EventBus) -> None:
10
- self._event_bus = event_bus
11
-
12
- def _publish(self, event: events.EventBase) -> None:
13
- self._event_bus.publish(event)
14
-
15
- @abc.abstractmethod
16
- def connect(self) -> None:
17
- pass
18
-
19
- @abc.abstractmethod
20
- def disconnect(self) -> None:
21
- pass
22
-
23
- @abc.abstractmethod
24
- def subscribe(self, symbol: str, bar_period: models.BarPeriod) -> None:
25
- pass
26
-
27
- @abc.abstractmethod
28
- def unsubscribe(self, symbol: str, bar_period: models.BarPeriod) -> None:
29
- pass
30
-
31
- def wait_until_complete(self) -> None:
32
- pass
@@ -1,33 +0,0 @@
1
- __all__ = [
2
- "EventBase",
3
- "MarketEvent",
4
- "BrokerRequestEvent",
5
- "BrokerResponseEvent",
6
- "BarReceived",
7
- "BarProcessed",
8
- "OrderSubmission",
9
- "OrderModification",
10
- "OrderCancellation",
11
- "OrderSubmissionAccepted",
12
- "OrderSubmissionRejected",
13
- "OrderModificationAccepted",
14
- "OrderModificationRejected",
15
- "OrderCancellationAccepted",
16
- "OrderCancellationRejected",
17
- "OrderFilled",
18
- "OrderExpired",
19
- ]
20
-
21
- from .bases import EventBase, MarketEvent, BrokerRequestEvent, BrokerResponseEvent
22
- from .market import BarReceived, BarProcessed
23
- from .requests import OrderSubmission, OrderModification, OrderCancellation
24
- from .responses import (
25
- OrderSubmissionAccepted,
26
- OrderSubmissionRejected,
27
- OrderModificationAccepted,
28
- OrderModificationRejected,
29
- OrderCancellationAccepted,
30
- OrderCancellationRejected,
31
- OrderFilled,
32
- OrderExpired,
33
- )
@@ -1,29 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import dataclasses
4
- import pandas as pd
5
- import uuid
6
-
7
-
8
- @dataclasses.dataclass(kw_only=True, frozen=True)
9
- class EventBase:
10
- ts_event: pd.Timestamp
11
- ts_created: pd.Timestamp = dataclasses.field(
12
- default_factory=lambda: pd.Timestamp.now(tz="UTC")
13
- )
14
-
15
-
16
- @dataclasses.dataclass(kw_only=True, frozen=True)
17
- class MarketEvent(EventBase):
18
- pass
19
-
20
-
21
- @dataclasses.dataclass(kw_only=True, frozen=True)
22
- class BrokerRequestEvent(EventBase):
23
- system_order_id: uuid.UUID
24
-
25
-
26
- @dataclasses.dataclass(kw_only=True, frozen=True)
27
- class BrokerResponseEvent(EventBase):
28
- ts_broker: pd.Timestamp
29
- associated_order_id: uuid.UUID
@@ -1,22 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import dataclasses
4
-
5
- from onesecondtrader.core import models
6
- from . import bases
7
-
8
-
9
- @dataclasses.dataclass(kw_only=True, frozen=True)
10
- class BarReceived(bases.MarketEvent):
11
- symbol: str
12
- bar_period: models.data.BarPeriod
13
- open: float
14
- high: float
15
- low: float
16
- close: float
17
- volume: int | None = None
18
-
19
-
20
- @dataclasses.dataclass(kw_only=True, frozen=True)
21
- class BarProcessed(BarReceived):
22
- indicators: dict[str, float] = dataclasses.field(default_factory=dict)