onesecondtrader 0.24.0__py3-none-any.whl → 0.25.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 (37) hide show
  1. onesecondtrader/events/__init__.py +33 -0
  2. onesecondtrader/events/bases.py +29 -0
  3. onesecondtrader/events/market.py +22 -0
  4. onesecondtrader/events/requests.py +31 -0
  5. onesecondtrader/events/responses.py +54 -0
  6. onesecondtrader/messaging/__init__.py +7 -0
  7. onesecondtrader/messaging/contracts.py +11 -0
  8. onesecondtrader/{core/event_bus.py → messaging/eventbus.py} +10 -27
  9. onesecondtrader/models/__init__.py +8 -0
  10. onesecondtrader/models/data.py +10 -0
  11. onesecondtrader/models/orders.py +15 -0
  12. {onesecondtrader-0.24.0.dist-info → onesecondtrader-0.25.0.dist-info}/METADATA +1 -1
  13. onesecondtrader-0.25.0.dist-info/RECORD +16 -0
  14. onesecondtrader/analyst/__init__.py +0 -0
  15. onesecondtrader/analyst/charting.py +0 -0
  16. onesecondtrader/components/__init__.py +0 -0
  17. onesecondtrader/components/broker_base.py +0 -0
  18. onesecondtrader/components/datafeed_base.py +0 -0
  19. onesecondtrader/components/indicator_base.py +0 -0
  20. onesecondtrader/components/strategy_base.py +0 -0
  21. onesecondtrader/connectors/__init__.py +0 -0
  22. onesecondtrader/connectors/ib.py +0 -0
  23. onesecondtrader/connectors/mt5.py +0 -0
  24. onesecondtrader/connectors/simulated.py +0 -0
  25. onesecondtrader/core/__init__.py +0 -47
  26. onesecondtrader/core/domain_models.py +0 -30
  27. onesecondtrader/core/event_messages.py +0 -128
  28. onesecondtrader/core/event_publisher.py +0 -23
  29. onesecondtrader/core/event_subscriber.py +0 -76
  30. onesecondtrader/libraries/__init__.py +0 -0
  31. onesecondtrader/libraries/indicators.py +0 -0
  32. onesecondtrader/libraries/strategies.py +0 -0
  33. onesecondtrader/observers/__init__.py +0 -0
  34. onesecondtrader/observers/csvbookkeeper.py +0 -0
  35. onesecondtrader-0.24.0.dist-info/RECORD +0 -27
  36. {onesecondtrader-0.24.0.dist-info → onesecondtrader-0.25.0.dist-info}/WHEEL +0 -0
  37. {onesecondtrader-0.24.0.dist-info → onesecondtrader-0.25.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,33 @@
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
+ )
@@ -0,0 +1,29 @@
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
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+
5
+ from onesecondtrader 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)
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import uuid
5
+
6
+ from onesecondtrader import models
7
+ from . import bases
8
+
9
+
10
+ @dataclasses.dataclass(kw_only=True, frozen=True)
11
+ class OrderSubmission(bases.BrokerRequestEvent):
12
+ system_order_id: uuid.UUID = dataclasses.field(default_factory=uuid.uuid4)
13
+ symbol: str
14
+ order_type: models.orders.OrderType
15
+ side: models.orders.OrderSide
16
+ quantity: float
17
+ limit_price: float | None = None
18
+ stop_price: float | None = None
19
+
20
+
21
+ @dataclasses.dataclass(kw_only=True, frozen=True)
22
+ class OrderCancellation(bases.BrokerRequestEvent):
23
+ symbol: str
24
+
25
+
26
+ @dataclasses.dataclass(kw_only=True, frozen=True)
27
+ class OrderModification(bases.BrokerRequestEvent):
28
+ symbol: str
29
+ quantity: float | None = None
30
+ limit_price: float | None = None
31
+ stop_price: float | None = None
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import uuid
5
+
6
+ from onesecondtrader import models
7
+ from . import bases
8
+
9
+
10
+ @dataclasses.dataclass(kw_only=True, frozen=True)
11
+ class OrderSubmissionAccepted(bases.BrokerResponseEvent):
12
+ broker_order_id: str | None = None
13
+
14
+
15
+ @dataclasses.dataclass(kw_only=True, frozen=True)
16
+ class OrderSubmissionRejected(bases.BrokerResponseEvent):
17
+ reason: str | None = None
18
+
19
+
20
+ @dataclasses.dataclass(kw_only=True, frozen=True)
21
+ class OrderModificationAccepted(bases.BrokerResponseEvent):
22
+ broker_order_id: str | None = None
23
+
24
+
25
+ @dataclasses.dataclass(kw_only=True, frozen=True)
26
+ class OrderModificationRejected(bases.BrokerResponseEvent):
27
+ reason: str | None = None
28
+
29
+
30
+ @dataclasses.dataclass(kw_only=True, frozen=True)
31
+ class OrderCancellationAccepted(bases.BrokerResponseEvent):
32
+ pass
33
+
34
+
35
+ @dataclasses.dataclass(kw_only=True, frozen=True)
36
+ class OrderCancellationRejected(bases.BrokerResponseEvent):
37
+ reason: str | None = None
38
+
39
+
40
+ @dataclasses.dataclass(kw_only=True, frozen=True)
41
+ class OrderFilled(bases.BrokerResponseEvent):
42
+ fill_id: uuid.UUID = dataclasses.field(default_factory=uuid.uuid4)
43
+ broker_fill_id: str | None = None
44
+ symbol: str
45
+ side: models.orders.OrderSide
46
+ quantity_filled: float
47
+ fill_price: float
48
+ commission: float
49
+ exchange: str = "SIMULATED"
50
+
51
+
52
+ @dataclasses.dataclass(kw_only=True, frozen=True)
53
+ class OrderExpired(bases.BrokerResponseEvent):
54
+ pass
@@ -0,0 +1,7 @@
1
+ __all__ = [
2
+ "EventBus",
3
+ "EventSubscriberLike",
4
+ ]
5
+
6
+ from .eventbus import EventBus
7
+ from .contracts import EventSubscriberLike
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+
5
+ from onesecondtrader import events
6
+
7
+
8
+ @typing.runtime_checkable
9
+ class EventSubscriberLike(typing.Protocol):
10
+ def receive(self, event: events.bases.EventBase) -> None: ...
11
+ def wait_until_idle(self) -> None: ...
@@ -1,53 +1,36 @@
1
- """
2
- Read first: [Event Messages](./event_messages.md).
3
-
4
- ---
5
- This module defines the central event bus for publish-subscribe communication.
6
-
7
- EventBus is the core messaging infrastructure that routes events between system
8
- components.
9
- Subscribers register interest in specific event types and receive events when publishers
10
- dispatch them.
11
- Event routing uses exact type matching, so subscribing to a base class will not receive
12
- events of derived types.
13
- ---
14
- """
1
+ from __future__ import annotations
15
2
 
16
3
  import collections
17
4
  import threading
18
- import typing
19
-
20
- from .event_messages import EventBase
21
-
22
5
 
23
- @typing.runtime_checkable
24
- class EventSubscriberLike(typing.Protocol):
25
- def receive(self, event: EventBase) -> None: ...
26
- def wait_until_idle(self) -> None: ...
6
+ from onesecondtrader import events
7
+ from . import contracts
27
8
 
28
9
 
29
10
  class EventBus:
30
11
  def __init__(self) -> None:
31
12
  self._per_event_subscriptions: collections.defaultdict[
32
- type[EventBase], set[EventSubscriberLike]
13
+ type[events.bases.EventBase], set[contracts.EventSubscriberLike]
33
14
  ] = collections.defaultdict(set)
34
- self._subscribers: set[EventSubscriberLike] = set()
15
+ self._subscribers: set[contracts.EventSubscriberLike] = set()
35
16
  self._lock: threading.Lock = threading.Lock()
36
17
 
37
18
  def subscribe(
38
- self, subscriber: EventSubscriberLike, event_type: type[EventBase]
19
+ self,
20
+ subscriber: contracts.EventSubscriberLike,
21
+ event_type: type[events.bases.EventBase],
39
22
  ) -> None:
40
23
  with self._lock:
41
24
  self._subscribers.add(subscriber)
42
25
  self._per_event_subscriptions[event_type].add(subscriber)
43
26
 
44
- def unsubscribe(self, subscriber: EventSubscriberLike) -> None:
27
+ def unsubscribe(self, subscriber: contracts.EventSubscriberLike) -> None:
45
28
  with self._lock:
46
29
  for set_of_event_subscribers in self._per_event_subscriptions.values():
47
30
  set_of_event_subscribers.discard(subscriber)
48
31
  self._subscribers.discard(subscriber)
49
32
 
50
- def publish(self, event: EventBase) -> None:
33
+ def publish(self, event: events.bases.EventBase) -> None:
51
34
  with self._lock:
52
35
  subscribers = self._per_event_subscriptions[type(event)].copy()
53
36
  for subscriber in subscribers:
@@ -0,0 +1,8 @@
1
+ __all__ = [
2
+ "BarPeriod",
3
+ "OrderSide",
4
+ "OrderType",
5
+ ]
6
+
7
+ from .data import BarPeriod
8
+ from .orders import OrderSide, OrderType
@@ -0,0 +1,10 @@
1
+ from __future__ import annotations
2
+
3
+ import enum
4
+
5
+
6
+ class BarPeriod(enum.Enum):
7
+ SECOND = enum.auto()
8
+ MINUTE = enum.auto()
9
+ HOUR = enum.auto()
10
+ DAY = enum.auto()
@@ -0,0 +1,15 @@
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()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onesecondtrader
3
- Version: 0.24.0
3
+ Version: 0.25.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,16 @@
1
+ onesecondtrader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ onesecondtrader/events/__init__.py,sha256=IOlFRdiOXz93SpvkpKL8wr1954d_8olKSB1n9mlTL3Y,898
3
+ onesecondtrader/events/bases.py,sha256=g-ykq2jgcitIAueRurUlqAq0jINQwuhSWi_khAniPHw,662
4
+ onesecondtrader/events/market.py,sha256=IfHuIGfp_IUiw-dFay4c4RYmkoNzshxbhuWTglBqfN0,509
5
+ onesecondtrader/events/requests.py,sha256=2KXwSckiar9-fy8wkN3vcSIeOkeBfeo_XhUhrNKEd2Q,831
6
+ onesecondtrader/events/responses.py,sha256=w_BH1nkkPyxQjh30EXEVFcUGDoMprFc2PuAaqpVrQ8A,1436
7
+ onesecondtrader/messaging/__init__.py,sha256=9yLobI20ZmqipPHG_pwVgdGOEoj-sIAdGWhH17MKSu4,132
8
+ onesecondtrader/messaging/contracts.py,sha256=_LCDtwqgCqNZ5Js1Ht5iFvqNqZUMzi83RVeJgXpTeno,267
9
+ onesecondtrader/messaging/eventbus.py,sha256=J36tmuemRjDATHikSSzL3-7Kmx5fu_sX09X7tb94IF0,1522
10
+ onesecondtrader/models/__init__.py,sha256=cH5xyniz78MQjM9_-fFdP1ZW6FFLTmayMwQauFO23bU,135
11
+ onesecondtrader/models/data.py,sha256=TqUvTtjpmzTJT8ZdTYnlVoyI7Qck2IsseCazWZxJgD0,173
12
+ onesecondtrader/models/orders.py,sha256=y6Ar-6fMqaOd_hRnRGvfWUF0Z13H_2hfTOW3ROOk0A8,254
13
+ onesecondtrader-0.25.0.dist-info/METADATA,sha256=eWtsWhZOEqTGaEubNmJhXnWFtYxSfhYwJheci2HAwkI,9682
14
+ onesecondtrader-0.25.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
15
+ onesecondtrader-0.25.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
16
+ onesecondtrader-0.25.0.dist-info/RECORD,,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,47 +0,0 @@
1
- from .domain_models import BarPeriod, OrderSide, OrderType
2
- from .event_bus import EventBus
3
- from .event_messages import (
4
- AcceptedOrderCancellation,
5
- AcceptedOrderModification,
6
- AcceptedOrderSubmission,
7
- BrokerRequestEventBase,
8
- BrokerResponseEventBase,
9
- ConfirmedOrderExpired,
10
- ConfirmedOrderFilled,
11
- EventBase,
12
- MarketEventBase,
13
- NewBar,
14
- RejectedOrderCancellation,
15
- RejectedOrderModification,
16
- RejectedOrderSubmission,
17
- RequestOrderCancellation,
18
- RequestOrderModification,
19
- RequestOrderSubmission,
20
- )
21
- from .event_publisher import EventPublisher
22
- from .event_subscriber import EventSubscriber
23
-
24
- __all__ = [
25
- "BarPeriod",
26
- "OrderSide",
27
- "OrderType",
28
- "EventBus",
29
- "AcceptedOrderCancellation",
30
- "AcceptedOrderModification",
31
- "AcceptedOrderSubmission",
32
- "BrokerRequestEventBase",
33
- "BrokerResponseEventBase",
34
- "ConfirmedOrderExpired",
35
- "ConfirmedOrderFilled",
36
- "EventBase",
37
- "MarketEventBase",
38
- "NewBar",
39
- "RejectedOrderCancellation",
40
- "RejectedOrderModification",
41
- "RejectedOrderSubmission",
42
- "RequestOrderCancellation",
43
- "RequestOrderModification",
44
- "RequestOrderSubmission",
45
- "EventPublisher",
46
- "EventSubscriber",
47
- ]
@@ -1,30 +0,0 @@
1
- """
2
- ---
3
- This module defines the core domain models used throughout the system.
4
-
5
- Domain models are enumerations that define the shared vocabulary of the trading system.
6
- They provide a fixed set of valid values for core concepts and are used across all
7
- system components to ensure consistency and type safety.
8
- ---
9
- """
10
-
11
- import enum
12
-
13
-
14
- class OrderType(enum.Enum):
15
- LIMIT = enum.auto()
16
- MARKET = enum.auto()
17
- STOP = enum.auto()
18
- STOP_LIMIT = enum.auto()
19
-
20
-
21
- class OrderSide(enum.Enum):
22
- BUY = enum.auto()
23
- SELL = enum.auto()
24
-
25
-
26
- class BarPeriod(enum.Enum):
27
- SECOND = 32
28
- MINUTE = 33
29
- HOUR = 34
30
- DAY = 35
@@ -1,128 +0,0 @@
1
- """
2
- Read first: [Domain Models](./domain_models.md).
3
-
4
- ---
5
- This module defines the event messages used throughout the system.
6
-
7
- Event messages are immutable dataclasses used for communication between system
8
- components
9
- They are semantically grouped into market, broker request, and broker
10
- response events via inheritance from dedicated base classes.
11
- ---
12
- """
13
-
14
- import dataclasses
15
- import pandas as pd
16
- import uuid
17
-
18
- from .domain_models import BarPeriod, OrderSide, OrderType
19
-
20
-
21
- @dataclasses.dataclass(kw_only=True, frozen=True)
22
- class EventBase:
23
- ts_event: pd.Timestamp
24
- ts_created: pd.Timestamp = dataclasses.field(
25
- default_factory=lambda: pd.Timestamp.now(tz="UTC")
26
- )
27
-
28
-
29
- @dataclasses.dataclass(kw_only=True, frozen=True)
30
- class MarketEventBase(EventBase):
31
- pass
32
-
33
-
34
- @dataclasses.dataclass(kw_only=True, frozen=True)
35
- class BrokerRequestEventBase(EventBase):
36
- pass
37
-
38
-
39
- @dataclasses.dataclass(kw_only=True, frozen=True)
40
- class BrokerResponseEventBase(EventBase):
41
- ts_broker: pd.Timestamp
42
-
43
-
44
- @dataclasses.dataclass(kw_only=True, frozen=True)
45
- class NewBar(MarketEventBase):
46
- symbol: str
47
- bar_period: BarPeriod
48
- open: float
49
- high: float
50
- low: float
51
- close: float
52
- volume: int | None = None
53
-
54
-
55
- @dataclasses.dataclass(kw_only=True, frozen=True)
56
- class RequestOrderSubmission(BrokerRequestEventBase):
57
- order_id: uuid.UUID = dataclasses.field(default_factory=uuid.uuid4)
58
- symbol: str
59
- order_type: OrderType
60
- side: OrderSide
61
- quantity: float
62
- limit_price: float | None = None
63
- stop_price: float | None = None
64
-
65
-
66
- @dataclasses.dataclass(kw_only=True, frozen=True)
67
- class RequestOrderCancellation(BrokerRequestEventBase):
68
- symbol: str
69
- order_id: uuid.UUID
70
-
71
-
72
- @dataclasses.dataclass(kw_only=True, frozen=True)
73
- class RequestOrderModification(BrokerRequestEventBase):
74
- symbol: str
75
- order_id: uuid.UUID
76
- quantity: float | None = None
77
- limit_price: float | None = None
78
- stop_price: float | None = None
79
-
80
-
81
- @dataclasses.dataclass(kw_only=True, frozen=True)
82
- class AcceptedOrderSubmission(BrokerResponseEventBase):
83
- order_id: uuid.UUID
84
- broker_order_id: str | None = None
85
-
86
-
87
- @dataclasses.dataclass(kw_only=True, frozen=True)
88
- class AcceptedOrderModification(BrokerResponseEventBase):
89
- order_id: uuid.UUID
90
- broker_order_id: str | None = None
91
-
92
-
93
- @dataclasses.dataclass(kw_only=True, frozen=True)
94
- class AcceptedOrderCancellation(BrokerResponseEventBase):
95
- order_id: uuid.UUID
96
-
97
-
98
- @dataclasses.dataclass(kw_only=True, frozen=True)
99
- class RejectedOrderSubmission(BrokerResponseEventBase):
100
- order_id: uuid.UUID
101
-
102
-
103
- @dataclasses.dataclass(kw_only=True, frozen=True)
104
- class RejectedOrderModification(BrokerResponseEventBase):
105
- order_id: uuid.UUID
106
-
107
-
108
- @dataclasses.dataclass(kw_only=True, frozen=True)
109
- class RejectedOrderCancellation(BrokerResponseEventBase):
110
- order_id: uuid.UUID
111
-
112
-
113
- @dataclasses.dataclass(kw_only=True, frozen=True)
114
- class ConfirmedOrderFilled(BrokerResponseEventBase):
115
- fill_id: uuid.UUID = dataclasses.field(default_factory=uuid.uuid4)
116
- broker_fill_id: str | None = None
117
- associated_order_id: uuid.UUID
118
- symbol: str
119
- side: OrderSide
120
- quantity_filled: float
121
- fill_price: float
122
- commission: float
123
- exchange: str = "SIMULATED"
124
-
125
-
126
- @dataclasses.dataclass(kw_only=True, frozen=True)
127
- class ConfirmedOrderExpired(BrokerResponseEventBase):
128
- order_id: uuid.UUID
@@ -1,23 +0,0 @@
1
- """
2
- Read first: [Event Bus](./event_bus.md), [Event Messages](./event_messages.md).
3
-
4
- ---
5
- This module defines the base class for components that publish events.
6
-
7
- EventPublisher provides a minimal interface for publishing events to the event bus.
8
- Components that only publish events inherit from this class directly.
9
- Components that both subscribe and publish inherit from both EventSubscriber and
10
- EventPublisher.
11
- ---
12
- """
13
-
14
- from .event_bus import EventBus
15
- from .event_messages import EventBase
16
-
17
-
18
- class EventPublisher:
19
- def __init__(self, event_bus: EventBus) -> None:
20
- self._event_bus = event_bus
21
-
22
- def _publish(self, event: EventBase) -> None:
23
- self._event_bus.publish(event)
@@ -1,76 +0,0 @@
1
- """
2
- Read first: [Event Bus](./event_bus.md), [Event Messages](./event_messages.md).
3
-
4
- ---
5
- This module defines the base class for components that subscribe to events.
6
-
7
- EventSubscriber provides a threaded event loop that receives events from the event bus.
8
- Each subscriber runs in its own thread and processes events from its internal queue.
9
- Components that only subscribe inherit from this class directly.
10
- Components that both subscribe and publish inherit from both EventSubscriber and
11
- EventPublisher.
12
- ---
13
- """
14
-
15
- import abc
16
- import queue
17
- import threading
18
-
19
- from .event_bus import EventBus
20
- from .event_messages import EventBase
21
-
22
-
23
- class EventSubscriber(abc.ABC):
24
- def __init__(self, event_bus: EventBus) -> None:
25
- self._event_bus = event_bus
26
- self._queue: queue.Queue[EventBase | None] = queue.Queue()
27
- self._running = True
28
- self._thread = threading.Thread(
29
- target=self._event_loop, name=self.__class__.__name__
30
- )
31
- self._thread.start()
32
-
33
- def receive(self, event: EventBase) -> None:
34
- if self._running:
35
- self._queue.put(event)
36
-
37
- def wait_until_idle(self) -> None:
38
- if not self._running:
39
- return
40
- self._queue.join()
41
-
42
- def shutdown(self) -> None:
43
- if not self._running:
44
- return
45
- self._running = False
46
- self._event_bus.unsubscribe(self)
47
- self._queue.put(None)
48
- if threading.current_thread() is not self._thread:
49
- self._thread.join()
50
-
51
- def _subscribe(self, *event_types: type[EventBase]) -> None:
52
- for event_type in event_types:
53
- self._event_bus.subscribe(self, event_type)
54
-
55
- def _event_loop(self) -> None:
56
- while True:
57
- event = self._queue.get()
58
- if event is None:
59
- self._queue.task_done()
60
- break
61
- try:
62
- self._on_event(event)
63
- except Exception:
64
- self._on_exception()
65
- finally:
66
- self._queue.task_done()
67
- self._cleanup()
68
-
69
- def _on_exception(self) -> None:
70
- pass
71
-
72
- def _cleanup(self) -> None:
73
- pass
74
-
75
- @abc.abstractmethod
76
- def _on_event(self, event: EventBase) -> None: ...
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,27 +0,0 @@
1
- onesecondtrader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- onesecondtrader/analyst/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- onesecondtrader/analyst/charting.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- onesecondtrader/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- onesecondtrader/components/broker_base.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- onesecondtrader/components/datafeed_base.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- onesecondtrader/components/indicator_base.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- onesecondtrader/components/strategy_base.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- onesecondtrader/connectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- onesecondtrader/connectors/ib.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- onesecondtrader/connectors/mt5.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- onesecondtrader/connectors/simulated.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- onesecondtrader/core/__init__.py,sha256=sbxGdriACYOgBBTJluaAF9W11RWfhCDgzKP5JtwN-sI,1228
14
- onesecondtrader/core/domain_models.py,sha256=G-DxruNArRAKSFZOWFKPYMMeJNKx9L7HD_e98TZBxYo,624
15
- onesecondtrader/core/event_bus.py,sha256=uxLIfWqnHM8KTuKThiySgZPe616y6IGNUhTb4CmoE90,2009
16
- onesecondtrader/core/event_messages.py,sha256=N6hbTPEQevGkHKlvW3IoWGbHIzs7ySRSD6v24rynG0c,3348
17
- onesecondtrader/core/event_publisher.py,sha256=XjRcoOIo5-RSxJ_aazTgFd2ypoP-HM9hfiGBtiGojFo,694
18
- onesecondtrader/core/event_subscriber.py,sha256=HqSxOjToXT_YF03W4jjlEayZ82e1RJ-qqY9P-HP_Xns,2220
19
- onesecondtrader/libraries/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- onesecondtrader/libraries/indicators.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- onesecondtrader/libraries/strategies.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- onesecondtrader/observers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- onesecondtrader/observers/csvbookkeeper.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- onesecondtrader-0.24.0.dist-info/METADATA,sha256=WGHyqYgRJA4EK9i5yFPYwpCJjHK8mNk_ZOagQsNMRPs,9682
25
- onesecondtrader-0.24.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
26
- onesecondtrader-0.24.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
27
- onesecondtrader-0.24.0.dist-info/RECORD,,