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.
- onesecondtrader/events/__init__.py +33 -0
- onesecondtrader/events/bases.py +29 -0
- onesecondtrader/events/market.py +22 -0
- onesecondtrader/events/requests.py +31 -0
- onesecondtrader/events/responses.py +54 -0
- onesecondtrader/messaging/__init__.py +7 -0
- onesecondtrader/messaging/contracts.py +11 -0
- onesecondtrader/{core/event_bus.py → messaging/eventbus.py} +10 -27
- onesecondtrader/models/__init__.py +8 -0
- onesecondtrader/models/data.py +10 -0
- onesecondtrader/models/orders.py +15 -0
- {onesecondtrader-0.24.0.dist-info → onesecondtrader-0.25.0.dist-info}/METADATA +1 -1
- onesecondtrader-0.25.0.dist-info/RECORD +16 -0
- onesecondtrader/analyst/__init__.py +0 -0
- onesecondtrader/analyst/charting.py +0 -0
- onesecondtrader/components/__init__.py +0 -0
- onesecondtrader/components/broker_base.py +0 -0
- onesecondtrader/components/datafeed_base.py +0 -0
- onesecondtrader/components/indicator_base.py +0 -0
- onesecondtrader/components/strategy_base.py +0 -0
- onesecondtrader/connectors/__init__.py +0 -0
- onesecondtrader/connectors/ib.py +0 -0
- onesecondtrader/connectors/mt5.py +0 -0
- onesecondtrader/connectors/simulated.py +0 -0
- onesecondtrader/core/__init__.py +0 -47
- onesecondtrader/core/domain_models.py +0 -30
- onesecondtrader/core/event_messages.py +0 -128
- onesecondtrader/core/event_publisher.py +0 -23
- onesecondtrader/core/event_subscriber.py +0 -76
- onesecondtrader/libraries/__init__.py +0 -0
- onesecondtrader/libraries/indicators.py +0 -0
- onesecondtrader/libraries/strategies.py +0 -0
- onesecondtrader/observers/__init__.py +0 -0
- onesecondtrader/observers/csvbookkeeper.py +0 -0
- onesecondtrader-0.24.0.dist-info/RECORD +0 -27
- {onesecondtrader-0.24.0.dist-info → onesecondtrader-0.25.0.dist-info}/WHEEL +0 -0
- {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,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
|
-
|
|
24
|
-
|
|
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,
|
|
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,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.
|
|
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
|
onesecondtrader/connectors/ib.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
onesecondtrader/core/__init__.py
DELETED
|
@@ -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,,
|
|
File without changes
|
|
File without changes
|