onetick-py 1.177.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.
- locator_parser/__init__.py +0 -0
- locator_parser/acl.py +73 -0
- locator_parser/actions.py +262 -0
- locator_parser/common.py +368 -0
- locator_parser/io.py +43 -0
- locator_parser/locator.py +150 -0
- onetick/__init__.py +101 -0
- onetick/doc_utilities/__init__.py +3 -0
- onetick/doc_utilities/napoleon.py +40 -0
- onetick/doc_utilities/ot_doctest.py +140 -0
- onetick/doc_utilities/snippets.py +279 -0
- onetick/lib/__init__.py +4 -0
- onetick/lib/instance.py +141 -0
- onetick/py/__init__.py +293 -0
- onetick/py/_stack_info.py +89 -0
- onetick/py/_version.py +2 -0
- onetick/py/aggregations/__init__.py +11 -0
- onetick/py/aggregations/_base.py +648 -0
- onetick/py/aggregations/_docs.py +948 -0
- onetick/py/aggregations/compute.py +286 -0
- onetick/py/aggregations/functions.py +2216 -0
- onetick/py/aggregations/generic.py +104 -0
- onetick/py/aggregations/high_low.py +80 -0
- onetick/py/aggregations/num_distinct.py +83 -0
- onetick/py/aggregations/order_book.py +501 -0
- onetick/py/aggregations/other.py +1014 -0
- onetick/py/backports.py +26 -0
- onetick/py/cache.py +374 -0
- onetick/py/callback/__init__.py +5 -0
- onetick/py/callback/callback.py +276 -0
- onetick/py/callback/callbacks.py +131 -0
- onetick/py/compatibility.py +798 -0
- onetick/py/configuration.py +771 -0
- onetick/py/core/__init__.py +0 -0
- onetick/py/core/_csv_inspector.py +93 -0
- onetick/py/core/_internal/__init__.py +0 -0
- onetick/py/core/_internal/_manually_bound_value.py +6 -0
- onetick/py/core/_internal/_nodes_history.py +250 -0
- onetick/py/core/_internal/_op_utils/__init__.py +0 -0
- onetick/py/core/_internal/_op_utils/every_operand.py +9 -0
- onetick/py/core/_internal/_op_utils/is_const.py +10 -0
- onetick/py/core/_internal/_per_tick_scripts/tick_list_sort_template.script +121 -0
- onetick/py/core/_internal/_proxy_node.py +140 -0
- onetick/py/core/_internal/_state_objects.py +2312 -0
- onetick/py/core/_internal/_state_vars.py +93 -0
- onetick/py/core/_source/__init__.py +0 -0
- onetick/py/core/_source/_symbol_param.py +95 -0
- onetick/py/core/_source/schema.py +97 -0
- onetick/py/core/_source/source_methods/__init__.py +0 -0
- onetick/py/core/_source/source_methods/aggregations.py +809 -0
- onetick/py/core/_source/source_methods/applyers.py +296 -0
- onetick/py/core/_source/source_methods/columns.py +141 -0
- onetick/py/core/_source/source_methods/data_quality.py +301 -0
- onetick/py/core/_source/source_methods/debugs.py +272 -0
- onetick/py/core/_source/source_methods/drops.py +120 -0
- onetick/py/core/_source/source_methods/fields.py +619 -0
- onetick/py/core/_source/source_methods/filters.py +1002 -0
- onetick/py/core/_source/source_methods/joins.py +1413 -0
- onetick/py/core/_source/source_methods/merges.py +605 -0
- onetick/py/core/_source/source_methods/misc.py +1455 -0
- onetick/py/core/_source/source_methods/pandases.py +155 -0
- onetick/py/core/_source/source_methods/renames.py +356 -0
- onetick/py/core/_source/source_methods/sorts.py +183 -0
- onetick/py/core/_source/source_methods/switches.py +142 -0
- onetick/py/core/_source/source_methods/symbols.py +117 -0
- onetick/py/core/_source/source_methods/times.py +627 -0
- onetick/py/core/_source/source_methods/writes.py +986 -0
- onetick/py/core/_source/symbol.py +205 -0
- onetick/py/core/_source/tmp_otq.py +222 -0
- onetick/py/core/column.py +209 -0
- onetick/py/core/column_operations/__init__.py +0 -0
- onetick/py/core/column_operations/_methods/__init__.py +4 -0
- onetick/py/core/column_operations/_methods/_internal.py +28 -0
- onetick/py/core/column_operations/_methods/conversions.py +216 -0
- onetick/py/core/column_operations/_methods/methods.py +292 -0
- onetick/py/core/column_operations/_methods/op_types.py +160 -0
- onetick/py/core/column_operations/accessors/__init__.py +0 -0
- onetick/py/core/column_operations/accessors/_accessor.py +28 -0
- onetick/py/core/column_operations/accessors/decimal_accessor.py +104 -0
- onetick/py/core/column_operations/accessors/dt_accessor.py +537 -0
- onetick/py/core/column_operations/accessors/float_accessor.py +184 -0
- onetick/py/core/column_operations/accessors/str_accessor.py +1367 -0
- onetick/py/core/column_operations/base.py +1121 -0
- onetick/py/core/cut_builder.py +150 -0
- onetick/py/core/db_constants.py +20 -0
- onetick/py/core/eval_query.py +245 -0
- onetick/py/core/lambda_object.py +441 -0
- onetick/py/core/multi_output_source.py +232 -0
- onetick/py/core/per_tick_script.py +2256 -0
- onetick/py/core/query_inspector.py +464 -0
- onetick/py/core/source.py +1744 -0
- onetick/py/db/__init__.py +2 -0
- onetick/py/db/_inspection.py +1128 -0
- onetick/py/db/db.py +1327 -0
- onetick/py/db/utils.py +64 -0
- onetick/py/docs/__init__.py +0 -0
- onetick/py/docs/docstring_parser.py +112 -0
- onetick/py/docs/utils.py +81 -0
- onetick/py/functions.py +2398 -0
- onetick/py/license.py +190 -0
- onetick/py/log.py +88 -0
- onetick/py/math.py +935 -0
- onetick/py/misc.py +470 -0
- onetick/py/oqd/__init__.py +22 -0
- onetick/py/oqd/eps.py +1195 -0
- onetick/py/oqd/sources.py +325 -0
- onetick/py/otq.py +216 -0
- onetick/py/pyomd_mock.py +47 -0
- onetick/py/run.py +916 -0
- onetick/py/servers.py +173 -0
- onetick/py/session.py +1347 -0
- onetick/py/sources/__init__.py +19 -0
- onetick/py/sources/cache.py +167 -0
- onetick/py/sources/common.py +128 -0
- onetick/py/sources/csv.py +642 -0
- onetick/py/sources/custom.py +85 -0
- onetick/py/sources/data_file.py +305 -0
- onetick/py/sources/data_source.py +1045 -0
- onetick/py/sources/empty.py +94 -0
- onetick/py/sources/odbc.py +337 -0
- onetick/py/sources/order_book.py +271 -0
- onetick/py/sources/parquet.py +168 -0
- onetick/py/sources/pit.py +191 -0
- onetick/py/sources/query.py +495 -0
- onetick/py/sources/snapshots.py +419 -0
- onetick/py/sources/split_query_output_by_symbol.py +198 -0
- onetick/py/sources/symbology_mapping.py +123 -0
- onetick/py/sources/symbols.py +374 -0
- onetick/py/sources/ticks.py +825 -0
- onetick/py/sql.py +70 -0
- onetick/py/state.py +251 -0
- onetick/py/types.py +2131 -0
- onetick/py/utils/__init__.py +70 -0
- onetick/py/utils/acl.py +93 -0
- onetick/py/utils/config.py +186 -0
- onetick/py/utils/default.py +49 -0
- onetick/py/utils/file.py +38 -0
- onetick/py/utils/helpers.py +76 -0
- onetick/py/utils/locator.py +94 -0
- onetick/py/utils/perf.py +498 -0
- onetick/py/utils/query.py +49 -0
- onetick/py/utils/render.py +1374 -0
- onetick/py/utils/script.py +244 -0
- onetick/py/utils/temp.py +471 -0
- onetick/py/utils/types.py +120 -0
- onetick/py/utils/tz.py +84 -0
- onetick_py-1.177.0.dist-info/METADATA +137 -0
- onetick_py-1.177.0.dist-info/RECORD +152 -0
- onetick_py-1.177.0.dist-info/WHEEL +5 -0
- onetick_py-1.177.0.dist-info/entry_points.txt +2 -0
- onetick_py-1.177.0.dist-info/licenses/LICENSE +21 -0
- onetick_py-1.177.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, List, Optional, Union
|
|
2
|
+
from onetick.py.backports import Literal
|
|
3
|
+
|
|
4
|
+
from abc import ABC
|
|
5
|
+
|
|
6
|
+
import onetick.py as otp
|
|
7
|
+
from onetick.py.otq import otq
|
|
8
|
+
from onetick.py import types as ott
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from onetick.py.core.source import Source # hack for annotations
|
|
12
|
+
from onetick.py.core.column import _Column
|
|
13
|
+
from onetick.py.compatibility import is_supported_otq_ob_summary, is_max_spread_supported
|
|
14
|
+
from ._base import _Aggregation, get_seconds_from_time_offset
|
|
15
|
+
from ._docs import (_running_doc,
|
|
16
|
+
_bucket_interval_doc,
|
|
17
|
+
_bucket_time_doc,
|
|
18
|
+
_bucket_units_ob_doc,
|
|
19
|
+
_bucket_end_condition_doc,
|
|
20
|
+
_end_condition_per_group_doc,
|
|
21
|
+
_group_by_doc,
|
|
22
|
+
_groups_to_display_doc,
|
|
23
|
+
_side_doc,
|
|
24
|
+
_max_levels_doc,
|
|
25
|
+
_min_levels_doc,
|
|
26
|
+
_max_depth_shares_doc,
|
|
27
|
+
_max_depth_for_price_doc,
|
|
28
|
+
_max_spread_doc,
|
|
29
|
+
_book_uncross_method_doc,
|
|
30
|
+
_dq_events_that_clear_book_doc,
|
|
31
|
+
_best_ask_price_field_doc,
|
|
32
|
+
_best_bid_price_field_doc,
|
|
33
|
+
_bucket_interval_ob_num_levels_doc,
|
|
34
|
+
_identify_source_doc,
|
|
35
|
+
_show_full_detail_doc,
|
|
36
|
+
_show_only_changes_doc,
|
|
37
|
+
_book_delimiters_doc,
|
|
38
|
+
_max_initialization_days_doc,
|
|
39
|
+
_state_key_max_inactivity_sec_doc,
|
|
40
|
+
_size_max_fractional_digits_doc,
|
|
41
|
+
_include_market_order_ticks_doc)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
OB_SNAPSHOT_DOC_PARAMS = [
|
|
45
|
+
_running_doc,
|
|
46
|
+
_bucket_interval_doc, _bucket_time_doc, _bucket_units_ob_doc,
|
|
47
|
+
_bucket_end_condition_doc, _end_condition_per_group_doc, _group_by_doc, _groups_to_display_doc,
|
|
48
|
+
_side_doc, _max_levels_doc, _max_depth_shares_doc, _max_depth_for_price_doc, _max_spread_doc,
|
|
49
|
+
_book_uncross_method_doc, _dq_events_that_clear_book_doc, _identify_source_doc,
|
|
50
|
+
_show_full_detail_doc, _show_only_changes_doc, _book_delimiters_doc,
|
|
51
|
+
_max_initialization_days_doc, _state_key_max_inactivity_sec_doc,
|
|
52
|
+
_size_max_fractional_digits_doc,
|
|
53
|
+
_include_market_order_ticks_doc,
|
|
54
|
+
]
|
|
55
|
+
OB_SNAPSHOT_WIDE_DOC_PARAMS = [
|
|
56
|
+
_running_doc,
|
|
57
|
+
_bucket_interval_doc, _bucket_time_doc, _bucket_units_ob_doc, _bucket_end_condition_doc,
|
|
58
|
+
_end_condition_per_group_doc, _group_by_doc, _groups_to_display_doc,
|
|
59
|
+
_max_levels_doc, _max_depth_shares_doc, _max_depth_for_price_doc, _max_spread_doc,
|
|
60
|
+
_book_uncross_method_doc, _dq_events_that_clear_book_doc,
|
|
61
|
+
_book_delimiters_doc,
|
|
62
|
+
_max_initialization_days_doc, _state_key_max_inactivity_sec_doc,
|
|
63
|
+
_size_max_fractional_digits_doc,
|
|
64
|
+
_include_market_order_ticks_doc,
|
|
65
|
+
]
|
|
66
|
+
OB_SNAPSHOT_FLAT_DOC_PARAMS = [
|
|
67
|
+
_running_doc,
|
|
68
|
+
_bucket_interval_doc, _bucket_time_doc, _bucket_units_ob_doc, _bucket_end_condition_doc,
|
|
69
|
+
_end_condition_per_group_doc, _group_by_doc, _groups_to_display_doc,
|
|
70
|
+
_max_levels_doc,
|
|
71
|
+
_book_uncross_method_doc, _dq_events_that_clear_book_doc,
|
|
72
|
+
_show_full_detail_doc,
|
|
73
|
+
_max_initialization_days_doc, _state_key_max_inactivity_sec_doc,
|
|
74
|
+
_size_max_fractional_digits_doc,
|
|
75
|
+
_include_market_order_ticks_doc,
|
|
76
|
+
]
|
|
77
|
+
OB_SUMMARY_DOC_PARAMS = [
|
|
78
|
+
_running_doc,
|
|
79
|
+
_bucket_interval_doc, _bucket_time_doc, _bucket_units_ob_doc,
|
|
80
|
+
_bucket_end_condition_doc, _end_condition_per_group_doc, _group_by_doc, _groups_to_display_doc,
|
|
81
|
+
_side_doc, _max_levels_doc, _min_levels_doc, _max_depth_shares_doc, _max_depth_for_price_doc, _max_spread_doc,
|
|
82
|
+
_book_uncross_method_doc, _dq_events_that_clear_book_doc, _max_initialization_days_doc,
|
|
83
|
+
_state_key_max_inactivity_sec_doc, _size_max_fractional_digits_doc,
|
|
84
|
+
_include_market_order_ticks_doc,
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
OB_SIZE_DOC_PARAMS = [
|
|
88
|
+
_running_doc,
|
|
89
|
+
_bucket_interval_doc, _bucket_time_doc, _bucket_units_ob_doc,
|
|
90
|
+
_bucket_end_condition_doc, _end_condition_per_group_doc, _group_by_doc, _groups_to_display_doc,
|
|
91
|
+
_side_doc, _max_levels_doc, _max_depth_for_price_doc, _max_spread_doc,
|
|
92
|
+
_book_uncross_method_doc, _dq_events_that_clear_book_doc, _max_initialization_days_doc,
|
|
93
|
+
_best_ask_price_field_doc, _best_bid_price_field_doc,
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
OB_VWAP_DOC_PARAMS = [
|
|
97
|
+
_running_doc,
|
|
98
|
+
_bucket_interval_doc, _bucket_time_doc, _bucket_units_ob_doc,
|
|
99
|
+
_bucket_end_condition_doc, _end_condition_per_group_doc, _group_by_doc, _groups_to_display_doc,
|
|
100
|
+
_side_doc, _max_levels_doc, _max_depth_shares_doc,
|
|
101
|
+
_book_uncross_method_doc, _dq_events_that_clear_book_doc, _max_initialization_days_doc,
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
OB_NUM_LEVELS_DOC_PARAMS = [
|
|
105
|
+
_running_doc,
|
|
106
|
+
_bucket_interval_ob_num_levels_doc, _side_doc,
|
|
107
|
+
_book_uncross_method_doc, _dq_events_that_clear_book_doc, _max_initialization_days_doc,
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class _OrderBookAggregation(_Aggregation, ABC):
|
|
112
|
+
FIELDS_TO_SKIP = ['column_name', 'all_fields', 'boundary_tick_bucket', 'output_field_name']
|
|
113
|
+
FIELDS_MAPPING = dict(_Aggregation.FIELDS_MAPPING, **{
|
|
114
|
+
'side': 'SIDE',
|
|
115
|
+
'max_levels': 'MAX_LEVELS',
|
|
116
|
+
'max_depth_shares': 'MAX_DEPTH_SHARES',
|
|
117
|
+
'max_depth_for_price': 'MAX_DEPTH_FOR_PRICE',
|
|
118
|
+
'max_spread': 'MAX_SPREAD',
|
|
119
|
+
'max_initialization_days': 'MAX_INITIALIZATION_DAYS',
|
|
120
|
+
'book_uncross_method': 'BOOK_UNCROSS_METHOD',
|
|
121
|
+
'dq_events_that_clear_book': 'DQ_EVENTS_THAT_CLEAR_BOOK',
|
|
122
|
+
})
|
|
123
|
+
FIELDS_DEFAULT = dict(_Aggregation.FIELDS_DEFAULT, **{
|
|
124
|
+
'side': None,
|
|
125
|
+
'max_levels': None,
|
|
126
|
+
'max_depth_shares': None,
|
|
127
|
+
'max_depth_for_price': None,
|
|
128
|
+
'max_spread': None,
|
|
129
|
+
'max_initialization_days': 1,
|
|
130
|
+
'book_uncross_method': None,
|
|
131
|
+
'dq_events_that_clear_book': None,
|
|
132
|
+
})
|
|
133
|
+
_validations_to_skip = ['running_all_fields']
|
|
134
|
+
|
|
135
|
+
def __init__(self,
|
|
136
|
+
*args,
|
|
137
|
+
side: Optional[Literal['ASK', 'BID']] = None,
|
|
138
|
+
max_levels: Optional[int] = None,
|
|
139
|
+
max_depth_shares: Optional[int] = None,
|
|
140
|
+
max_depth_for_price: Optional[float] = None,
|
|
141
|
+
max_spread: Optional[float] = None,
|
|
142
|
+
max_initialization_days: int = 1,
|
|
143
|
+
book_uncross_method: Optional[Literal['REMOVE_OLDER_CROSSED_LEVELS']] = None,
|
|
144
|
+
dq_events_that_clear_book: Optional[List[str]] = None,
|
|
145
|
+
**kwargs):
|
|
146
|
+
self.side = side
|
|
147
|
+
self.max_levels = max_levels
|
|
148
|
+
self.max_depth_shares = max_depth_shares
|
|
149
|
+
self.max_depth_for_price = max_depth_for_price
|
|
150
|
+
self.max_spread = max_spread
|
|
151
|
+
self.max_initialization_days = max_initialization_days
|
|
152
|
+
self.book_uncross_method = book_uncross_method
|
|
153
|
+
self.dq_events_that_clear_book = ','.join(dq_events_that_clear_book) if dq_events_that_clear_book else None
|
|
154
|
+
self.bound_symbols = None
|
|
155
|
+
self._validate_ob_input_columns = True
|
|
156
|
+
|
|
157
|
+
super().__init__(_Column('TIMESTAMP'), *args, **kwargs)
|
|
158
|
+
|
|
159
|
+
def _param_validation(self):
|
|
160
|
+
super()._param_validation()
|
|
161
|
+
book_uncross_methods = (None, 'REMOVE_OLDER_CROSSED_LEVELS')
|
|
162
|
+
if self.book_uncross_method not in book_uncross_methods:
|
|
163
|
+
raise ValueError(
|
|
164
|
+
f"Wrong value for parameter 'book_uncross_method': '{self.book_uncross_method}'. "
|
|
165
|
+
f"Possible values: {book_uncross_methods}."
|
|
166
|
+
)
|
|
167
|
+
valid_units = ("seconds", "days", "months", "flexible")
|
|
168
|
+
if self.bucket_units not in valid_units:
|
|
169
|
+
raise ValueError("'bucket_units' can be one of the following: "
|
|
170
|
+
f"'{', '.join(valid_units)}'; however, '{self.bucket_units}' was passed")
|
|
171
|
+
|
|
172
|
+
if self.max_spread is not None:
|
|
173
|
+
if self.side:
|
|
174
|
+
raise ValueError('Parameters `max_spread` and `side` shouldn\'t be specified both at the same time')
|
|
175
|
+
|
|
176
|
+
if not is_max_spread_supported():
|
|
177
|
+
raise RuntimeError('Parameter `max_spread` is not supported on this OneTick version')
|
|
178
|
+
|
|
179
|
+
def disable_ob_input_columns_validation(self):
|
|
180
|
+
self._validate_ob_input_columns = False
|
|
181
|
+
|
|
182
|
+
def validate_input_columns(self, src: 'Source'):
|
|
183
|
+
super().validate_input_columns(src)
|
|
184
|
+
|
|
185
|
+
if not self._validate_ob_input_columns:
|
|
186
|
+
return
|
|
187
|
+
|
|
188
|
+
if any([
|
|
189
|
+
not {'BUY_SELL_FLAG', 'PRICE', 'SIZE'}.issubset(src.schema),
|
|
190
|
+
'UPDATE_TIME' not in src.schema and 'DELETED_TIME' not in src.schema
|
|
191
|
+
]):
|
|
192
|
+
raise TypeError(f"Aggregation `{self.NAME}` need these columns: "
|
|
193
|
+
f"BUY_SELL_FLAG, PRICE, SIZE and (UPDATE_TIME or DELETED_TIME)")
|
|
194
|
+
|
|
195
|
+
def to_ep(self, *args, **kwargs):
|
|
196
|
+
ob_ep = super().to_ep(*args, **kwargs)
|
|
197
|
+
if self.bound_symbols:
|
|
198
|
+
ob_ep = ob_ep.symbols(self.bound_symbols)
|
|
199
|
+
|
|
200
|
+
return ob_ep
|
|
201
|
+
|
|
202
|
+
def set_bound_symbols(self, bound_symbols=None):
|
|
203
|
+
if isinstance(bound_symbols, str):
|
|
204
|
+
bound_symbols = [bound_symbols]
|
|
205
|
+
|
|
206
|
+
self.bound_symbols = bound_symbols
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class ObSnapshot(_OrderBookAggregation):
|
|
210
|
+
NAME = 'OB_SNAPSHOT'
|
|
211
|
+
EP = otq.ObSnapshot
|
|
212
|
+
|
|
213
|
+
FIELDS_MAPPING = dict(_OrderBookAggregation.FIELDS_MAPPING, **{
|
|
214
|
+
'identify_source': 'IDENTIFY_SOURCE',
|
|
215
|
+
'show_full_detail': 'SHOW_FULL_DETAIL',
|
|
216
|
+
'show_only_changes': 'SHOW_ONLY_CHANGES',
|
|
217
|
+
'book_delimiters': 'BOOK_DELIMITERS',
|
|
218
|
+
'state_key_max_inactivity_sec': 'STATE_KEY_MAX_INACTIVITY_SEC',
|
|
219
|
+
'size_max_fractional_digits': 'SIZE_MAX_FRACTIONAL_DIGITS',
|
|
220
|
+
'include_market_order_ticks': 'INCLUDE_MARKET_ORDER_TICKS',
|
|
221
|
+
})
|
|
222
|
+
FIELDS_DEFAULT = dict(_OrderBookAggregation.FIELDS_DEFAULT, **{
|
|
223
|
+
'identify_source': False,
|
|
224
|
+
'show_full_detail': False,
|
|
225
|
+
'show_only_changes': False,
|
|
226
|
+
'book_delimiters': None,
|
|
227
|
+
'state_key_max_inactivity_sec': None,
|
|
228
|
+
'size_max_fractional_digits': 0,
|
|
229
|
+
'include_market_order_ticks': None,
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
def __init__(self,
|
|
233
|
+
*args,
|
|
234
|
+
identify_source: bool = False,
|
|
235
|
+
show_full_detail: bool = False,
|
|
236
|
+
show_only_changes: bool = False,
|
|
237
|
+
book_delimiters: Optional[Literal['D']] = None,
|
|
238
|
+
state_key_max_inactivity_sec: Optional[int] = None,
|
|
239
|
+
size_max_fractional_digits: int = 0,
|
|
240
|
+
include_market_order_ticks: Optional[bool] = None,
|
|
241
|
+
**kwargs):
|
|
242
|
+
self.identify_source = identify_source
|
|
243
|
+
self.show_full_detail = show_full_detail
|
|
244
|
+
self.show_only_changes = show_only_changes
|
|
245
|
+
self.book_delimiters = book_delimiters
|
|
246
|
+
self.state_key_max_inactivity_sec = state_key_max_inactivity_sec
|
|
247
|
+
self.size_max_fractional_digits = size_max_fractional_digits
|
|
248
|
+
self.include_market_order_ticks = include_market_order_ticks
|
|
249
|
+
# we don't want to set hard limit on the output of order book aggregations
|
|
250
|
+
if self.show_full_detail:
|
|
251
|
+
kwargs['all_fields'] = True
|
|
252
|
+
self._size_type = int
|
|
253
|
+
if self.size_max_fractional_digits > 0:
|
|
254
|
+
self._size_type = float # type: ignore[assignment]
|
|
255
|
+
super().__init__(*args, **kwargs)
|
|
256
|
+
|
|
257
|
+
def _param_validation(self):
|
|
258
|
+
super()._param_validation()
|
|
259
|
+
if self.include_market_order_ticks is not None:
|
|
260
|
+
if 'include_market_order_ticks' not in self.EP.Parameters.list_parameters():
|
|
261
|
+
raise ValueError("Parameter 'include_market_order_ticks' is not supported on this OneTick API version")
|
|
262
|
+
otp.compatibility.is_include_market_order_ticks_supported(
|
|
263
|
+
throw_warning=True,
|
|
264
|
+
feature_name="parameter 'include_market_order_ticks'",
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
268
|
+
schema = {
|
|
269
|
+
'PRICE': float,
|
|
270
|
+
'SIZE': self._size_type,
|
|
271
|
+
'LEVEL': int,
|
|
272
|
+
'UPDATE_TIME': otp.nsectime,
|
|
273
|
+
'BUY_SELL_FLAG': int,
|
|
274
|
+
}
|
|
275
|
+
if self.book_delimiters:
|
|
276
|
+
schema['DELIMITER'] = str
|
|
277
|
+
return schema
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
class ObSnapshotWide(ObSnapshot):
|
|
281
|
+
NAME = 'OB_SNAPSHOT_WIDE'
|
|
282
|
+
EP = otq.ObSnapshotWide
|
|
283
|
+
|
|
284
|
+
FIELDS_TO_SKIP = [
|
|
285
|
+
*ObSnapshot.FIELDS_TO_SKIP, 'side', 'identify_source', 'show_full_detail', 'show_only_changes'
|
|
286
|
+
]
|
|
287
|
+
|
|
288
|
+
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
289
|
+
schema = {
|
|
290
|
+
'BID_PRICE': float,
|
|
291
|
+
'BID_SIZE': self._size_type,
|
|
292
|
+
'BID_UPDATE_TIME': otp.nsectime,
|
|
293
|
+
'ASK_PRICE': float,
|
|
294
|
+
'ASK_SIZE': self._size_type,
|
|
295
|
+
'ASK_UPDATE_TIME': otp.nsectime,
|
|
296
|
+
'LEVEL': int,
|
|
297
|
+
}
|
|
298
|
+
if self.book_delimiters:
|
|
299
|
+
schema['DELIMITER'] = str
|
|
300
|
+
return schema
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class ObSnapshotFlat(ObSnapshot):
|
|
304
|
+
NAME = 'OB_SNAPSHOT_FLAT'
|
|
305
|
+
EP = otq.ObSnapshotFlat
|
|
306
|
+
|
|
307
|
+
FIELDS_TO_SKIP = [
|
|
308
|
+
*ObSnapshot.FIELDS_TO_SKIP,
|
|
309
|
+
'side', 'identify_source', 'show_only_changes',
|
|
310
|
+
'book_delimiters', 'max_depth_shares', 'max_depth_for_price', 'max_spread',
|
|
311
|
+
]
|
|
312
|
+
|
|
313
|
+
def validate_input_columns(self, src: 'Source'):
|
|
314
|
+
super().validate_input_columns(src)
|
|
315
|
+
if self.max_levels is None or self.max_levels < 1 or self.max_levels > 100_000:
|
|
316
|
+
raise ValueError(f"Parameter 'max_levels' must be set in aggregation `{self.NAME}`"
|
|
317
|
+
f" and must be between 1 and 100000.")
|
|
318
|
+
|
|
319
|
+
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
320
|
+
schema = {}
|
|
321
|
+
assert self.max_levels is not None
|
|
322
|
+
for level in range(1, self.max_levels + 1):
|
|
323
|
+
schema.update({
|
|
324
|
+
f'BID_PRICE{level}': float,
|
|
325
|
+
f'BID_SIZE{level}': self._size_type,
|
|
326
|
+
f'BID_UPDATE_TIME{level}': otp.nsectime,
|
|
327
|
+
f'ASK_PRICE{level}': float,
|
|
328
|
+
f'ASK_SIZE{level}': self._size_type,
|
|
329
|
+
f'ASK_UPDATE_TIME{level}': otp.nsectime,
|
|
330
|
+
})
|
|
331
|
+
return schema
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
class ObSummary(_OrderBookAggregation):
|
|
335
|
+
NAME = 'OB_SUMMARY'
|
|
336
|
+
|
|
337
|
+
# Will be set later, to prevent error while importing this module with outdated onetick
|
|
338
|
+
EP = None
|
|
339
|
+
|
|
340
|
+
FIELDS_MAPPING = dict(_OrderBookAggregation.FIELDS_MAPPING, **{
|
|
341
|
+
'min_levels': 'MIN_LEVELS',
|
|
342
|
+
'state_key_max_inactivity_sec': 'STATE_KEY_MAX_INACTIVITY_SEC',
|
|
343
|
+
'size_max_fractional_digits': 'SIZE_MAX_FRACTIONAL_DIGITS',
|
|
344
|
+
'include_market_order_ticks': 'INCLUDE_MARKET_ORDER_TICKS',
|
|
345
|
+
})
|
|
346
|
+
FIELDS_DEFAULT = dict(_OrderBookAggregation.FIELDS_DEFAULT, **{
|
|
347
|
+
'min_levels': None,
|
|
348
|
+
'state_key_max_inactivity_sec': None,
|
|
349
|
+
'size_max_fractional_digits': 0,
|
|
350
|
+
'include_market_order_ticks': None,
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
def __init__(self,
|
|
354
|
+
*args,
|
|
355
|
+
min_levels: Optional[int] = None,
|
|
356
|
+
state_key_max_inactivity_sec: Optional[int] = None,
|
|
357
|
+
size_max_fractional_digits: int = 0,
|
|
358
|
+
include_market_order_ticks: Optional[bool] = None,
|
|
359
|
+
**kwargs):
|
|
360
|
+
if is_supported_otq_ob_summary():
|
|
361
|
+
self.EP = otq.ObSummary
|
|
362
|
+
else:
|
|
363
|
+
raise RuntimeError("Used onetick installation not support onetick.query.ObSummary")
|
|
364
|
+
|
|
365
|
+
self.min_levels = min_levels
|
|
366
|
+
self.state_key_max_inactivity_sec = state_key_max_inactivity_sec
|
|
367
|
+
self.size_max_fractional_digits = size_max_fractional_digits
|
|
368
|
+
self.include_market_order_ticks = include_market_order_ticks
|
|
369
|
+
self._size_type = int
|
|
370
|
+
if self.size_max_fractional_digits > 0:
|
|
371
|
+
self._size_type = float # type: ignore[assignment]
|
|
372
|
+
super().__init__(*args, **kwargs)
|
|
373
|
+
|
|
374
|
+
def _param_validation(self):
|
|
375
|
+
super()._param_validation()
|
|
376
|
+
if self.include_market_order_ticks is not None:
|
|
377
|
+
if 'include_market_order_ticks' not in self.EP.Parameters.list_parameters():
|
|
378
|
+
raise ValueError("Parameter 'include_market_order_ticks' is not supported on this OneTick API version")
|
|
379
|
+
otp.compatibility.is_include_market_order_ticks_supported(
|
|
380
|
+
throw_warning=True,
|
|
381
|
+
feature_name="parameter 'include_market_order_ticks'",
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
385
|
+
schema = {
|
|
386
|
+
'BID_SIZE': self._size_type,
|
|
387
|
+
'BID_VWAP': float,
|
|
388
|
+
'BEST_BID_PRICE': float,
|
|
389
|
+
'WORST_BID_PRICE': float,
|
|
390
|
+
'NUM_BID_LEVELS': int,
|
|
391
|
+
'ASK_SIZE': self._size_type,
|
|
392
|
+
'ASK_VWAP': float,
|
|
393
|
+
'BEST_ASK_PRICE': float,
|
|
394
|
+
'WORST_ASK_PRICE': float,
|
|
395
|
+
'NUM_ASK_LEVELS': int,
|
|
396
|
+
}
|
|
397
|
+
return schema
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
class ObSize(_OrderBookAggregation):
|
|
401
|
+
NAME = 'OB_SIZE'
|
|
402
|
+
EP = otq.ObSize
|
|
403
|
+
|
|
404
|
+
FIELDS_MAPPING = dict(_OrderBookAggregation.FIELDS_MAPPING, **{
|
|
405
|
+
'min_levels': 'MIN_LEVELS',
|
|
406
|
+
'best_ask_price_field': 'BEST_ASK_PRICE_FIELD',
|
|
407
|
+
'best_bid_price_field': 'BEST_BID_PRICE_FIELD',
|
|
408
|
+
})
|
|
409
|
+
FIELDS_DEFAULT = dict(_OrderBookAggregation.FIELDS_DEFAULT, **{
|
|
410
|
+
'min_levels': None,
|
|
411
|
+
'best_ask_price_field': '',
|
|
412
|
+
'best_bid_price_field': '',
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
def __init__(
|
|
416
|
+
self, *args, min_levels: Optional[int] = None,
|
|
417
|
+
best_ask_price_field: Optional[Union[str, _Column]] = None,
|
|
418
|
+
best_bid_price_field: Optional[Union[str, _Column]] = None,
|
|
419
|
+
**kwargs,
|
|
420
|
+
):
|
|
421
|
+
if min_levels and not kwargs.get('max_depth_for_price'):
|
|
422
|
+
raise ValueError('`min_levels` parameter must not be set when `max_depth_for_price` not set')
|
|
423
|
+
|
|
424
|
+
self.min_levels = min_levels
|
|
425
|
+
|
|
426
|
+
if isinstance(best_ask_price_field, _Column):
|
|
427
|
+
best_ask_price_field = str(best_ask_price_field)
|
|
428
|
+
elif best_ask_price_field is None:
|
|
429
|
+
best_ask_price_field = ''
|
|
430
|
+
|
|
431
|
+
if isinstance(best_bid_price_field, _Column):
|
|
432
|
+
best_bid_price_field = str(best_bid_price_field)
|
|
433
|
+
elif best_bid_price_field is None:
|
|
434
|
+
best_bid_price_field = ''
|
|
435
|
+
|
|
436
|
+
self.best_ask_price_field = best_ask_price_field
|
|
437
|
+
self.best_bid_price_field = best_bid_price_field
|
|
438
|
+
super().__init__(*args, **kwargs)
|
|
439
|
+
|
|
440
|
+
def validate_input_columns(self, src: 'Source'):
|
|
441
|
+
super().validate_input_columns(src)
|
|
442
|
+
|
|
443
|
+
if self.best_ask_price_field and self.best_ask_price_field not in src.schema:
|
|
444
|
+
raise ValueError(
|
|
445
|
+
f'Column \'{self.best_ask_price_field}\' from `best_ask_price_field` parameter not in the schema.'
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
if self.best_bid_price_field and self.best_bid_price_field not in src.schema:
|
|
449
|
+
raise ValueError(
|
|
450
|
+
f'Column \'{self.best_bid_price_field}\' from `best_bid_price_field` parameter not in the schema.'
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
454
|
+
if self.side:
|
|
455
|
+
return {'VALUE': float}
|
|
456
|
+
|
|
457
|
+
return {
|
|
458
|
+
'ASK_VALUE': float,
|
|
459
|
+
'BID_VALUE': float,
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class ObVwap(_OrderBookAggregation):
|
|
464
|
+
NAME = 'OB_VWAP'
|
|
465
|
+
EP = otq.ObVwap
|
|
466
|
+
|
|
467
|
+
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
468
|
+
if self.side:
|
|
469
|
+
return {'VALUE': float}
|
|
470
|
+
|
|
471
|
+
return {
|
|
472
|
+
'ASK_VALUE': float,
|
|
473
|
+
'BID_VALUE': float,
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
class ObNumLevels(_OrderBookAggregation):
|
|
478
|
+
NAME = 'OB_NUM_LEVELS'
|
|
479
|
+
EP = otq.ObNumLevels
|
|
480
|
+
|
|
481
|
+
def __init__(self, *args, bucket_interval: Union[int, ott.OTPBaseTimeOffset] = 0, **kwargs):
|
|
482
|
+
if not isinstance(bucket_interval, (int, ott.OTPBaseTimeOffset)):
|
|
483
|
+
raise ValueError('Unsupported value type for `bucket_interval` parameter')
|
|
484
|
+
|
|
485
|
+
if isinstance(bucket_interval, ott.OTPBaseTimeOffset):
|
|
486
|
+
_, datepart = bucket_interval.get_offset()
|
|
487
|
+
if datepart not in {'second', 'minute', 'hour', 'day'}:
|
|
488
|
+
raise ValueError(f"Unsupported DatePart passed to bucket_interval: {datepart}")
|
|
489
|
+
|
|
490
|
+
bucket_interval = get_seconds_from_time_offset(bucket_interval)
|
|
491
|
+
|
|
492
|
+
super().__init__(*args, bucket_interval=bucket_interval, **kwargs)
|
|
493
|
+
|
|
494
|
+
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
495
|
+
if self.side:
|
|
496
|
+
return {'VALUE': float}
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
'ASK_VALUE': float,
|
|
500
|
+
'BID_VALUE': float,
|
|
501
|
+
}
|