onesecondtrader 0.50.0__py3-none-any.whl → 0.51.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/brokers/__init__.py +11 -0
- onesecondtrader/brokers/base.py +110 -0
- onesecondtrader/brokers/simulated.py +494 -0
- onesecondtrader/events/orders/base.py +4 -4
- onesecondtrader/events/orders/expirations.py +2 -2
- onesecondtrader/events/orders/fills.py +1 -1
- onesecondtrader/events/requests/base.py +1 -1
- onesecondtrader/events/requests/order_submission.py +1 -1
- onesecondtrader/events/responses/base.py +4 -4
- onesecondtrader/events/responses/cancellations.py +5 -5
- onesecondtrader/events/responses/modifications.py +5 -5
- onesecondtrader/events/responses/orders.py +5 -5
- onesecondtrader/models/rejection_reasons.py +5 -5
- {onesecondtrader-0.50.0.dist-info → onesecondtrader-0.51.0.dist-info}/METADATA +1 -1
- {onesecondtrader-0.50.0.dist-info → onesecondtrader-0.51.0.dist-info}/RECORD +17 -14
- {onesecondtrader-0.50.0.dist-info → onesecondtrader-0.51.0.dist-info}/WHEEL +0 -0
- {onesecondtrader-0.50.0.dist-info → onesecondtrader-0.51.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provides interfaces for order execution via a simulated broker and adapters to real venues.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from onesecondtrader.brokers.base import BrokerBase
|
|
6
|
+
from onesecondtrader.brokers.simulated import SimulatedBroker
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"BrokerBase",
|
|
10
|
+
"SimulatedBroker",
|
|
11
|
+
]
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
|
|
3
|
+
from onesecondtrader import events, messaging
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BrokerBase(messaging.Subscriber):
|
|
7
|
+
"""
|
|
8
|
+
Abstract base class for broker components.
|
|
9
|
+
|
|
10
|
+
A broker component receives order-related request events from the event bus and translates them into actions against an external execution venue or simulated environment.
|
|
11
|
+
Responses to these requests are published back onto the event bus.
|
|
12
|
+
|
|
13
|
+
This class defines the event-handling interface and subscription logic common to all broker implementations.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, event_bus: messaging.EventBus) -> None:
|
|
17
|
+
"""
|
|
18
|
+
Initialize the broker and subscribe to order request events.
|
|
19
|
+
|
|
20
|
+
Parameters:
|
|
21
|
+
event_bus:
|
|
22
|
+
Event bus used for receiving order requests and publishing response events.
|
|
23
|
+
"""
|
|
24
|
+
super().__init__(event_bus)
|
|
25
|
+
|
|
26
|
+
self._subscribe(
|
|
27
|
+
events.requests.OrderSubmissionRequest,
|
|
28
|
+
events.requests.OrderCancellationRequest,
|
|
29
|
+
events.requests.OrderModificationRequest,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
@abc.abstractmethod
|
|
33
|
+
def connect(self) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Establish a connection to the external broker API.
|
|
36
|
+
For simulated broker, this method is a no-op.
|
|
37
|
+
|
|
38
|
+
Implementations are responsible for initializing any external resources required to submit, modify, or cancel orders.
|
|
39
|
+
"""
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
def disconnect(self) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Disconnect the external broker API and stop event processing.
|
|
45
|
+
For simulated broker, this method is a no-op.
|
|
46
|
+
|
|
47
|
+
This method shuts down the subscriber and releases associated resources.
|
|
48
|
+
"""
|
|
49
|
+
self.shutdown()
|
|
50
|
+
|
|
51
|
+
def _on_event(self, event: events.EventBase) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Dispatch incoming order-related events to the appropriate handler.
|
|
54
|
+
|
|
55
|
+
Parameters:
|
|
56
|
+
event:
|
|
57
|
+
Incoming event received from the event bus.
|
|
58
|
+
"""
|
|
59
|
+
match event:
|
|
60
|
+
case events.requests.OrderSubmissionRequest() as submit_order:
|
|
61
|
+
self._on_submit_order(submit_order)
|
|
62
|
+
case events.requests.OrderCancellationRequest() as cancel_order:
|
|
63
|
+
self._on_cancel_order(cancel_order)
|
|
64
|
+
case events.requests.OrderModificationRequest() as modify_order:
|
|
65
|
+
self._on_modify_order(modify_order)
|
|
66
|
+
case _:
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
@abc.abstractmethod
|
|
70
|
+
def _on_submit_order(self, event: events.requests.OrderSubmissionRequest) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Handle an order submission request.
|
|
73
|
+
|
|
74
|
+
Parameters:
|
|
75
|
+
event:
|
|
76
|
+
Order submission request event.
|
|
77
|
+
"""
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
@abc.abstractmethod
|
|
81
|
+
def _on_cancel_order(self, event: events.requests.OrderCancellationRequest) -> None:
|
|
82
|
+
"""
|
|
83
|
+
Handle an order cancellation request.
|
|
84
|
+
|
|
85
|
+
Parameters:
|
|
86
|
+
event:
|
|
87
|
+
Order cancellation request event.
|
|
88
|
+
"""
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
@abc.abstractmethod
|
|
92
|
+
def _on_modify_order(self, event: events.requests.OrderModificationRequest) -> None:
|
|
93
|
+
"""
|
|
94
|
+
Handle an order modification request.
|
|
95
|
+
|
|
96
|
+
Parameters:
|
|
97
|
+
event:
|
|
98
|
+
Order modification request event.
|
|
99
|
+
"""
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
def _respond(self, response_event: events.responses.ResponseBase) -> None:
|
|
103
|
+
"""
|
|
104
|
+
Publish a response event to the event bus.
|
|
105
|
+
|
|
106
|
+
Parameters:
|
|
107
|
+
response_event:
|
|
108
|
+
Response event generated by the broker.
|
|
109
|
+
"""
|
|
110
|
+
self._publish(response_event)
|
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
import uuid
|
|
5
|
+
|
|
6
|
+
from onesecondtrader import events, messaging, models
|
|
7
|
+
from onesecondtrader.brokers.base import BrokerBase
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclasses.dataclass
|
|
11
|
+
class _PendingOrder:
|
|
12
|
+
"""
|
|
13
|
+
Internal order state tracked by the simulated broker.
|
|
14
|
+
|
|
15
|
+
This structure represents broker-side pending order state and is distinct from order request events.
|
|
16
|
+
It is used to evaluate trigger conditions against incoming market bars and to generate fills when conditions are met.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
order_id: uuid.UUID
|
|
20
|
+
symbol: str
|
|
21
|
+
order_type: models.OrderType
|
|
22
|
+
side: models.TradeSide
|
|
23
|
+
quantity: float
|
|
24
|
+
limit_price: float | None = None
|
|
25
|
+
stop_price: float | None = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SimulatedBroker(BrokerBase):
|
|
29
|
+
"""
|
|
30
|
+
Event-driven simulated broker for backtesting.
|
|
31
|
+
|
|
32
|
+
The broker subscribes to order request events and market bar events.
|
|
33
|
+
Order requests are validated and accepted or rejected immediately.
|
|
34
|
+
Accepted orders are stored as pending broker-side state and evaluated against each incoming
|
|
35
|
+
bar.
|
|
36
|
+
When an order triggers, a fill event is published with a deterministic fill price model based on the bar's OHLC values.
|
|
37
|
+
|
|
38
|
+
The broker publishes response events using the event timestamp to preserve simulated time consistency.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
commission_per_unit: float = 0.0
|
|
42
|
+
minimum_commission_per_order: float = 0.0
|
|
43
|
+
|
|
44
|
+
def __init__(self, event_bus: messaging.EventBus) -> None:
|
|
45
|
+
"""
|
|
46
|
+
parameters:
|
|
47
|
+
event_bus:
|
|
48
|
+
Event bus used to receive order requests and market bars, and to publish broker responses and fills.
|
|
49
|
+
"""
|
|
50
|
+
self._pending_market_orders: dict[uuid.UUID, _PendingOrder] = {}
|
|
51
|
+
self._pending_limit_orders: dict[uuid.UUID, _PendingOrder] = {}
|
|
52
|
+
self._pending_stop_orders: dict[uuid.UUID, _PendingOrder] = {}
|
|
53
|
+
self._pending_stop_limit_orders: dict[uuid.UUID, _PendingOrder] = {}
|
|
54
|
+
|
|
55
|
+
super().__init__(event_bus)
|
|
56
|
+
self._subscribe(events.market.BarReceived)
|
|
57
|
+
|
|
58
|
+
def connect(self) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Establish broker readiness.
|
|
61
|
+
|
|
62
|
+
The simulated broker has no external connectivity requirements.
|
|
63
|
+
This method is a no-op and exists to satisfy the broker interface.
|
|
64
|
+
"""
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
def _on_event(self, event: events.EventBase) -> None:
|
|
68
|
+
"""
|
|
69
|
+
Dispatch incoming events.
|
|
70
|
+
|
|
71
|
+
Market bar events are routed to bar processing.
|
|
72
|
+
All other events are delegated to the broker base class for order request handling.
|
|
73
|
+
|
|
74
|
+
parameters:
|
|
75
|
+
event:
|
|
76
|
+
Incoming event received from the event bus.
|
|
77
|
+
"""
|
|
78
|
+
match event:
|
|
79
|
+
case events.market.BarReceived() as bar:
|
|
80
|
+
self._on_bar(bar)
|
|
81
|
+
case _:
|
|
82
|
+
super()._on_event(event)
|
|
83
|
+
|
|
84
|
+
def _on_bar(self, event: events.market.BarReceived) -> None:
|
|
85
|
+
"""
|
|
86
|
+
Process an incoming market bar.
|
|
87
|
+
|
|
88
|
+
Pending orders are evaluated against the bar in a fixed sequence to provide deterministic behavior.
|
|
89
|
+
Crucially, limit orders are processed after stop limit orders to ensure that limit orders created by stop limit orders are evaluated against the same bar.
|
|
90
|
+
|
|
91
|
+
parameters:
|
|
92
|
+
event:
|
|
93
|
+
Market bar used to trigger and price simulated fills.
|
|
94
|
+
"""
|
|
95
|
+
self._process_market_orders(event)
|
|
96
|
+
self._process_stop_orders(event)
|
|
97
|
+
self._process_stop_limit_orders(event)
|
|
98
|
+
self._process_limit_orders(event)
|
|
99
|
+
|
|
100
|
+
def _process_market_orders(self, event: events.market.BarReceived) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Fill pending market orders for the bar symbol.
|
|
103
|
+
|
|
104
|
+
Market orders are filled at the bar open price on the next received bar for the matching symbol.
|
|
105
|
+
|
|
106
|
+
parameters:
|
|
107
|
+
event:
|
|
108
|
+
Market bar providing the simulated fill price and timestamps.
|
|
109
|
+
"""
|
|
110
|
+
for order_id, order in list(self._pending_market_orders.items()):
|
|
111
|
+
if order.symbol != event.symbol:
|
|
112
|
+
continue
|
|
113
|
+
|
|
114
|
+
self._publish(
|
|
115
|
+
events.orders.FillEvent(
|
|
116
|
+
ts_event_ns=event.ts_event_ns,
|
|
117
|
+
ts_broker_ns=event.ts_event_ns,
|
|
118
|
+
associated_order_id=order.order_id,
|
|
119
|
+
symbol=order.symbol,
|
|
120
|
+
side=order.side,
|
|
121
|
+
quantity_filled=order.quantity,
|
|
122
|
+
fill_price=event.open,
|
|
123
|
+
commission=max(
|
|
124
|
+
order.quantity * self.commission_per_unit,
|
|
125
|
+
self.minimum_commission_per_order,
|
|
126
|
+
),
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
del self._pending_market_orders[order_id]
|
|
130
|
+
|
|
131
|
+
def _process_stop_orders(self, event: events.market.BarReceived) -> None:
|
|
132
|
+
"""
|
|
133
|
+
Evaluate and fill pending stop orders for the bar symbol.
|
|
134
|
+
|
|
135
|
+
Stop orders trigger when the bar crosses the stop level.
|
|
136
|
+
The fill price is modeled as the worse of the stop price and the bar open in the direction of the trade.
|
|
137
|
+
|
|
138
|
+
parameters:
|
|
139
|
+
event:
|
|
140
|
+
Market bar used to evaluate triggers and determine fill prices.
|
|
141
|
+
"""
|
|
142
|
+
for order_id, order in list(self._pending_stop_orders.items()):
|
|
143
|
+
if order.symbol != event.symbol:
|
|
144
|
+
continue
|
|
145
|
+
|
|
146
|
+
# This is for mypy, it has already been validated on submission
|
|
147
|
+
assert order.stop_price is not None
|
|
148
|
+
|
|
149
|
+
triggered = False
|
|
150
|
+
match order.side:
|
|
151
|
+
case models.TradeSide.BUY:
|
|
152
|
+
triggered = event.high >= order.stop_price
|
|
153
|
+
case models.TradeSide.SELL:
|
|
154
|
+
triggered = event.low <= order.stop_price
|
|
155
|
+
|
|
156
|
+
if not triggered:
|
|
157
|
+
continue
|
|
158
|
+
|
|
159
|
+
fill_price = 0.0
|
|
160
|
+
match order.side:
|
|
161
|
+
case models.TradeSide.BUY:
|
|
162
|
+
fill_price = max(order.stop_price, event.open)
|
|
163
|
+
case models.TradeSide.SELL:
|
|
164
|
+
fill_price = min(order.stop_price, event.open)
|
|
165
|
+
|
|
166
|
+
self._publish(
|
|
167
|
+
events.orders.FillEvent(
|
|
168
|
+
ts_event_ns=event.ts_event_ns,
|
|
169
|
+
ts_broker_ns=event.ts_event_ns,
|
|
170
|
+
associated_order_id=order.order_id,
|
|
171
|
+
symbol=order.symbol,
|
|
172
|
+
side=order.side,
|
|
173
|
+
quantity_filled=order.quantity,
|
|
174
|
+
fill_price=fill_price,
|
|
175
|
+
commission=max(
|
|
176
|
+
order.quantity * self.commission_per_unit,
|
|
177
|
+
self.minimum_commission_per_order,
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
del self._pending_stop_orders[order_id]
|
|
182
|
+
|
|
183
|
+
def _process_stop_limit_orders(self, event: events.market.BarReceived) -> None:
|
|
184
|
+
"""
|
|
185
|
+
Evaluate pending stop-limit orders for the bar symbol.
|
|
186
|
+
|
|
187
|
+
Stop-limit orders trigger on stop conditions.
|
|
188
|
+
When triggered, they are converted into pending limit orders at the same identifier.
|
|
189
|
+
|
|
190
|
+
parameters:
|
|
191
|
+
event:
|
|
192
|
+
Market bar used to evaluate stop triggers.
|
|
193
|
+
"""
|
|
194
|
+
for order_id, order in list(self._pending_stop_limit_orders.items()):
|
|
195
|
+
if order.symbol != event.symbol:
|
|
196
|
+
continue
|
|
197
|
+
|
|
198
|
+
assert order.stop_price is not None
|
|
199
|
+
|
|
200
|
+
triggered = False
|
|
201
|
+
match order.side:
|
|
202
|
+
case models.TradeSide.BUY:
|
|
203
|
+
triggered = event.high >= order.stop_price
|
|
204
|
+
case models.TradeSide.SELL:
|
|
205
|
+
triggered = event.low <= order.stop_price
|
|
206
|
+
|
|
207
|
+
if not triggered:
|
|
208
|
+
continue
|
|
209
|
+
|
|
210
|
+
limit_order = dataclasses.replace(order, order_type=models.OrderType.LIMIT)
|
|
211
|
+
self._pending_limit_orders[order_id] = limit_order
|
|
212
|
+
del self._pending_stop_limit_orders[order_id]
|
|
213
|
+
|
|
214
|
+
def _process_limit_orders(self, event: events.market.BarReceived) -> None:
|
|
215
|
+
"""
|
|
216
|
+
Evaluate and fill pending limit orders for the bar symbol.
|
|
217
|
+
|
|
218
|
+
Limit orders trigger when the bar crosses the limit level.
|
|
219
|
+
The fill price is modeled as the better of the limit price and the bar open in the direction of the trade.
|
|
220
|
+
|
|
221
|
+
parameters:
|
|
222
|
+
event:
|
|
223
|
+
Market bar used to evaluate triggers and determine fill prices.
|
|
224
|
+
"""
|
|
225
|
+
for order_id, order in list(self._pending_limit_orders.items()):
|
|
226
|
+
if order.symbol != event.symbol:
|
|
227
|
+
continue
|
|
228
|
+
|
|
229
|
+
assert order.limit_price is not None
|
|
230
|
+
|
|
231
|
+
triggered = False
|
|
232
|
+
match order.side:
|
|
233
|
+
case models.TradeSide.BUY:
|
|
234
|
+
triggered = event.low <= order.limit_price
|
|
235
|
+
case models.TradeSide.SELL:
|
|
236
|
+
triggered = event.high >= order.limit_price
|
|
237
|
+
|
|
238
|
+
if not triggered:
|
|
239
|
+
continue
|
|
240
|
+
|
|
241
|
+
fill_price = 0.0
|
|
242
|
+
match order.side:
|
|
243
|
+
case models.TradeSide.BUY:
|
|
244
|
+
fill_price = min(order.limit_price, event.open)
|
|
245
|
+
case models.TradeSide.SELL:
|
|
246
|
+
fill_price = max(order.limit_price, event.open)
|
|
247
|
+
|
|
248
|
+
self._publish(
|
|
249
|
+
events.orders.FillEvent(
|
|
250
|
+
ts_event_ns=event.ts_event_ns,
|
|
251
|
+
ts_broker_ns=event.ts_event_ns,
|
|
252
|
+
associated_order_id=order.order_id,
|
|
253
|
+
symbol=order.symbol,
|
|
254
|
+
side=order.side,
|
|
255
|
+
quantity_filled=order.quantity,
|
|
256
|
+
fill_price=fill_price,
|
|
257
|
+
commission=max(
|
|
258
|
+
order.quantity * self.commission_per_unit,
|
|
259
|
+
self.minimum_commission_per_order,
|
|
260
|
+
),
|
|
261
|
+
)
|
|
262
|
+
)
|
|
263
|
+
del self._pending_limit_orders[order_id]
|
|
264
|
+
|
|
265
|
+
def _reject_if_invalid_submission(
|
|
266
|
+
self, event: events.requests.OrderSubmissionRequest
|
|
267
|
+
) -> bool:
|
|
268
|
+
"""
|
|
269
|
+
Validate an order submission request.
|
|
270
|
+
|
|
271
|
+
Invalid submissions are rejected immediately by publishing an `OrderRejected` response event.
|
|
272
|
+
|
|
273
|
+
parameters:
|
|
274
|
+
event:
|
|
275
|
+
Order submission request event to validate.
|
|
276
|
+
|
|
277
|
+
returns:
|
|
278
|
+
True if the submission is invalid and was rejected, otherwise False.
|
|
279
|
+
"""
|
|
280
|
+
is_invalid = event.quantity <= 0
|
|
281
|
+
|
|
282
|
+
match event.order_type:
|
|
283
|
+
case models.OrderType.LIMIT:
|
|
284
|
+
is_invalid = (
|
|
285
|
+
is_invalid or event.limit_price is None or event.limit_price <= 0
|
|
286
|
+
)
|
|
287
|
+
case models.OrderType.STOP:
|
|
288
|
+
is_invalid = (
|
|
289
|
+
is_invalid or event.stop_price is None or event.stop_price <= 0
|
|
290
|
+
)
|
|
291
|
+
case models.OrderType.STOP_LIMIT:
|
|
292
|
+
is_invalid = is_invalid or (
|
|
293
|
+
event.limit_price is None
|
|
294
|
+
or event.limit_price <= 0
|
|
295
|
+
or event.stop_price is None
|
|
296
|
+
or event.stop_price <= 0
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
if is_invalid:
|
|
300
|
+
self._publish(
|
|
301
|
+
events.responses.OrderRejected(
|
|
302
|
+
ts_event_ns=event.ts_event_ns,
|
|
303
|
+
ts_broker_ns=event.ts_event_ns,
|
|
304
|
+
associated_order_id=event.system_order_id,
|
|
305
|
+
rejection_reason=models.OrderRejectionReason.UNKNOWN,
|
|
306
|
+
rejection_message="Unknown",
|
|
307
|
+
)
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
return is_invalid
|
|
311
|
+
|
|
312
|
+
def _on_submit_order(self, event: events.requests.OrderSubmissionRequest) -> None:
|
|
313
|
+
"""
|
|
314
|
+
Handle an order submission request.
|
|
315
|
+
|
|
316
|
+
Valid orders are stored as pending broker-side state and acknowledged via an `OrderAccepted` response event.
|
|
317
|
+
|
|
318
|
+
parameters:
|
|
319
|
+
event:
|
|
320
|
+
Order submission request event.
|
|
321
|
+
"""
|
|
322
|
+
if self._reject_if_invalid_submission(event):
|
|
323
|
+
return
|
|
324
|
+
|
|
325
|
+
order = _PendingOrder(
|
|
326
|
+
order_id=event.system_order_id,
|
|
327
|
+
symbol=event.symbol,
|
|
328
|
+
order_type=event.order_type,
|
|
329
|
+
side=event.side,
|
|
330
|
+
quantity=event.quantity,
|
|
331
|
+
limit_price=event.limit_price,
|
|
332
|
+
stop_price=event.stop_price,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
match order.order_type:
|
|
336
|
+
case models.OrderType.MARKET:
|
|
337
|
+
self._pending_market_orders[order.order_id] = order
|
|
338
|
+
case models.OrderType.LIMIT:
|
|
339
|
+
self._pending_limit_orders[order.order_id] = order
|
|
340
|
+
case models.OrderType.STOP:
|
|
341
|
+
self._pending_stop_orders[order.order_id] = order
|
|
342
|
+
case models.OrderType.STOP_LIMIT:
|
|
343
|
+
self._pending_stop_limit_orders[order.order_id] = order
|
|
344
|
+
|
|
345
|
+
self._publish(
|
|
346
|
+
events.responses.OrderAccepted(
|
|
347
|
+
ts_event_ns=event.ts_event_ns,
|
|
348
|
+
ts_broker_ns=event.ts_event_ns,
|
|
349
|
+
associated_order_id=order.order_id,
|
|
350
|
+
)
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
def _on_cancel_order(self, event: events.requests.OrderCancellationRequest) -> None:
|
|
354
|
+
"""
|
|
355
|
+
Handle an order cancellation request.
|
|
356
|
+
|
|
357
|
+
If the referenced order is pending, it is removed and acknowledged via `CancellationAccepted`.
|
|
358
|
+
Otherwise, `CancellationRejected` is published.
|
|
359
|
+
|
|
360
|
+
parameters:
|
|
361
|
+
event:
|
|
362
|
+
Order cancellation request event.
|
|
363
|
+
"""
|
|
364
|
+
order_id = event.system_order_id
|
|
365
|
+
|
|
366
|
+
removed = False
|
|
367
|
+
for pending_orders in (
|
|
368
|
+
self._pending_market_orders,
|
|
369
|
+
self._pending_limit_orders,
|
|
370
|
+
self._pending_stop_orders,
|
|
371
|
+
self._pending_stop_limit_orders,
|
|
372
|
+
):
|
|
373
|
+
if order_id in pending_orders:
|
|
374
|
+
del pending_orders[order_id]
|
|
375
|
+
removed = True
|
|
376
|
+
break
|
|
377
|
+
|
|
378
|
+
if removed:
|
|
379
|
+
self._publish(
|
|
380
|
+
events.responses.CancellationAccepted(
|
|
381
|
+
ts_event_ns=event.ts_event_ns,
|
|
382
|
+
ts_broker_ns=event.ts_event_ns,
|
|
383
|
+
associated_order_id=order_id,
|
|
384
|
+
)
|
|
385
|
+
)
|
|
386
|
+
else:
|
|
387
|
+
self._publish(
|
|
388
|
+
events.responses.CancellationRejected(
|
|
389
|
+
ts_event_ns=event.ts_event_ns,
|
|
390
|
+
ts_broker_ns=event.ts_event_ns,
|
|
391
|
+
associated_order_id=order_id,
|
|
392
|
+
rejection_reason=models.CancellationRejectionReason.UNKNOWN,
|
|
393
|
+
rejection_message="Unknown",
|
|
394
|
+
)
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
def _reject_if_invalid_modification(
|
|
398
|
+
self, event: events.requests.OrderModificationRequest
|
|
399
|
+
) -> bool:
|
|
400
|
+
"""
|
|
401
|
+
Validate an order modification request.
|
|
402
|
+
|
|
403
|
+
Invalid modifications are rejected immediately by publishing a `ModificationRejected` response event.
|
|
404
|
+
|
|
405
|
+
parameters:
|
|
406
|
+
event:
|
|
407
|
+
Order modification request event to validate.
|
|
408
|
+
|
|
409
|
+
returns:
|
|
410
|
+
True if the modification is invalid and was rejected, otherwise False.
|
|
411
|
+
"""
|
|
412
|
+
is_invalid = (
|
|
413
|
+
(event.quantity is not None and event.quantity <= 0)
|
|
414
|
+
or (event.limit_price is not None and event.limit_price <= 0)
|
|
415
|
+
or (event.stop_price is not None and event.stop_price <= 0)
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
if is_invalid:
|
|
419
|
+
self._publish(
|
|
420
|
+
events.responses.ModificationRejected(
|
|
421
|
+
ts_event_ns=event.ts_event_ns,
|
|
422
|
+
ts_broker_ns=event.ts_event_ns,
|
|
423
|
+
associated_order_id=event.system_order_id,
|
|
424
|
+
rejection_reason=models.ModificationRejectionReason.UNKNOWN,
|
|
425
|
+
rejection_message="Unknown",
|
|
426
|
+
)
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
return is_invalid
|
|
430
|
+
|
|
431
|
+
def _on_modify_order(self, event: events.requests.OrderModificationRequest) -> None:
|
|
432
|
+
"""
|
|
433
|
+
Handle an order modification request.
|
|
434
|
+
|
|
435
|
+
If the referenced order is pending, its fields are updated and acknowledged via `ModificationAccepted`.
|
|
436
|
+
Otherwise, `ModificationRejected` is published.
|
|
437
|
+
|
|
438
|
+
parameters:
|
|
439
|
+
event:
|
|
440
|
+
Order modification request event.
|
|
441
|
+
"""
|
|
442
|
+
if self._reject_if_invalid_modification(event):
|
|
443
|
+
return
|
|
444
|
+
|
|
445
|
+
order_id = event.system_order_id
|
|
446
|
+
|
|
447
|
+
for pending_orders in (
|
|
448
|
+
self._pending_market_orders,
|
|
449
|
+
self._pending_limit_orders,
|
|
450
|
+
self._pending_stop_orders,
|
|
451
|
+
self._pending_stop_limit_orders,
|
|
452
|
+
):
|
|
453
|
+
if order_id in pending_orders:
|
|
454
|
+
order = pending_orders[order_id]
|
|
455
|
+
|
|
456
|
+
new_quantity = (
|
|
457
|
+
event.quantity if event.quantity is not None else order.quantity
|
|
458
|
+
)
|
|
459
|
+
new_limit_price = (
|
|
460
|
+
event.limit_price
|
|
461
|
+
if event.limit_price is not None
|
|
462
|
+
else order.limit_price
|
|
463
|
+
)
|
|
464
|
+
new_stop_price = (
|
|
465
|
+
event.stop_price
|
|
466
|
+
if event.stop_price is not None
|
|
467
|
+
else order.stop_price
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
pending_orders[order_id] = dataclasses.replace(
|
|
471
|
+
order,
|
|
472
|
+
quantity=new_quantity,
|
|
473
|
+
limit_price=new_limit_price,
|
|
474
|
+
stop_price=new_stop_price,
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
self._publish(
|
|
478
|
+
events.responses.ModificationAccepted(
|
|
479
|
+
ts_event_ns=event.ts_event_ns,
|
|
480
|
+
ts_broker_ns=event.ts_event_ns,
|
|
481
|
+
associated_order_id=order_id,
|
|
482
|
+
)
|
|
483
|
+
)
|
|
484
|
+
return
|
|
485
|
+
|
|
486
|
+
self._publish(
|
|
487
|
+
events.responses.ModificationRejected(
|
|
488
|
+
ts_event_ns=event.ts_event_ns,
|
|
489
|
+
ts_broker_ns=event.ts_event_ns,
|
|
490
|
+
associated_order_id=order_id,
|
|
491
|
+
rejection_reason=models.ModificationRejectionReason.UNKNOWN,
|
|
492
|
+
rejection_message="Unknown",
|
|
493
|
+
)
|
|
494
|
+
)
|
|
@@ -9,17 +9,17 @@ from onesecondtrader import events
|
|
|
9
9
|
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
|
|
10
10
|
class OrderBase(events.EventBase):
|
|
11
11
|
"""
|
|
12
|
-
Base class for
|
|
12
|
+
Base class for brokers-originated order events.
|
|
13
13
|
|
|
14
|
-
Order events are
|
|
14
|
+
Order events are brokers-originated facts about the state or execution of an order.
|
|
15
15
|
Each order event is correlated to a system order identifier via `associated_order_id`.
|
|
16
16
|
|
|
17
17
|
| Field | Type | Semantics |
|
|
18
18
|
|-----------------------|-----------------|---------------------------------------------------------------------------------------|
|
|
19
19
|
| `ts_event_ns` | `int` | Time at which the response event was observed by the system, as UTC epoch nanoseconds.|
|
|
20
20
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
21
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
22
|
-
| `associated_order_id` | `uuid.UUID`. | Identifier of the order associated with the
|
|
21
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the response, as UTC epoch nanoseconds. |
|
|
22
|
+
| `associated_order_id` | `uuid.UUID`. | Identifier of the order associated with the brokers response. |
|
|
23
23
|
| `broker_order_id` | `str` or `None` | Broker-assigned identifier of the order, if reported. |
|
|
24
24
|
| `symbol` | `str` | Identifier of the traded instrument. |
|
|
25
25
|
"""
|
|
@@ -8,13 +8,13 @@ from onesecondtrader.events.orders.base import OrderBase
|
|
|
8
8
|
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
|
|
9
9
|
class OrderExpired(OrderBase):
|
|
10
10
|
"""
|
|
11
|
-
Event indicating that the order is no longer active at the venue due to expiration according to
|
|
11
|
+
Event indicating that the order is no longer active at the venue due to expiration according to brokers- or venue-specific rules (e.g. time-in-force constraints).
|
|
12
12
|
|
|
13
13
|
| Field | Type | Semantics |
|
|
14
14
|
|-----------------------|-----------------|------------------------------------------------------------------------------------|
|
|
15
15
|
| `ts_event_ns` | `int` | Time at which the expiration was observed by the system, as UTC epoch nanoseconds. |
|
|
16
16
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
17
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
17
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the expiration, as UTC epoch nanoseconds. |
|
|
18
18
|
| `associated_order_id` | `uuid.UUID` | Identifier of the expired order. |
|
|
19
19
|
| `broker_order_id` | `str` or `None` | Broker-assigned identifier of the expired order, if reported. |
|
|
20
20
|
| `symbol` | `str` | Identifier of the traded instrument. |
|
|
@@ -19,7 +19,7 @@ class FillEvent(OrderBase):
|
|
|
19
19
|
|-----------------------|---------------------|---------------------------------------------------------------------------------|
|
|
20
20
|
| `ts_event_ns` | `int` | Time at which the fill was observed by the system, as UTC epoch nanoseconds. |
|
|
21
21
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
22
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
22
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the fill, as UTC epoch nanoseconds. |
|
|
23
23
|
| `associated_order_id` | `uuid.UUID` | Identifier of the order associated with the fill. |
|
|
24
24
|
| `broker_order_id` | `str` or `None` | Broker-assigned identifier of the order associated with the fill, if available. |
|
|
25
25
|
| `symbol` | `str` | Identifier of the traded instrument. |
|
|
@@ -11,7 +11,7 @@ class RequestBase(events.EventBase):
|
|
|
11
11
|
"""
|
|
12
12
|
Base class for request events.
|
|
13
13
|
|
|
14
|
-
This class defines attributes common to all requests issued to a
|
|
14
|
+
This class defines attributes common to all requests issued to a brokers.
|
|
15
15
|
|
|
16
16
|
| Field | Type | Semantics |
|
|
17
17
|
|-------------------|-------------|----------------------------------------------------------------------------|
|
|
@@ -10,7 +10,7 @@ from onesecondtrader.events.requests.base import RequestBase
|
|
|
10
10
|
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
|
|
11
11
|
class OrderSubmissionRequest(RequestBase):
|
|
12
12
|
"""
|
|
13
|
-
Event representing a request to submit a new order to a
|
|
13
|
+
Event representing a request to submit a new order to a brokers.
|
|
14
14
|
|
|
15
15
|
The `system_order_id` is a unique identifier assigned by the system to the order submission request by default at object creation.
|
|
16
16
|
|
|
@@ -10,16 +10,16 @@ from onesecondtrader import events
|
|
|
10
10
|
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
|
|
11
11
|
class ResponseBase(events.EventBase):
|
|
12
12
|
"""
|
|
13
|
-
Base class for
|
|
13
|
+
Base class for brokers response events.
|
|
14
14
|
|
|
15
|
-
This class defines attributes common to all responses received from a
|
|
15
|
+
This class defines attributes common to all responses received from a brokers in reaction to previously issued requests.
|
|
16
16
|
|
|
17
17
|
| Field | Type | Semantics |
|
|
18
18
|
|-----------------------|-------------|---------------------------------------------------------------------------------------|
|
|
19
19
|
| `ts_event_ns` | `int` | Time at which the response event was observed by the system, as UTC epoch nanoseconds.|
|
|
20
20
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
21
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
22
|
-
| `associated_order_id` | `uuid.UUID` | Identifier of the order associated with the
|
|
21
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the response, as UTC epoch nanoseconds. |
|
|
22
|
+
| `associated_order_id` | `uuid.UUID` | Identifier of the order associated with the brokers response. |
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
ts_broker_ns: int
|
|
@@ -9,13 +9,13 @@ from onesecondtrader.events.responses.base import ResponseBase
|
|
|
9
9
|
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
|
|
10
10
|
class CancellationAccepted(ResponseBase):
|
|
11
11
|
"""
|
|
12
|
-
Event indicating that the order cancellation has been acknowledged by the
|
|
12
|
+
Event indicating that the order cancellation has been acknowledged by the brokers and the order is no longer active at the execution venue.
|
|
13
13
|
|
|
14
14
|
| Field | Type | Semantics |
|
|
15
15
|
|-----------------------|-----------------|----------------------------------------------------------------------------------------|
|
|
16
16
|
| `ts_event_ns` | `int` | Time at which the cancellation was observed by the system, as UTC epoch nanoseconds. |
|
|
17
17
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
18
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
18
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the cancellation, as UTC epoch nanoseconds. |
|
|
19
19
|
| `associated_order_id` | `uuid.UUID` | Identifier of the cancelled order. |
|
|
20
20
|
| `broker_order_id` | `str` or `None` | Broker-assigned identifier of the cancelled order, if reported. |
|
|
21
21
|
"""
|
|
@@ -26,16 +26,16 @@ class CancellationAccepted(ResponseBase):
|
|
|
26
26
|
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
|
|
27
27
|
class CancellationRejected(ResponseBase):
|
|
28
28
|
"""
|
|
29
|
-
Event indicating that the order cancellation has been rejected by the
|
|
29
|
+
Event indicating that the order cancellation has been rejected by the brokers.
|
|
30
30
|
|
|
31
31
|
| Field | Type | Semantics |
|
|
32
32
|
|-----------------------|--------------------------------------|------------------------------------------------------------------------------------|
|
|
33
33
|
| `ts_event_ns` | `int` | Time at which the rejection was observed by the system, as UTC epoch nanoseconds. |
|
|
34
34
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
35
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
35
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the rejection, as UTC epoch nanoseconds. |
|
|
36
36
|
| `associated_order_id` | `uuid.UUID` | Identifier of the order associated with the rejected cancellation. |
|
|
37
37
|
| `rejection_reason` | `models.CancellationRejectionReason` | Canonical classification of the cancellation rejection cause. |
|
|
38
|
-
| `rejection_message` | `str` | Human-readable explanation provided by the
|
|
38
|
+
| `rejection_message` | `str` | Human-readable explanation provided by the brokers. |
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
41
|
rejection_reason: models.CancellationRejectionReason
|
|
@@ -10,13 +10,13 @@ from onesecondtrader.events.responses.base import ResponseBase
|
|
|
10
10
|
class ModificationAccepted(ResponseBase):
|
|
11
11
|
"""
|
|
12
12
|
Event indicating that the requested modification has been acknowledged by
|
|
13
|
-
the
|
|
13
|
+
the brokers and that the updated order parameters are active at the execution venue.
|
|
14
14
|
|
|
15
15
|
| Field | Type | Semantics |
|
|
16
16
|
|-----------------------|-----------------|----------------------------------------------------------------------------------------|
|
|
17
17
|
| `ts_event_ns` | `int` | Time at which the acceptance was observed by the system, as UTC epoch nanoseconds. |
|
|
18
18
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
19
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
19
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the modification acceptance, as UTC epoch nanoseconds. |
|
|
20
20
|
| `associated_order_id` | `uuid.UUID` | Identifier of the modified order. |
|
|
21
21
|
| `broker_order_id` | `str` or `None` | Broker-assigned identifier of the order after modification, if reported. |
|
|
22
22
|
"""
|
|
@@ -27,16 +27,16 @@ class ModificationAccepted(ResponseBase):
|
|
|
27
27
|
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
|
|
28
28
|
class ModificationRejected(ResponseBase):
|
|
29
29
|
"""
|
|
30
|
-
Event indicating that the requested modification has been rejected by the
|
|
30
|
+
Event indicating that the requested modification has been rejected by the brokers.
|
|
31
31
|
|
|
32
32
|
| Field | Type | Semantics |
|
|
33
33
|
|-----------------------|--------------------------------------|------------------------------------------------------------------------------------|
|
|
34
34
|
| `ts_event_ns` | `int` | Time at which the rejection was observed by the system, as UTC epoch nanoseconds. |
|
|
35
35
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
36
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
36
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the rejection, as UTC epoch nanoseconds. |
|
|
37
37
|
| `associated_order_id` | `uuid.UUID` | Identifier of the order associated with the rejected modification. |
|
|
38
38
|
| `rejection_reason` | `models.ModificationRejectionReason` | Canonical classification of the modification rejection cause. |
|
|
39
|
-
| `rejection_message` | `str` | Human-readable explanation provided by the
|
|
39
|
+
| `rejection_message` | `str` | Human-readable explanation provided by the brokers. |
|
|
40
40
|
"""
|
|
41
41
|
|
|
42
42
|
rejection_reason: models.ModificationRejectionReason
|
|
@@ -9,13 +9,13 @@ from onesecondtrader.events.responses.base import ResponseBase
|
|
|
9
9
|
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
|
|
10
10
|
class OrderAccepted(ResponseBase):
|
|
11
11
|
"""
|
|
12
|
-
Event indicating that the order has been accepted by the
|
|
12
|
+
Event indicating that the order has been accepted by the brokers and is active at the execution venue.
|
|
13
13
|
|
|
14
14
|
| Field | Type | Semantics |
|
|
15
15
|
|-----------------------|-----------------|------------------------------------------------------------------------------------|
|
|
16
16
|
| `ts_event_ns` | `int` | Time at which the acceptance was observed by the system, as UTC epoch nanoseconds. |
|
|
17
17
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
18
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
18
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the acceptance, as UTC epoch nanoseconds. |
|
|
19
19
|
| `associated_order_id` | `uuid.UUID` | Identifier of the accepted order. |
|
|
20
20
|
| `broker_order_id` | `str` or `None` | Broker-assigned identifier of the accepted order. |
|
|
21
21
|
"""
|
|
@@ -26,16 +26,16 @@ class OrderAccepted(ResponseBase):
|
|
|
26
26
|
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
|
|
27
27
|
class OrderRejected(ResponseBase):
|
|
28
28
|
"""
|
|
29
|
-
Event indicating that the order has been rejected by the
|
|
29
|
+
Event indicating that the order has been rejected by the brokers.
|
|
30
30
|
|
|
31
31
|
| Field | Type | Semantics |
|
|
32
32
|
|-----------------------|-------------------------------|------------------------------------------------------------------------------------|
|
|
33
33
|
| `ts_event_ns` | `int` | Time at which the rejection was observed by the system, as UTC epoch nanoseconds. |
|
|
34
34
|
| `ts_created_ns` | `int` | Time at which the event object was created, as UTC epoch nanoseconds. |
|
|
35
|
-
| `ts_broker_ns` | `int` | Time reported by the
|
|
35
|
+
| `ts_broker_ns` | `int` | Time reported by the brokers for the rejection, as UTC epoch nanoseconds. |
|
|
36
36
|
| `associated_order_id` | `uuid.UUID` | Identifier of the rejected order. |
|
|
37
37
|
| `rejection_reason` | `models.OrderRejectionReason` | Canonical classification of the rejection cause. |
|
|
38
|
-
| `rejection_message` | `str` | Human-readable explanation provided by the
|
|
38
|
+
| `rejection_message` | `str` | Human-readable explanation provided by the brokers. |
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
41
|
rejection_reason: models.OrderRejectionReason
|
|
@@ -8,7 +8,7 @@ class OrderRejectionReason(enum.Enum):
|
|
|
8
8
|
Enumeration of canonical order rejection reasons.
|
|
9
9
|
|
|
10
10
|
This enumeration defines the system-level classification of order rejection causes.
|
|
11
|
-
It provides a stable,
|
|
11
|
+
It provides a stable, brokers-agnostic taxonomy for programmatic handling of rejected orders.
|
|
12
12
|
|
|
13
13
|
| Value | Semantics |
|
|
14
14
|
|-----------|---------------------------------------------------------------------------|
|
|
@@ -22,8 +22,8 @@ class ModificationRejectionReason(enum.Enum):
|
|
|
22
22
|
"""
|
|
23
23
|
Enumeration of canonical order modification rejection reasons.
|
|
24
24
|
|
|
25
|
-
This enumeration defines the system-level classification of reasons for which an order modification request may be rejected by a
|
|
26
|
-
It provides a stable,
|
|
25
|
+
This enumeration defines the system-level classification of reasons for which an order modification request may be rejected by a brokers.
|
|
26
|
+
It provides a stable, brokers-agnostic taxonomy intended for programmatic handling and observability of modification rejections.
|
|
27
27
|
|
|
28
28
|
| Value | Semantics |
|
|
29
29
|
|-----------|----------------------------------------------------------------------------------|
|
|
@@ -37,8 +37,8 @@ class CancellationRejectionReason(enum.Enum):
|
|
|
37
37
|
"""
|
|
38
38
|
Enumeration of canonical order cancellation rejection reasons.
|
|
39
39
|
|
|
40
|
-
This enumeration defines the system-level classification of reasons for which an order cancellation request may be rejected by a
|
|
41
|
-
It provides a stable,
|
|
40
|
+
This enumeration defines the system-level classification of reasons for which an order cancellation request may be rejected by a brokers.
|
|
41
|
+
It provides a stable, brokers-agnostic taxonomy intended for programmatic handling and observability of cancellation rejections.
|
|
42
42
|
|
|
43
43
|
| Value | Semantics |
|
|
44
44
|
|-----------|----------------------------------------------------------------------------------|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: onesecondtrader
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.51.0
|
|
4
4
|
Summary: The Trading Infrastructure Toolkit for Python. Research, simulate, and deploy algorithmic trading strategies — all in one place.
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Author: Nils P. Kujath
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
onesecondtrader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
onesecondtrader/brokers/__init__.py,sha256=CmOhwKOayuYCeg5KRiTp4fc8nSDnsLzIBkUNWhUevlo,271
|
|
3
|
+
onesecondtrader/brokers/base.py,sha256=I4tQFr7P1DF5QAWb3I9tHz5D_zTleH8vEXS2WsH55DE,3531
|
|
4
|
+
onesecondtrader/brokers/simulated.py,sha256=ZY39a84J2BmC2ADMkrSRzNBumPXudVBz2eUSnnHb0LM,17930
|
|
2
5
|
onesecondtrader/events/__init__.py,sha256=1T7hJA6afxClEXvvnbXtHu9iMyhduRdJZWlg4ObWaKE,222
|
|
3
6
|
onesecondtrader/events/base.py,sha256=WpLo1bSKJe7Poh2IuDDCiBYZo9vE8mkq3cQlUpyTXsY,850
|
|
4
7
|
onesecondtrader/events/market/__init__.py,sha256=49z6maexBIDkAjIfkLbYzSZWEbyTpQ_HEEgT0eacrDo,132
|
|
5
8
|
onesecondtrader/events/market/bar_processed.py,sha256=NsCDGC21ykmioJoITspoAuz5mesKP0_hkM4UumWk1eU,1993
|
|
6
9
|
onesecondtrader/events/market/bar_received.py,sha256=_LJEZ7P-AfYQEIkXYNt-toO9_WG_XTS2Y86tb-qdOVU,1961
|
|
7
10
|
onesecondtrader/events/orders/__init__.py,sha256=IgVmiVUGMwDlFnL1ItAgvPwmkqEMJDLgQK8aJIKQ1Ic,164
|
|
8
|
-
onesecondtrader/events/orders/base.py,sha256=
|
|
9
|
-
onesecondtrader/events/orders/expirations.py,sha256=
|
|
10
|
-
onesecondtrader/events/orders/fills.py,sha256=
|
|
11
|
+
onesecondtrader/events/orders/base.py,sha256=t4sw98Xv5oeUlJM9zfyVjP8rlqwKyoAUOaiBNuN7iEU,1654
|
|
12
|
+
onesecondtrader/events/orders/expirations.py,sha256=cJiDpfPwIbrMm8FC344jfKQlWxwZZcZCNF2TYxXSVLk,1467
|
|
13
|
+
onesecondtrader/events/orders/fills.py,sha256=oi5tZVImGNw1FzXsbUcPjScFIY8seN_x2TTBZgc90-M,2773
|
|
11
14
|
onesecondtrader/events/requests/__init__.py,sha256=PWVAjNdgHWZArWXz9HU7E-6ZgMdfCpn4wAJiM9a5q6E,325
|
|
12
|
-
onesecondtrader/events/requests/base.py,sha256=
|
|
15
|
+
onesecondtrader/events/requests/base.py,sha256=xmG4rQ0rfWAmo_lMiLgtplHqUo_P6du7JykXXr0QtoM,1085
|
|
13
16
|
onesecondtrader/events/requests/order_cancellation.py,sha256=X_ZMOx09gz0Hf8hvDE1OahqK1SoH4nw9IOMJIdbbTKs,1029
|
|
14
17
|
onesecondtrader/events/requests/order_modification.py,sha256=Tks2mXn1bkuOVLsk98tTk3E2CTld6SF1IwmkCvGvsc8,1538
|
|
15
|
-
onesecondtrader/events/requests/order_submission.py,sha256=
|
|
18
|
+
onesecondtrader/events/requests/order_submission.py,sha256=nEqAYl7QcEeu6wE_HnKqjvG34JWhTtjTjkIrkDiQ0ME,2156
|
|
16
19
|
onesecondtrader/events/responses/__init__.py,sha256=ihg3zxjygLi-sA6wIbsm163ic8346WiAVtztb6ONy_4,409
|
|
17
|
-
onesecondtrader/events/responses/base.py,sha256=
|
|
18
|
-
onesecondtrader/events/responses/cancellations.py,sha256=
|
|
19
|
-
onesecondtrader/events/responses/modifications.py,sha256=
|
|
20
|
-
onesecondtrader/events/responses/orders.py,sha256=
|
|
20
|
+
onesecondtrader/events/responses/base.py,sha256=rq5-avQ-1JqkrahhA7xt892UzecYUHF-3Al9EFSQtAU,1245
|
|
21
|
+
onesecondtrader/events/responses/cancellations.py,sha256=zB8kLCNFRQVVg-IoiAZOxhjPpvZrV6cbIPBkwASQG4Y,2946
|
|
22
|
+
onesecondtrader/events/responses/modifications.py,sha256=sG_KQU-4PsiakZrNKLmE6TOB-lSzSNBoBxJjfSQ9sy4,2973
|
|
23
|
+
onesecondtrader/events/responses/orders.py,sha256=g0N6ak3rOCQ1Vb97gmHYPIMgPtSpavbfL99OMhvzCZg,2791
|
|
21
24
|
onesecondtrader/indicators/__init__.py,sha256=i-syRqCdQdC2BLL-7bDBcdl2Mll1LgE7hi2GleCJ4HI,366
|
|
22
25
|
onesecondtrader/indicators/base.py,sha256=iGfgOj1B_LRGBeh7VjM5OjxoYnSxV7JZUP1C3O_dfmE,4653
|
|
23
26
|
onesecondtrader/indicators/market_fields.py,sha256=Znyii0egBkJT3CFlYhQ5ArRNidmBLF0TzgCr2AWu5CA,4306
|
|
@@ -29,9 +32,9 @@ onesecondtrader/models/__init__.py,sha256=XWL6aNLwAA2JQMoqK2PY-_CwigV0ighx4zwGQV
|
|
|
29
32
|
onesecondtrader/models/bar_fields.py,sha256=GnLBL08ueUr35w2dAbKwOBWrdBS98OC9r0T2NifwTH8,646
|
|
30
33
|
onesecondtrader/models/bar_period.py,sha256=J8ncVtcAxR52uD0nbC8Knds_GUP5wiuNj5rAKq4vv-4,475
|
|
31
34
|
onesecondtrader/models/order_types.py,sha256=SiJamarLQ7zkHzHLLbd86I_TeZrQJ4QEIMqNHj4dxXU,737
|
|
32
|
-
onesecondtrader/models/rejection_reasons.py,sha256=
|
|
35
|
+
onesecondtrader/models/rejection_reasons.py,sha256=Avp1JYf413_aUQQkEeswI-9EJBmQdd7B6bnQ1MslDNE,2132
|
|
33
36
|
onesecondtrader/models/trade_sides.py,sha256=Pf9BpxoUxqgKC_EKAExfSqgfIIK9NW-RpJES0XHRF-8,583
|
|
34
|
-
onesecondtrader-0.
|
|
35
|
-
onesecondtrader-0.
|
|
36
|
-
onesecondtrader-0.
|
|
37
|
-
onesecondtrader-0.
|
|
37
|
+
onesecondtrader-0.51.0.dist-info/METADATA,sha256=5qFkty3l7BfcTm5Ah9vlUWOEi7Ad7jtSYAj5KUNVGMo,9951
|
|
38
|
+
onesecondtrader-0.51.0.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
|
|
39
|
+
onesecondtrader-0.51.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
40
|
+
onesecondtrader-0.51.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|