PyAlgoEngine 0.12.0.post3__cp313-cp313-win_amd64.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.
- algo_engine/__infra__.pxd +3 -0
- algo_engine/__init__.pxd +3 -0
- algo_engine/__init__.py +91 -0
- algo_engine/apps/__init__.py +17 -0
- algo_engine/apps/backtest/__init__.py +20 -0
- algo_engine/apps/backtest/doc_server.py +328 -0
- algo_engine/apps/backtest/static/styles/dash.css +48 -0
- algo_engine/apps/backtest/templates/dash.html +20 -0
- algo_engine/apps/backtest/templates/index.html +40 -0
- algo_engine/apps/backtest/tester.py +252 -0
- algo_engine/apps/backtest/web_app.py +125 -0
- algo_engine/apps/bokeh_server.py +245 -0
- algo_engine/apps/demo/__init__.py +0 -0
- algo_engine/apps/demo/test.py +40 -0
- algo_engine/apps/sim_input/__init__.py +23 -0
- algo_engine/apps/sim_input/client.py +412 -0
- algo_engine/apps/sim_input/sim_keyboard.py +88 -0
- algo_engine/apps/sim_input/sim_mouse.py +137 -0
- algo_engine/apps/sim_input/window.py +162 -0
- algo_engine/backtest/__init__.py +19 -0
- algo_engine/backtest/__main__.py +51 -0
- algo_engine/backtest/metrics.py +179 -0
- algo_engine/backtest/replay.py +635 -0
- algo_engine/backtest/sim_match.py +506 -0
- algo_engine/base/__infra__.pxd +3 -0
- algo_engine/base/__init__.pxd +3 -0
- algo_engine/base/__init__.py +60 -0
- algo_engine/base/c_allocator_protocol.c +10756 -0
- algo_engine/base/c_allocator_protocol.cp313-win_amd64.pyd +0 -0
- algo_engine/base/c_allocator_protocol.pxd +24 -0
- algo_engine/base/c_allocator_protocol.pyi +68 -0
- algo_engine/base/c_allocator_protocol.pyx +88 -0
- algo_engine/base/c_intern_string.c +5845 -0
- algo_engine/base/c_intern_string.cp313-win_amd64.pyd +0 -0
- algo_engine/base/c_intern_string.pxd +14 -0
- algo_engine/base/c_intern_string.pyi +22 -0
- algo_engine/base/c_intern_string.pyx +17 -0
- algo_engine/base/c_market_data/__infra__.pxd +196 -0
- algo_engine/base/c_market_data/__init__.pxd +196 -0
- algo_engine/base/c_market_data/__init__.py +24 -0
- algo_engine/base/c_market_data/c_candlestick.c +18960 -0
- algo_engine/base/c_market_data/c_candlestick.cp313-win_amd64.pyd +0 -0
- algo_engine/base/c_market_data/c_candlestick.pxd +27 -0
- algo_engine/base/c_market_data/c_candlestick.pyi +217 -0
- algo_engine/base/c_market_data/c_candlestick.pyx +255 -0
- algo_engine/base/c_market_data/c_internal.c +14023 -0
- algo_engine/base/c_market_data/c_internal.cp313-win_amd64.pyd +0 -0
- algo_engine/base/c_market_data/c_internal.pxd +14 -0
- algo_engine/base/c_market_data/c_internal.pyi +47 -0
- algo_engine/base/c_market_data/c_internal.pyx +41 -0
- algo_engine/base/c_market_data/c_market_data.c +30739 -0
- algo_engine/base/c_market_data/c_market_data.cp313-win_amd64.pyd +0 -0
- algo_engine/base/c_market_data/c_market_data.h +1464 -0
- algo_engine/base/c_market_data/c_market_data.pxd +418 -0
- algo_engine/base/c_market_data/c_market_data.pyi +550 -0
- algo_engine/base/c_market_data/c_market_data.pyx +688 -0
- algo_engine/base/c_market_data/c_market_data_buffer.c +29370 -0
- algo_engine/base/c_market_data/c_market_data_buffer.cp313-win_amd64.pyd +0 -0
- algo_engine/base/c_market_data/c_market_data_buffer.h +941 -0
- algo_engine/base/c_market_data/c_market_data_buffer.pxd +143 -0
- algo_engine/base/c_market_data/c_market_data_buffer.pyi +355 -0
- algo_engine/base/c_market_data/c_market_data_buffer.pyx +571 -0
- algo_engine/base/c_market_data/c_market_data_config.h +29 -0
- algo_engine/base/c_market_data/c_tick.c +44230 -0
- algo_engine/base/c_market_data/c_tick.cp313-win_amd64.pyd +0 -0
- algo_engine/base/c_market_data/c_tick.pxd +53 -0
- algo_engine/base/c_market_data/c_tick.pyi +466 -0
- algo_engine/base/c_market_data/c_tick.pyx +673 -0
- algo_engine/base/c_market_data/c_trade_utils.c +28665 -0
- algo_engine/base/c_market_data/c_trade_utils.cp313-win_amd64.pyd +0 -0
- algo_engine/base/c_market_data/c_trade_utils.pxd +53 -0
- algo_engine/base/c_market_data/c_trade_utils.pyi +602 -0
- algo_engine/base/c_market_data/c_trade_utils.pyx +609 -0
- algo_engine/base/c_market_data/c_transaction.c +23521 -0
- algo_engine/base/c_market_data/c_transaction.cp313-win_amd64.pyd +0 -0
- algo_engine/base/c_market_data/c_transaction.pxd +27 -0
- algo_engine/base/c_market_data/c_transaction.pyi +433 -0
- algo_engine/base/c_market_data/c_transaction.pyx +460 -0
- algo_engine/base/console_utils.py +1070 -0
- algo_engine/base/finance_decimal.py +258 -0
- algo_engine/base/telemetrics.py +104 -0
- algo_engine/engine/__infra__.pxd +10 -0
- algo_engine/engine/__init__.pxd +10 -0
- algo_engine/engine/__init__.py +40 -0
- algo_engine/engine/algo_engine.py +904 -0
- algo_engine/engine/c_event_engine.c +16289 -0
- algo_engine/engine/c_event_engine.cp313-win_amd64.pyd +0 -0
- algo_engine/engine/c_event_engine.pxd +25 -0
- algo_engine/engine/c_event_engine.pyi +68 -0
- algo_engine/engine/c_market_engine.c +24222 -0
- algo_engine/engine/c_market_engine.cp313-win_amd64.pyd +0 -0
- algo_engine/engine/c_market_engine.pxd +87 -0
- algo_engine/engine/c_market_engine.pyi +357 -0
- algo_engine/engine/event_engine.py +53 -0
- algo_engine/engine/trade_engine.py +2037 -0
- algo_engine/exchange_profile/__infra__.pxd +99 -0
- algo_engine/exchange_profile/__init__.pxd +99 -0
- algo_engine/exchange_profile/__init__.py +36 -0
- algo_engine/exchange_profile/c_ex_profile_base.c +87 -0
- algo_engine/exchange_profile/c_ex_profile_base.h +1148 -0
- algo_engine/exchange_profile/c_ex_profile_cn.c +968 -0
- algo_engine/exchange_profile/c_ex_profile_cn.h +39 -0
- algo_engine/exchange_profile/c_exchange_profile.c +52061 -0
- algo_engine/exchange_profile/c_exchange_profile.cp313-win_amd64.pyd +0 -0
- algo_engine/exchange_profile/c_exchange_profile.pxd +336 -0
- algo_engine/exchange_profile/c_exchange_profile.pyi +867 -0
- algo_engine/exchange_profile/c_exchange_profile.pyx +1482 -0
- algo_engine/exchange_profile/c_profile_cn.c +7779 -0
- algo_engine/exchange_profile/c_profile_cn.cp313-win_amd64.pyd +0 -0
- algo_engine/exchange_profile/c_profile_cn.pxd +1 -0
- algo_engine/exchange_profile/c_profile_cn.pyi +3 -0
- algo_engine/exchange_profile/c_profile_cn.pyx +1 -0
- algo_engine/exchange_profile/c_profile_default.c +7779 -0
- algo_engine/exchange_profile/c_profile_default.cp313-win_amd64.pyd +0 -0
- algo_engine/exchange_profile/c_profile_default.pxd +1 -0
- algo_engine/exchange_profile/c_profile_default.pyi +3 -0
- algo_engine/exchange_profile/c_profile_default.pyx +1 -0
- algo_engine/exchange_profile/c_profile_dispatcher.c +7779 -0
- algo_engine/exchange_profile/c_profile_dispatcher.cp313-win_amd64.pyd +0 -0
- algo_engine/exchange_profile/c_profile_dispatcher.pxd +1 -0
- algo_engine/exchange_profile/c_profile_dispatcher.pyi +3 -0
- algo_engine/exchange_profile/c_profile_dispatcher.pyx +1 -0
- algo_engine/includes/algo_engine/base/c_allocator_protocol.c +10756 -0
- algo_engine/includes/algo_engine/base/c_intern_string.c +5845 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_candlestick.c +18960 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_internal.c +14023 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_market_data.c +30739 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_market_data.h +1464 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_market_data_buffer.c +29370 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_market_data_buffer.h +941 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_market_data_config.h +29 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_tick.c +44230 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_trade_utils.c +28665 -0
- algo_engine/includes/algo_engine/base/c_market_data/c_transaction.c +23521 -0
- algo_engine/includes/algo_engine/engine/c_event_engine.c +16289 -0
- algo_engine/includes/algo_engine/engine/c_market_engine.c +24222 -0
- algo_engine/includes/algo_engine/exchange_profile/c_ex_profile_base.c +87 -0
- algo_engine/includes/algo_engine/exchange_profile/c_ex_profile_base.h +1148 -0
- algo_engine/includes/algo_engine/exchange_profile/c_ex_profile_cn.c +968 -0
- algo_engine/includes/algo_engine/exchange_profile/c_ex_profile_cn.h +39 -0
- algo_engine/includes/algo_engine/exchange_profile/c_exchange_profile.c +52061 -0
- algo_engine/includes/algo_engine/exchange_profile/c_profile_cn.c +7779 -0
- algo_engine/includes/algo_engine/exchange_profile/c_profile_default.c +7779 -0
- algo_engine/includes/algo_engine/exchange_profile/c_profile_dispatcher.c +7779 -0
- algo_engine/monitor/__init__.py +15 -0
- algo_engine/monitor/advanced_data_interface.py +334 -0
- algo_engine/strategy/__init__.py +44 -0
- algo_engine/strategy/strategy_engine.py +441 -0
- algo_engine/utils/__init__.py +3 -0
- algo_engine/utils/commit_regularizer.py +49 -0
- algo_engine/utils/data_utils.py +296 -0
- pyalgoengine-0.12.0.post3.dist-info/METADATA +142 -0
- pyalgoengine-0.12.0.post3.dist-info/RECORD +156 -0
- pyalgoengine-0.12.0.post3.dist-info/WHEEL +5 -0
- pyalgoengine-0.12.0.post3.dist-info/licenses/LICENSE +21 -0
- pyalgoengine-0.12.0.post3.dist-info/top_level.txt +2 -0
|
Binary file
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from .c_market_data cimport md_variant, md_order_state, MarketData
|
|
2
|
+
from .c_transaction cimport TransactionData
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
cdef class TradeReport(MarketData):
|
|
6
|
+
|
|
7
|
+
cdef dict c_to_json(self)
|
|
8
|
+
|
|
9
|
+
@staticmethod
|
|
10
|
+
cdef TradeReport c_from_json(dict json_dict)
|
|
11
|
+
|
|
12
|
+
cpdef TradeReport reset_order_id(self, object order_id=?)
|
|
13
|
+
|
|
14
|
+
cpdef TradeReport reset_trade_id(self, object trade_id=?)
|
|
15
|
+
|
|
16
|
+
cpdef TransactionData to_trade(self)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
cdef class TradeInstruction(MarketData):
|
|
20
|
+
cdef readonly dict trades
|
|
21
|
+
|
|
22
|
+
cdef dict c_to_json(self)
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
cdef TradeInstruction c_from_json(dict json_dict)
|
|
26
|
+
|
|
27
|
+
cpdef TradeInstruction reset(self)
|
|
28
|
+
|
|
29
|
+
cpdef TradeInstruction reset_order_id(self, object order_id=?)
|
|
30
|
+
|
|
31
|
+
cpdef TradeInstruction set_order_state(self, md_order_state order_state, double timestamp=?)
|
|
32
|
+
|
|
33
|
+
cpdef TradeInstruction fill(self, TradeReport trade_report)
|
|
34
|
+
|
|
35
|
+
cpdef TradeInstruction add_trade(self, TradeReport trade_report)
|
|
36
|
+
|
|
37
|
+
cpdef TradeInstruction cancel_order(self, double timestamp=?)
|
|
38
|
+
|
|
39
|
+
cpdef TradeInstruction canceled(self, double timestamp=?)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
cdef inline object report_from_header(const md_variant* market_data, bint owner):
|
|
43
|
+
cdef TradeReport instance = TradeReport.__new__(TradeReport)
|
|
44
|
+
instance.header = market_data
|
|
45
|
+
instance.owner = owner
|
|
46
|
+
return instance
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
cdef inline object instruction_from_header(const md_variant* market_data, bint owner):
|
|
50
|
+
cdef TradeInstruction instance = TradeInstruction.__new__(TradeInstruction)
|
|
51
|
+
instance.header = market_data
|
|
52
|
+
instance.owner = owner
|
|
53
|
+
return instance
|
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
import uuid
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Any, Literal, Optional, Union
|
|
5
|
+
|
|
6
|
+
from typing_extensions import deprecated
|
|
7
|
+
|
|
8
|
+
from .c_transaction import OrderType, TransactionSide, TransactionData
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OrderState(enum.IntEnum):
|
|
12
|
+
"""
|
|
13
|
+
Enum representing the various states an order can be in during its lifecycle.
|
|
14
|
+
"""
|
|
15
|
+
STATE_UNKNOWN: OrderState
|
|
16
|
+
STATE_REJECTED: OrderState
|
|
17
|
+
STATE_INVALID: OrderState
|
|
18
|
+
STATE_PENDING: OrderState
|
|
19
|
+
STATE_SENT: OrderState
|
|
20
|
+
STATE_PLACED: OrderState
|
|
21
|
+
STATE_PARTFILLED: OrderState
|
|
22
|
+
STATE_FILLED: OrderState
|
|
23
|
+
STATE_CANCELING: OrderState
|
|
24
|
+
STATE_CANCELED: OrderState
|
|
25
|
+
|
|
26
|
+
# Deprecated aliases
|
|
27
|
+
UNKNOWN: deprecated('Use STATE_UNKNOWN instead')(OrderState)
|
|
28
|
+
Rejected: deprecated('Use STATE_REJECTED instead')(OrderState)
|
|
29
|
+
Invalid: deprecated('Use STATE_INVALID instead')(OrderState)
|
|
30
|
+
Pending: deprecated('Use STATE_PENDING instead')(OrderState)
|
|
31
|
+
Sent: deprecated('Use STATE_SENT instead')(OrderState)
|
|
32
|
+
Placed: deprecated('Use STATE_PLACED instead')(OrderState)
|
|
33
|
+
PartFilled: deprecated('Use STATE_PARTFILLED instead')(OrderState)
|
|
34
|
+
Filled: deprecated('Use STATE_FILLED instead')(OrderState)
|
|
35
|
+
Canceling: deprecated('Use STATE_CANCELING instead')(OrderState)
|
|
36
|
+
Canceled: deprecated('Use STATE_CANCELED instead')(OrderState)
|
|
37
|
+
|
|
38
|
+
def __hash__(self) -> int:
|
|
39
|
+
"""Enable usage as a dictionary key."""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def is_working(self) -> bool:
|
|
44
|
+
"""
|
|
45
|
+
Check if order is in a working state.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
True for SENT, PLACED, PARTFILLED, or CANCELING states
|
|
49
|
+
"""
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def is_placed(self) -> bool:
|
|
54
|
+
"""
|
|
55
|
+
Check if order has been placed, require confirmation from exchange.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
True for PLACED, PARTFILLED, FILLED, or CANCELING states
|
|
59
|
+
"""
|
|
60
|
+
...
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def is_done(self) -> bool:
|
|
64
|
+
"""
|
|
65
|
+
Check if order is in a terminal state.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
True for FILLED, CANCELED, REJECTED, or INVALID states
|
|
69
|
+
"""
|
|
70
|
+
...
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def state_name(self) -> str:
|
|
74
|
+
"""Get human-readable name of the order state."""
|
|
75
|
+
...
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class TradeReport:
|
|
79
|
+
"""
|
|
80
|
+
Represents an execution report from the exchange for a filled trade.
|
|
81
|
+
|
|
82
|
+
Contains details about price, volume, fees, and identifiers for both
|
|
83
|
+
the trade and the original order.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def __init__(
|
|
87
|
+
self,
|
|
88
|
+
ticker: str,
|
|
89
|
+
timestamp: float,
|
|
90
|
+
price: float,
|
|
91
|
+
volume: float,
|
|
92
|
+
side: int,
|
|
93
|
+
notional: float = 0.0,
|
|
94
|
+
multiplier: float = 1.0,
|
|
95
|
+
fee: float = 0.0,
|
|
96
|
+
order_id: Union[str, int, bytes, uuid.UUID, None] = None,
|
|
97
|
+
trade_id: Union[str, int, bytes, uuid.UUID, None] = None,
|
|
98
|
+
**kwargs: Any
|
|
99
|
+
) -> None:
|
|
100
|
+
"""
|
|
101
|
+
Initialize a trade report.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
ticker: The ticker of the trade report
|
|
105
|
+
timestamp: Unix timestamp of trade
|
|
106
|
+
price: Execution price
|
|
107
|
+
volume: Traded volume
|
|
108
|
+
side: Trade side (see TransactionSide)
|
|
109
|
+
notional: Optional pre-calculated notional value
|
|
110
|
+
multiplier: Contract multiplier (default 1.0)
|
|
111
|
+
fee: Transaction fee/cost
|
|
112
|
+
order_id: Original order identifier
|
|
113
|
+
trade_id: Unique trade identifier
|
|
114
|
+
**kwargs: Additional trade attributes
|
|
115
|
+
"""
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
def __eq__(self, other: TradeReport) -> bool:
|
|
119
|
+
"""Compare trade reports for equality. By trade_id and order_id."""
|
|
120
|
+
...
|
|
121
|
+
|
|
122
|
+
def __repr__(self) -> str:
|
|
123
|
+
"""Get string representation of the trade report."""
|
|
124
|
+
...
|
|
125
|
+
|
|
126
|
+
def __reduce__(self) -> tuple[Any, ...]:
|
|
127
|
+
"""Support for pickle protocol."""
|
|
128
|
+
...
|
|
129
|
+
|
|
130
|
+
def __setstate__(self, state: Any) -> None:
|
|
131
|
+
"""Support for pickle protocol."""
|
|
132
|
+
...
|
|
133
|
+
|
|
134
|
+
def __copy__(self) -> TradeReport:
|
|
135
|
+
"""Create a deep copy of the trade report."""
|
|
136
|
+
...
|
|
137
|
+
|
|
138
|
+
def reset_order_id(
|
|
139
|
+
self,
|
|
140
|
+
order_id: Union[str, int, bytes, uuid.UUID, None] = None
|
|
141
|
+
) -> TradeReport:
|
|
142
|
+
"""
|
|
143
|
+
Update the order ID reference and return self.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
order_id: New order identifier
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
self (for method chaining)
|
|
150
|
+
"""
|
|
151
|
+
...
|
|
152
|
+
|
|
153
|
+
def reset_trade_id(
|
|
154
|
+
self,
|
|
155
|
+
trade_id: Union[str, int, bytes, uuid.UUID, None] = None
|
|
156
|
+
) -> TradeReport:
|
|
157
|
+
"""
|
|
158
|
+
Update the trade ID and return self.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
trade_id: New trade identifier
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
self (for method chaining)
|
|
165
|
+
"""
|
|
166
|
+
...
|
|
167
|
+
|
|
168
|
+
def to_bytes(self) -> bytes:
|
|
169
|
+
"""Serialize to byte data."""
|
|
170
|
+
...
|
|
171
|
+
|
|
172
|
+
@classmethod
|
|
173
|
+
def from_bytes(cls, data: bytes) -> TradeReport:
|
|
174
|
+
"""Deserialize from byte data."""
|
|
175
|
+
...
|
|
176
|
+
|
|
177
|
+
def to_json(self, fmt: str = 'str', **kwargs) -> dict[str, Any] | str:
|
|
178
|
+
"""Serialize to JSON format."""
|
|
179
|
+
...
|
|
180
|
+
|
|
181
|
+
@classmethod
|
|
182
|
+
def from_json(cls, json_dict: dict[str, Any] | str | bytes) -> TradeReport:
|
|
183
|
+
"""Deserialize from JSON format."""
|
|
184
|
+
...
|
|
185
|
+
|
|
186
|
+
def copy(self) -> TradeReport:
|
|
187
|
+
"""Create a deep copy of the trade report."""
|
|
188
|
+
...
|
|
189
|
+
|
|
190
|
+
def to_trade(self) -> TransactionData:
|
|
191
|
+
"""Convert to TransactionData format."""
|
|
192
|
+
...
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def ticker(self) -> str:
|
|
196
|
+
"""Get the financial instrument identifier."""
|
|
197
|
+
...
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def timestamp(self) -> float:
|
|
201
|
+
"""
|
|
202
|
+
Get the Unix timestamp of this market data.
|
|
203
|
+
|
|
204
|
+
Note: Represents the "last time" (not start time) to prevent future data issues.
|
|
205
|
+
"""
|
|
206
|
+
...
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def dtype(self) -> int:
|
|
210
|
+
"""Get the DataType int value for this market data class."""
|
|
211
|
+
...
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def topic(self) -> str:
|
|
215
|
+
"""
|
|
216
|
+
Get the topic string identifying this market data.
|
|
217
|
+
|
|
218
|
+
Example: "000016.SH.TickData"
|
|
219
|
+
"""
|
|
220
|
+
...
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def market_time(self) -> datetime:
|
|
224
|
+
"""
|
|
225
|
+
Get the timestamp as a Python datetime object.
|
|
226
|
+
|
|
227
|
+
The market_time is subjected to the timezone info. If necessary, set the tz in PROFILE.
|
|
228
|
+
|
|
229
|
+
"""
|
|
230
|
+
...
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def price(self) -> float:
|
|
234
|
+
"""Get execution price."""
|
|
235
|
+
...
|
|
236
|
+
|
|
237
|
+
@property
|
|
238
|
+
def volume(self) -> float:
|
|
239
|
+
"""Get traded volume."""
|
|
240
|
+
...
|
|
241
|
+
|
|
242
|
+
@property
|
|
243
|
+
def side_int(self) -> int:
|
|
244
|
+
"""Get raw integer value of trade side."""
|
|
245
|
+
...
|
|
246
|
+
|
|
247
|
+
@property
|
|
248
|
+
def side_sign(self) -> Literal[-1, 0, 1]:
|
|
249
|
+
"""Get directional sign of trade (-1, 0, 1)."""
|
|
250
|
+
...
|
|
251
|
+
|
|
252
|
+
@property
|
|
253
|
+
def side(self) -> TransactionSide:
|
|
254
|
+
"""Get TransactionSide enum value."""
|
|
255
|
+
...
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def multiplier(self) -> float:
|
|
259
|
+
"""Get contract multiplier."""
|
|
260
|
+
...
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def notional(self) -> float:
|
|
264
|
+
"""Get notional value (price * volume * multiplier)."""
|
|
265
|
+
...
|
|
266
|
+
|
|
267
|
+
@property
|
|
268
|
+
def fee(self) -> float:
|
|
269
|
+
"""Get transaction fee/cost."""
|
|
270
|
+
...
|
|
271
|
+
|
|
272
|
+
@property
|
|
273
|
+
def trade_id(self) -> Union[str, int, bytes, uuid.UUID, None]:
|
|
274
|
+
"""Get unique trade identifier."""
|
|
275
|
+
...
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def order_id(self) -> Union[str, int, bytes, uuid.UUID, None]:
|
|
279
|
+
"""Get the original order identifier."""
|
|
280
|
+
...
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def market_price(self) -> float:
|
|
284
|
+
"""Same as price."""
|
|
285
|
+
...
|
|
286
|
+
|
|
287
|
+
@property
|
|
288
|
+
def volume_flow(self) -> float:
|
|
289
|
+
"""Get signed volume flow (volume * side_sign)."""
|
|
290
|
+
...
|
|
291
|
+
|
|
292
|
+
@property
|
|
293
|
+
def notional_flow(self) -> float:
|
|
294
|
+
"""Get signed notional flow (notional * side_sign)."""
|
|
295
|
+
...
|
|
296
|
+
|
|
297
|
+
@property
|
|
298
|
+
def trade_time(self) -> datetime:
|
|
299
|
+
"""Get timestamp as datetime object."""
|
|
300
|
+
...
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class TradeInstruction:
|
|
304
|
+
"""
|
|
305
|
+
Represents a trading instruction/order and its execution state.
|
|
306
|
+
|
|
307
|
+
Manages order lifecycle automatically through fill, cancel_order,
|
|
308
|
+
and canceled methods. Tracks all executions in the "trades" dictionary.
|
|
309
|
+
"""
|
|
310
|
+
|
|
311
|
+
trades: dict[Union[str, int, bytes, uuid.UUID], TradeReport]
|
|
312
|
+
|
|
313
|
+
def __init__(
|
|
314
|
+
self,
|
|
315
|
+
ticker: str,
|
|
316
|
+
timestamp: float,
|
|
317
|
+
side: int,
|
|
318
|
+
volume: float,
|
|
319
|
+
order_type: int = ...,
|
|
320
|
+
limit_price: float = ...,
|
|
321
|
+
multiplier: float = 1.0,
|
|
322
|
+
order_id: Union[str, int, bytes, uuid.UUID, None] = None,
|
|
323
|
+
**kwargs: Any
|
|
324
|
+
) -> None:
|
|
325
|
+
"""
|
|
326
|
+
Initialize a trade instruction.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
ticker: The ticker of the trade instruction
|
|
330
|
+
timestamp: Creation timestamp
|
|
331
|
+
side: Order side (see TransactionSide)
|
|
332
|
+
volume: Total order volume
|
|
333
|
+
order_type: Order type (see OrderType)
|
|
334
|
+
limit_price: Limit price (for limit orders)
|
|
335
|
+
multiplier: Contract multiplier (default 1.0)
|
|
336
|
+
order_id: Optional order identifier
|
|
337
|
+
**kwargs: Additional order attributes
|
|
338
|
+
"""
|
|
339
|
+
...
|
|
340
|
+
|
|
341
|
+
def __eq__(self, other: TradeInstruction) -> bool:
|
|
342
|
+
"""Compare trade instructions for equality. By order_id."""
|
|
343
|
+
...
|
|
344
|
+
|
|
345
|
+
def __repr__(self) -> str:
|
|
346
|
+
"""Get string representation of the instruction."""
|
|
347
|
+
...
|
|
348
|
+
|
|
349
|
+
def to_bytes(self) -> bytes:
|
|
350
|
+
"""Serialize to byte data."""
|
|
351
|
+
...
|
|
352
|
+
|
|
353
|
+
@classmethod
|
|
354
|
+
def from_bytes(cls, data: bytes) -> TradeInstruction:
|
|
355
|
+
"""Deserialize from byte data."""
|
|
356
|
+
...
|
|
357
|
+
|
|
358
|
+
def to_json(self, fmt: str = 'str', **kwargs) -> dict[str, Any] | str:
|
|
359
|
+
"""Serialize to JSON format."""
|
|
360
|
+
...
|
|
361
|
+
|
|
362
|
+
@classmethod
|
|
363
|
+
def from_json(cls, json_dict: dict[str, Any] | str | bytes) -> TradeInstruction:
|
|
364
|
+
"""Deserialize from JSON format."""
|
|
365
|
+
...
|
|
366
|
+
|
|
367
|
+
def __copy__(self) -> TradeInstruction:
|
|
368
|
+
"""Create a shallow copy of the instruction."""
|
|
369
|
+
...
|
|
370
|
+
|
|
371
|
+
def reset(self) -> TradeInstruction:
|
|
372
|
+
"""Reset instruction to initial state and return self."""
|
|
373
|
+
...
|
|
374
|
+
|
|
375
|
+
def reset_order_id(
|
|
376
|
+
self,
|
|
377
|
+
order_id: Union[str, int, bytes, uuid.UUID, None] = None
|
|
378
|
+
) -> TradeInstruction:
|
|
379
|
+
"""
|
|
380
|
+
Update the order ID and return self.
|
|
381
|
+
|
|
382
|
+
Args:
|
|
383
|
+
order_id: New order identifier
|
|
384
|
+
|
|
385
|
+
Returns:
|
|
386
|
+
self (for method chaining)
|
|
387
|
+
"""
|
|
388
|
+
...
|
|
389
|
+
|
|
390
|
+
def set_order_state(
|
|
391
|
+
self,
|
|
392
|
+
order_state: int,
|
|
393
|
+
timestamp: float = ...
|
|
394
|
+
) -> TradeInstruction:
|
|
395
|
+
"""Update order state and return self."""
|
|
396
|
+
...
|
|
397
|
+
|
|
398
|
+
def fill(self, trade_report: TradeReport) -> TradeInstruction:
|
|
399
|
+
"""Add a trade report to instruction and return self."""
|
|
400
|
+
...
|
|
401
|
+
|
|
402
|
+
def add_trade(self, trade_report: TradeReport) -> TradeInstruction:
|
|
403
|
+
"""Add a trade report and return self. This method skips all safety checks."""
|
|
404
|
+
...
|
|
405
|
+
|
|
406
|
+
def cancel_order(self, timestamp: float = ...) -> TradeInstruction:
|
|
407
|
+
"""
|
|
408
|
+
Transition to CANCELING state and return self.
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
timestamp: Cancellation timestamp (defaults to now)
|
|
412
|
+
"""
|
|
413
|
+
...
|
|
414
|
+
|
|
415
|
+
def canceled(self, timestamp: float = ...) -> TradeInstruction:
|
|
416
|
+
"""
|
|
417
|
+
Transition to CANCELED state and return self.
|
|
418
|
+
|
|
419
|
+
Args:
|
|
420
|
+
timestamp: Cancellation timestamp (defaults to now)
|
|
421
|
+
"""
|
|
422
|
+
...
|
|
423
|
+
|
|
424
|
+
@property
|
|
425
|
+
def ticker(self) -> str:
|
|
426
|
+
"""Get the financial instrument identifier."""
|
|
427
|
+
...
|
|
428
|
+
|
|
429
|
+
@property
|
|
430
|
+
def timestamp(self) -> float:
|
|
431
|
+
"""
|
|
432
|
+
Get the Unix timestamp of this market data.
|
|
433
|
+
|
|
434
|
+
Note: Represents the "last time" (not start time) to prevent future data issues.
|
|
435
|
+
"""
|
|
436
|
+
...
|
|
437
|
+
|
|
438
|
+
@property
|
|
439
|
+
def dtype(self) -> int:
|
|
440
|
+
"""Get the DataType int value for this market data class."""
|
|
441
|
+
...
|
|
442
|
+
|
|
443
|
+
@property
|
|
444
|
+
def topic(self) -> str:
|
|
445
|
+
"""
|
|
446
|
+
Get the topic string identifying this market data.
|
|
447
|
+
|
|
448
|
+
Example: "000016.SH.TickData"
|
|
449
|
+
"""
|
|
450
|
+
...
|
|
451
|
+
|
|
452
|
+
@property
|
|
453
|
+
def market_time(self) -> datetime:
|
|
454
|
+
"""
|
|
455
|
+
Get the timestamp as a Python datetime object.
|
|
456
|
+
|
|
457
|
+
The market_time is subjected to the timezone info. If necessary, set the tz in PROFILE.
|
|
458
|
+
|
|
459
|
+
"""
|
|
460
|
+
...
|
|
461
|
+
|
|
462
|
+
@property
|
|
463
|
+
def is_working(self) -> bool:
|
|
464
|
+
"""
|
|
465
|
+
Check if order is active/working.
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
True for SENT, PLACED, PARTFILLED or CANCELING states
|
|
469
|
+
"""
|
|
470
|
+
...
|
|
471
|
+
|
|
472
|
+
@property
|
|
473
|
+
def is_placed(self) -> bool:
|
|
474
|
+
"""
|
|
475
|
+
Check if order has been placed, require confirmation from exchange.
|
|
476
|
+
|
|
477
|
+
Returns:
|
|
478
|
+
True for PLACED, PARTFILLED, FILLED, or CANCELING states
|
|
479
|
+
"""
|
|
480
|
+
...
|
|
481
|
+
|
|
482
|
+
@property
|
|
483
|
+
def is_done(self) -> bool:
|
|
484
|
+
"""
|
|
485
|
+
Check if order is in terminal state.
|
|
486
|
+
|
|
487
|
+
Returns:
|
|
488
|
+
True for FILLED, CANCELED, REJECTED or INVALID states
|
|
489
|
+
"""
|
|
490
|
+
...
|
|
491
|
+
|
|
492
|
+
@property
|
|
493
|
+
def limit_price(self) -> float:
|
|
494
|
+
"""Get limit price (for limit orders)."""
|
|
495
|
+
...
|
|
496
|
+
|
|
497
|
+
@property
|
|
498
|
+
def volume(self) -> float:
|
|
499
|
+
"""Get total order volume."""
|
|
500
|
+
...
|
|
501
|
+
|
|
502
|
+
@property
|
|
503
|
+
def side_int(self) -> int:
|
|
504
|
+
"""Get raw integer value of order side."""
|
|
505
|
+
...
|
|
506
|
+
|
|
507
|
+
@property
|
|
508
|
+
def side_sign(self) -> Literal[-1, 0, 1]:
|
|
509
|
+
"""Get directional sign of order (-1, 0, 1)."""
|
|
510
|
+
...
|
|
511
|
+
|
|
512
|
+
@property
|
|
513
|
+
def side(self) -> TransactionSide:
|
|
514
|
+
"""Get TransactionSide enum value."""
|
|
515
|
+
...
|
|
516
|
+
|
|
517
|
+
@property
|
|
518
|
+
def order_type_int(self) -> int:
|
|
519
|
+
"""Get raw integer value of the order type."""
|
|
520
|
+
...
|
|
521
|
+
|
|
522
|
+
@property
|
|
523
|
+
def order_type(self) -> OrderType:
|
|
524
|
+
"""Get OrderType enum value."""
|
|
525
|
+
...
|
|
526
|
+
|
|
527
|
+
@property
|
|
528
|
+
def order_state_int(self) -> int:
|
|
529
|
+
"""Get raw integer value of order state."""
|
|
530
|
+
...
|
|
531
|
+
|
|
532
|
+
@property
|
|
533
|
+
def order_state(self) -> OrderState:
|
|
534
|
+
"""Get OrderState enum value."""
|
|
535
|
+
...
|
|
536
|
+
|
|
537
|
+
@property
|
|
538
|
+
def multiplier(self) -> float:
|
|
539
|
+
"""Get contract multiplier."""
|
|
540
|
+
...
|
|
541
|
+
|
|
542
|
+
@property
|
|
543
|
+
def filled_volume(self) -> float:
|
|
544
|
+
"""Get total filled volume across all executions."""
|
|
545
|
+
...
|
|
546
|
+
|
|
547
|
+
@property
|
|
548
|
+
def working_volume(self) -> float:
|
|
549
|
+
"""Get the remaining working volume (volume - filled)."""
|
|
550
|
+
...
|
|
551
|
+
|
|
552
|
+
@property
|
|
553
|
+
def filled_notional(self) -> float:
|
|
554
|
+
"""Get total notional value of fills."""
|
|
555
|
+
...
|
|
556
|
+
|
|
557
|
+
@property
|
|
558
|
+
def fee(self) -> float:
|
|
559
|
+
"""Get cumulative fees across all executions."""
|
|
560
|
+
...
|
|
561
|
+
|
|
562
|
+
@property
|
|
563
|
+
def order_id(self) -> Union[str, int, bytes, uuid.UUID, None]:
|
|
564
|
+
"""Get order identifier."""
|
|
565
|
+
...
|
|
566
|
+
|
|
567
|
+
@property
|
|
568
|
+
def average_price(self) -> float:
|
|
569
|
+
"""Calculate volume-weighted average fill price."""
|
|
570
|
+
...
|
|
571
|
+
|
|
572
|
+
@property
|
|
573
|
+
def start_time(self) -> datetime:
|
|
574
|
+
"""Get creation time as datetime."""
|
|
575
|
+
...
|
|
576
|
+
|
|
577
|
+
@property
|
|
578
|
+
def placed_ts(self) -> float:
|
|
579
|
+
"""Get order placement timestamp (if placed)."""
|
|
580
|
+
|
|
581
|
+
@property
|
|
582
|
+
def canceled_ts(self) -> float:
|
|
583
|
+
"""Get cancellation timestamp (if canceled)."""
|
|
584
|
+
|
|
585
|
+
@property
|
|
586
|
+
def finished_ts(self) -> float:
|
|
587
|
+
"""Get completion timestamp (if done)."""
|
|
588
|
+
|
|
589
|
+
@property
|
|
590
|
+
def placed_time(self) -> Optional[datetime]:
|
|
591
|
+
"""Get order placement time (if placed)."""
|
|
592
|
+
...
|
|
593
|
+
|
|
594
|
+
@property
|
|
595
|
+
def canceled_time(self) -> Optional[datetime]:
|
|
596
|
+
"""Get cancellation time (if canceled)."""
|
|
597
|
+
...
|
|
598
|
+
|
|
599
|
+
@property
|
|
600
|
+
def finished_time(self) -> Optional[datetime]:
|
|
601
|
+
"""Get completion time (if done)."""
|
|
602
|
+
...
|