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.
Files changed (152) hide show
  1. locator_parser/__init__.py +0 -0
  2. locator_parser/acl.py +73 -0
  3. locator_parser/actions.py +262 -0
  4. locator_parser/common.py +368 -0
  5. locator_parser/io.py +43 -0
  6. locator_parser/locator.py +150 -0
  7. onetick/__init__.py +101 -0
  8. onetick/doc_utilities/__init__.py +3 -0
  9. onetick/doc_utilities/napoleon.py +40 -0
  10. onetick/doc_utilities/ot_doctest.py +140 -0
  11. onetick/doc_utilities/snippets.py +279 -0
  12. onetick/lib/__init__.py +4 -0
  13. onetick/lib/instance.py +141 -0
  14. onetick/py/__init__.py +293 -0
  15. onetick/py/_stack_info.py +89 -0
  16. onetick/py/_version.py +2 -0
  17. onetick/py/aggregations/__init__.py +11 -0
  18. onetick/py/aggregations/_base.py +648 -0
  19. onetick/py/aggregations/_docs.py +948 -0
  20. onetick/py/aggregations/compute.py +286 -0
  21. onetick/py/aggregations/functions.py +2216 -0
  22. onetick/py/aggregations/generic.py +104 -0
  23. onetick/py/aggregations/high_low.py +80 -0
  24. onetick/py/aggregations/num_distinct.py +83 -0
  25. onetick/py/aggregations/order_book.py +501 -0
  26. onetick/py/aggregations/other.py +1014 -0
  27. onetick/py/backports.py +26 -0
  28. onetick/py/cache.py +374 -0
  29. onetick/py/callback/__init__.py +5 -0
  30. onetick/py/callback/callback.py +276 -0
  31. onetick/py/callback/callbacks.py +131 -0
  32. onetick/py/compatibility.py +798 -0
  33. onetick/py/configuration.py +771 -0
  34. onetick/py/core/__init__.py +0 -0
  35. onetick/py/core/_csv_inspector.py +93 -0
  36. onetick/py/core/_internal/__init__.py +0 -0
  37. onetick/py/core/_internal/_manually_bound_value.py +6 -0
  38. onetick/py/core/_internal/_nodes_history.py +250 -0
  39. onetick/py/core/_internal/_op_utils/__init__.py +0 -0
  40. onetick/py/core/_internal/_op_utils/every_operand.py +9 -0
  41. onetick/py/core/_internal/_op_utils/is_const.py +10 -0
  42. onetick/py/core/_internal/_per_tick_scripts/tick_list_sort_template.script +121 -0
  43. onetick/py/core/_internal/_proxy_node.py +140 -0
  44. onetick/py/core/_internal/_state_objects.py +2312 -0
  45. onetick/py/core/_internal/_state_vars.py +93 -0
  46. onetick/py/core/_source/__init__.py +0 -0
  47. onetick/py/core/_source/_symbol_param.py +95 -0
  48. onetick/py/core/_source/schema.py +97 -0
  49. onetick/py/core/_source/source_methods/__init__.py +0 -0
  50. onetick/py/core/_source/source_methods/aggregations.py +809 -0
  51. onetick/py/core/_source/source_methods/applyers.py +296 -0
  52. onetick/py/core/_source/source_methods/columns.py +141 -0
  53. onetick/py/core/_source/source_methods/data_quality.py +301 -0
  54. onetick/py/core/_source/source_methods/debugs.py +272 -0
  55. onetick/py/core/_source/source_methods/drops.py +120 -0
  56. onetick/py/core/_source/source_methods/fields.py +619 -0
  57. onetick/py/core/_source/source_methods/filters.py +1002 -0
  58. onetick/py/core/_source/source_methods/joins.py +1413 -0
  59. onetick/py/core/_source/source_methods/merges.py +605 -0
  60. onetick/py/core/_source/source_methods/misc.py +1455 -0
  61. onetick/py/core/_source/source_methods/pandases.py +155 -0
  62. onetick/py/core/_source/source_methods/renames.py +356 -0
  63. onetick/py/core/_source/source_methods/sorts.py +183 -0
  64. onetick/py/core/_source/source_methods/switches.py +142 -0
  65. onetick/py/core/_source/source_methods/symbols.py +117 -0
  66. onetick/py/core/_source/source_methods/times.py +627 -0
  67. onetick/py/core/_source/source_methods/writes.py +986 -0
  68. onetick/py/core/_source/symbol.py +205 -0
  69. onetick/py/core/_source/tmp_otq.py +222 -0
  70. onetick/py/core/column.py +209 -0
  71. onetick/py/core/column_operations/__init__.py +0 -0
  72. onetick/py/core/column_operations/_methods/__init__.py +4 -0
  73. onetick/py/core/column_operations/_methods/_internal.py +28 -0
  74. onetick/py/core/column_operations/_methods/conversions.py +216 -0
  75. onetick/py/core/column_operations/_methods/methods.py +292 -0
  76. onetick/py/core/column_operations/_methods/op_types.py +160 -0
  77. onetick/py/core/column_operations/accessors/__init__.py +0 -0
  78. onetick/py/core/column_operations/accessors/_accessor.py +28 -0
  79. onetick/py/core/column_operations/accessors/decimal_accessor.py +104 -0
  80. onetick/py/core/column_operations/accessors/dt_accessor.py +537 -0
  81. onetick/py/core/column_operations/accessors/float_accessor.py +184 -0
  82. onetick/py/core/column_operations/accessors/str_accessor.py +1367 -0
  83. onetick/py/core/column_operations/base.py +1121 -0
  84. onetick/py/core/cut_builder.py +150 -0
  85. onetick/py/core/db_constants.py +20 -0
  86. onetick/py/core/eval_query.py +245 -0
  87. onetick/py/core/lambda_object.py +441 -0
  88. onetick/py/core/multi_output_source.py +232 -0
  89. onetick/py/core/per_tick_script.py +2256 -0
  90. onetick/py/core/query_inspector.py +464 -0
  91. onetick/py/core/source.py +1744 -0
  92. onetick/py/db/__init__.py +2 -0
  93. onetick/py/db/_inspection.py +1128 -0
  94. onetick/py/db/db.py +1327 -0
  95. onetick/py/db/utils.py +64 -0
  96. onetick/py/docs/__init__.py +0 -0
  97. onetick/py/docs/docstring_parser.py +112 -0
  98. onetick/py/docs/utils.py +81 -0
  99. onetick/py/functions.py +2398 -0
  100. onetick/py/license.py +190 -0
  101. onetick/py/log.py +88 -0
  102. onetick/py/math.py +935 -0
  103. onetick/py/misc.py +470 -0
  104. onetick/py/oqd/__init__.py +22 -0
  105. onetick/py/oqd/eps.py +1195 -0
  106. onetick/py/oqd/sources.py +325 -0
  107. onetick/py/otq.py +216 -0
  108. onetick/py/pyomd_mock.py +47 -0
  109. onetick/py/run.py +916 -0
  110. onetick/py/servers.py +173 -0
  111. onetick/py/session.py +1347 -0
  112. onetick/py/sources/__init__.py +19 -0
  113. onetick/py/sources/cache.py +167 -0
  114. onetick/py/sources/common.py +128 -0
  115. onetick/py/sources/csv.py +642 -0
  116. onetick/py/sources/custom.py +85 -0
  117. onetick/py/sources/data_file.py +305 -0
  118. onetick/py/sources/data_source.py +1045 -0
  119. onetick/py/sources/empty.py +94 -0
  120. onetick/py/sources/odbc.py +337 -0
  121. onetick/py/sources/order_book.py +271 -0
  122. onetick/py/sources/parquet.py +168 -0
  123. onetick/py/sources/pit.py +191 -0
  124. onetick/py/sources/query.py +495 -0
  125. onetick/py/sources/snapshots.py +419 -0
  126. onetick/py/sources/split_query_output_by_symbol.py +198 -0
  127. onetick/py/sources/symbology_mapping.py +123 -0
  128. onetick/py/sources/symbols.py +374 -0
  129. onetick/py/sources/ticks.py +825 -0
  130. onetick/py/sql.py +70 -0
  131. onetick/py/state.py +251 -0
  132. onetick/py/types.py +2131 -0
  133. onetick/py/utils/__init__.py +70 -0
  134. onetick/py/utils/acl.py +93 -0
  135. onetick/py/utils/config.py +186 -0
  136. onetick/py/utils/default.py +49 -0
  137. onetick/py/utils/file.py +38 -0
  138. onetick/py/utils/helpers.py +76 -0
  139. onetick/py/utils/locator.py +94 -0
  140. onetick/py/utils/perf.py +498 -0
  141. onetick/py/utils/query.py +49 -0
  142. onetick/py/utils/render.py +1374 -0
  143. onetick/py/utils/script.py +244 -0
  144. onetick/py/utils/temp.py +471 -0
  145. onetick/py/utils/types.py +120 -0
  146. onetick/py/utils/tz.py +84 -0
  147. onetick_py-1.177.0.dist-info/METADATA +137 -0
  148. onetick_py-1.177.0.dist-info/RECORD +152 -0
  149. onetick_py-1.177.0.dist-info/WHEEL +5 -0
  150. onetick_py-1.177.0.dist-info/entry_points.txt +2 -0
  151. onetick_py-1.177.0.dist-info/licenses/LICENSE +21 -0
  152. 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
+ }