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,301 @@
1
+ import typing
2
+ from typing import TYPE_CHECKING, Optional, Union
3
+
4
+ from onetick.py.otq import otq
5
+ from onetick.py.core.column_operations.base import _Operation
6
+ from onetick.py.backports import Literal
7
+ from .misc import inplace_operation
8
+
9
+ if TYPE_CHECKING:
10
+ from onetick.py.core.source import Source
11
+
12
+
13
+ DATA_QUALITY_EVENTS = Literal[
14
+ 'COLLECTOR_FAILURE',
15
+ 'EMPTY',
16
+ 'MISSING',
17
+ 'MOUNT_BAD',
18
+ 'OK',
19
+ 'PATCHED',
20
+ 'QUALITY_DELAY_STITCHING_WITH_RT',
21
+ 'QUALITY_OK_STITCHING_WITH_RT',
22
+ 'STALE',
23
+ ]
24
+
25
+
26
+ @inplace_operation
27
+ def show_data_quality(self: 'Source', inplace=False) -> Optional['Source']:
28
+ """
29
+ This method shows data quality events within the interval of the query.
30
+
31
+ Parameters
32
+ ----------
33
+ inplace: bool
34
+ The flag controls whether operation should be applied inplace or not.
35
+ If ``inplace=True``, then it returns nothing.
36
+ Otherwise, method returns a new modified object.
37
+
38
+ See also
39
+ --------
40
+ | **SHOW_DATA_QUALITY** OneTick event processor
41
+ | :py:meth:`insert_data_quality_event`
42
+ | :py:meth:`intercept_data_quality`
43
+
44
+ Returns
45
+ -------
46
+ :class:`Source` or ``None``
47
+
48
+ Examples
49
+ --------
50
+
51
+ By default data quality events are not showed, use this method to see them:
52
+
53
+ >>> data = otp.Ticks({'A': [1, 2, 3]})
54
+ >>> data = data.insert_data_quality_event('OK')
55
+ >>> data = data.show_data_quality()
56
+ >>> otp.run(data)
57
+ Time DATA_QUALITY_TYPE DATA_QUALITY_NAME
58
+ 0 2003-12-01 00:00:00.000 0 OK
59
+ 1 2003-12-01 00:00:00.001 0 OK
60
+ 2 2003-12-01 00:00:00.002 0 OK
61
+ """
62
+
63
+ self.sink(
64
+ otq.ShowDataQuality()
65
+ )
66
+ self.schema.set(**{'DATA_QUALITY_TYPE': int, 'DATA_QUALITY_NAME': str})
67
+ return self
68
+
69
+
70
+ @inplace_operation
71
+ def insert_data_quality_event(
72
+ self: 'Source',
73
+ data_quality: DATA_QUALITY_EVENTS,
74
+ where: Optional[Union[str, _Operation]] = None,
75
+ insert_before: bool = True,
76
+ inplace=False,
77
+ ) -> Optional['Source']:
78
+ """
79
+ Insert data quality events into the data flow.
80
+
81
+ Parameters
82
+ ----------
83
+ data_quality: str
84
+ The type of data quality event.
85
+ Must be one of the supported data quality event types.
86
+ where: str or :class:`Operation`
87
+ Specifies a criterion for the selection of ticks whose arrival results in generation of a data quality event.
88
+ If this expression returns True, a data quality event will be inserted into a time series.
89
+ The expression can also be empty (default), in which case each input tick generates a data quality event.
90
+ insert_before: bool
91
+ If True (default),
92
+ generated data quality event tick will be inserted before the input tick that triggered its creation,
93
+ otherwise generated data quality event will be inserted after that input tick.
94
+ inplace: bool
95
+ The flag controls whether operation should be applied inplace or not.
96
+ If ``inplace=True``, then it returns nothing.
97
+ Otherwise, method returns a new modified object.
98
+
99
+ See also
100
+ --------
101
+ | **INSERT_DATA_QUALITY_EVENT** OneTick event processor
102
+ | :py:meth:`show_data_quality`
103
+ | :py:meth:`intercept_data_quality`
104
+
105
+ Returns
106
+ -------
107
+ :class:`Source` or ``None``
108
+
109
+ Examples
110
+ --------
111
+ Insert OK data quality event before each tick:
112
+
113
+ >>> data = otp.Ticks({'A': [1, 2, 3]})
114
+ >>> data = data.insert_data_quality_event('OK')
115
+ >>> otp.run(data)
116
+ Time A
117
+ 0 2003-12-01 00:00:00.000 1
118
+ 1 2003-12-01 00:00:00.001 2
119
+ 2 2003-12-01 00:00:00.002 3
120
+
121
+ By default data quality events are not showed,
122
+ use :py:meth:`show_data_quality` method to see them:
123
+
124
+ >>> data = otp.Ticks({'A': [1, 2, 3]})
125
+ >>> data = data.insert_data_quality_event('OK')
126
+ >>> data = data.show_data_quality()
127
+ >>> otp.run(data)
128
+ Time DATA_QUALITY_TYPE DATA_QUALITY_NAME
129
+ 0 2003-12-01 00:00:00.000 0 OK
130
+ 1 2003-12-01 00:00:00.001 0 OK
131
+ 2 2003-12-01 00:00:00.002 0 OK
132
+
133
+ Use ``where`` parameter to specify the condition when to insert ticks:
134
+
135
+ >>> data = otp.Ticks({'SIZE': [1, 200, 3]})
136
+ >>> data = data.insert_data_quality_event('MISSING', where=data['SIZE'] > 100)
137
+ >>> data = data.show_data_quality()
138
+ >>> otp.run(data)
139
+ Time DATA_QUALITY_TYPE DATA_QUALITY_NAME
140
+ 0 2003-12-01 00:00:00.001 2 MISSING
141
+ """
142
+ if data_quality not in typing.get_args(DATA_QUALITY_EVENTS):
143
+ raise ValueError(f"Parameter 'data_quality' doesn't support value: {data_quality}")
144
+
145
+ self.sink(
146
+ otq.InsertDataQualityEvent(
147
+ data_quality=data_quality,
148
+ where=str(where) if where is not None else '',
149
+ insert_before=insert_before,
150
+ )
151
+ )
152
+
153
+ return self
154
+
155
+
156
+ @inplace_operation
157
+ def intercept_data_quality(self: 'Source', inplace=False) -> Optional['Source']:
158
+ """
159
+ This method removes data quality messages, thus preventing them from delivery to the client application.
160
+
161
+ Parameters
162
+ ----------
163
+ inplace: bool
164
+ The flag controls whether operation should be applied inplace or not.
165
+ If ``inplace=True``, then it returns nothing.
166
+ Otherwise, method returns a new modified object.
167
+
168
+ See also
169
+ --------
170
+ | **INTERCEPT_DATA_QUALITY** OneTick event processor
171
+ | :py:meth:`insert_data_quality_event`
172
+ | :py:meth:`show_data_quality`
173
+
174
+ Returns
175
+ -------
176
+ :class:`Source` or ``None``
177
+
178
+ Examples
179
+ --------
180
+
181
+ By default data quality events are not showed, use this method to see them:
182
+
183
+ >>> data = otp.Ticks({'A': [1, 2, 3]})
184
+ >>> data = data.insert_data_quality_event('OK')
185
+ >>> data = data.show_data_quality()
186
+ >>> otp.run(data)
187
+ Time DATA_QUALITY_TYPE DATA_QUALITY_NAME
188
+ 0 2003-12-01 00:00:00.000 0 OK
189
+ 1 2003-12-01 00:00:00.001 0 OK
190
+ 2 2003-12-01 00:00:00.002 0 OK
191
+
192
+ Intercepting data quality events will remove them from the data flow:
193
+
194
+ >>> data = otp.Ticks({'A': [1, 2, 3]})
195
+ >>> data = data.insert_data_quality_event('OK')
196
+ >>> data = data.intercept_data_quality()
197
+ >>> data = data.show_data_quality()
198
+ >>> otp.run(data) # doctest: +ELLIPSIS
199
+ Empty DataFrame
200
+ ...
201
+ """
202
+ self.sink(
203
+ otq.InterceptDataQuality()
204
+ )
205
+ return self
206
+
207
+
208
+ @inplace_operation
209
+ def show_symbol_errors(self: 'Source', inplace=False) -> Optional['Source']:
210
+ """
211
+ This method propagates a tick representing per-symbol error.
212
+
213
+ Parameters
214
+ ----------
215
+ inplace: bool
216
+ The flag controls whether operation should be applied inplace or not.
217
+ If ``inplace=True``, then it returns nothing.
218
+ Otherwise, method returns a new modified object.
219
+
220
+ See also
221
+ --------
222
+ | **SHOW_SYMBOL_ERRORS** OneTick event processor
223
+ | :py:meth:`intercept_symbol_errors`
224
+ | :py:meth:`onetick.py.Source.throw`
225
+
226
+ Returns
227
+ -------
228
+ :class:`Source` or ``None``
229
+
230
+ Examples
231
+ --------
232
+
233
+ By default symbol errors are not showed, use this method to see them:
234
+
235
+ >>> data = otp.Ticks({'A': [1, 2, 3]})
236
+ >>> data = data.throw('WRONG', scope='symbol')
237
+ >>> data = data.show_symbol_errors()
238
+ >>> otp.run(data)
239
+ Time ERROR_CODE ERROR_MESSAGE
240
+ 0 2003-12-01 1 WRONG
241
+ 1 2003-12-01 1 WRONG
242
+ 2 2003-12-01 1 WRONG
243
+ """
244
+
245
+ self.sink(
246
+ otq.ShowSymbolErrors()
247
+ )
248
+ self.schema.set(**{'ERROR_CODE': int, 'ERROR_MESSAGE': str})
249
+ return self
250
+
251
+
252
+ @inplace_operation
253
+ def intercept_symbol_errors(self: 'Source', inplace=False) -> Optional['Source']:
254
+ """
255
+ This method removes removes per-symbol errors, thus preventing them from delivery to the client application.
256
+
257
+ Parameters
258
+ ----------
259
+ inplace: bool
260
+ The flag controls whether operation should be applied inplace or not.
261
+ If ``inplace=True``, then it returns nothing.
262
+ Otherwise, method returns a new modified object.
263
+
264
+ See also
265
+ --------
266
+ | **INTERCEPT_SYMBOL_ERRORS** OneTick event processor
267
+ | :py:meth:`show_symbol_errors`
268
+ | :py:meth:`onetick.py.Source.throw`
269
+
270
+ Returns
271
+ -------
272
+ :class:`Source` or ``None``
273
+
274
+ Examples
275
+ --------
276
+
277
+ By default data quality events are not showed, use this method to see them:
278
+
279
+ >>> data = otp.Ticks({'A': [1, 2, 3]})
280
+ >>> data = data.throw('WRONG', scope='symbol')
281
+ >>> data = data.show_symbol_errors()
282
+ >>> otp.run(data)
283
+ Time ERROR_CODE ERROR_MESSAGE
284
+ 0 2003-12-01 1 WRONG
285
+ 1 2003-12-01 1 WRONG
286
+ 2 2003-12-01 1 WRONG
287
+
288
+ Intercepting data quality events will remove them from the data flow:
289
+
290
+ >>> data = otp.Ticks({'A': [1, 2, 3]})
291
+ >>> data = data.throw('WRONG', scope='symbol')
292
+ >>> data = data.intercept_symbol_errors()
293
+ >>> data = data.show_symbol_errors()
294
+ >>> otp.run(data) # doctest: +ELLIPSIS
295
+ Empty DataFrame
296
+ ...
297
+ """
298
+ self.sink(
299
+ otq.InterceptSymbolErrors()
300
+ )
301
+ return self
@@ -0,0 +1,272 @@
1
+ from typing import TYPE_CHECKING, Callable, List, Optional, Tuple, Union
2
+
3
+ from onetick import py as otp
4
+ from onetick.py import configuration
5
+ from onetick.py.otq import otq
6
+
7
+ from .misc import inplace_operation
8
+
9
+ if TYPE_CHECKING:
10
+ from onetick.py.core.source import Source
11
+
12
+
13
+ @inplace_operation
14
+ def throw(
15
+ self: 'Source', message='', where=1, scope='query', error_code=1, throw_before_query_execution=False, inplace=False
16
+ ) -> Optional['Source']:
17
+ """
18
+ Propagates error or warning or throws an exception (depending on ``scope`` parameter)
19
+ when condition provided by ``where`` parameter evaluates to True.
20
+
21
+ Throwing an exception will abort query execution,
22
+ propagating error will stop tick propagation and
23
+ propagating warning will not change the data processing.
24
+
25
+ Parameters
26
+ ----------
27
+ message: str or Operation
28
+ Message that will be thrown in exception or returned in error message.
29
+ where: Operation
30
+ Logical expression that specifies condition when exception or error will be thrown.
31
+ scope: 'query' or 'symbol'
32
+ 'query' will throw an exception and 'symbol' will propagate an error or warning
33
+ depending on ``error_code`` parameter.
34
+ error_code: int
35
+ When ``scope='symbol'``, values from interval ``[1, 500]`` indicate warnings
36
+ and values from interval ``[1500, 2000]`` indicate errors.
37
+ Note that tick propagation will not stop when warning is raised,
38
+ and will stop when error is raised.
39
+
40
+ This parameter is not used when ``scope='query'``.
41
+ throw_before_query_execution: bool
42
+ If set to ``True``, the exception will be thrown before the execution of the query.
43
+ This option is intended for supplying placeholder queries that must always throw.
44
+ inplace: bool
45
+ The flag controls whether operation should be applied inplace or not.
46
+ If ``inplace=True``, then it returns nothing.
47
+ Otherwise method returns a new modified object.
48
+
49
+ See also
50
+ --------
51
+ **THROW** OneTick event processor
52
+
53
+ Returns
54
+ -------
55
+ :class:`Source` or ``None``
56
+
57
+ Examples
58
+ --------
59
+
60
+ By default, this method will throw an exception on the first tick with empty message:
61
+
62
+ >>> t = otp.Tick(A=1)
63
+ >>> t = t.throw()
64
+ >>> otp.run(t) # doctest: +ELLIPSIS
65
+ Traceback (most recent call last):
66
+ ...
67
+ Exception: ...: In THROW: ...
68
+ ...
69
+
70
+ You can specify exception message and condition (note that exception now is raised on second tick):
71
+
72
+ >>> t = otp.Ticks(A=[1, 2])
73
+ >>> t = t.throw(message='A is ' + t['A'].apply(str), where=(t['A']==2))
74
+ >>> otp.run(t) # doctest: +ELLIPSIS
75
+ Traceback (most recent call last):
76
+ ...
77
+ Exception: ...: In THROW: A is 2. ...
78
+ ...
79
+
80
+ Note that exception will not be thrown if there are no ticks:
81
+
82
+ >>> t = otp.Empty()
83
+ >>> t = t.throw()
84
+ >>> otp.run(t)
85
+ Empty DataFrame
86
+ Columns: []
87
+ Index: []
88
+
89
+ If you need exception to be thrown always, you can use ``throw_before_query_execution`` parameter:
90
+
91
+ >>> t = otp.Empty()
92
+ >>> t = t.throw(throw_before_query_execution=True)
93
+ >>> otp.run(t) # doctest: +ELLIPSIS
94
+ Traceback (most recent call last):
95
+ ...
96
+ Exception: ...: In THROW: ...
97
+
98
+ You can throw OneTick errors and warnings instead of exceptions.
99
+ Raising error codes from 1 to 500 indicates warnings.
100
+ Raising error codes from 1500 to 2000 indicates errors.
101
+ Tick propagation stops only when error is raised.
102
+
103
+ >>> t = otp.Ticks(A=[1, 2, 3, 4])
104
+ >>> t = t.throw(message='warning A=1', scope='symbol', error_code=2, where=(t['A']==1))
105
+ >>> t = t.throw(message='error A=3', scope='symbol', error_code=1502, where=(t['A']==3))
106
+ >>> otp.run(t)
107
+ Time A
108
+ 0 2003-12-01 00:00:00.000 1
109
+ 1 2003-12-01 00:00:00.001 2
110
+
111
+ Right now the only supported interface to get errors and warnings
112
+ is via ``map`` output structure and its methods:
113
+
114
+ >>> otp.run(t, symbols='AAPL', output_structure='map').output('AAPL').error
115
+ [(2, 'warning A=1'), (1502, 'error A=3')]
116
+ """
117
+ if isinstance(message, str):
118
+ treat_message_as_per_tick_expr = False
119
+ else:
120
+ treat_message_as_per_tick_expr = True
121
+ if scope not in {'query', 'symbol'}:
122
+ raise ValueError("Parameter 'scope' can only be set to 'query' or 'symbol'")
123
+ if not (1 <= error_code <= 500 or 1500 <= error_code <= 2000):
124
+ raise ValueError(
125
+ "Parameter 'error_code' can only take values "
126
+ "from interval [1, 500] for warnings and from interval [1500, 2000] for errors"
127
+ )
128
+ self.sink(
129
+ otq.Throw(
130
+ message=str(message),
131
+ treat_message_as_per_tick_expr=treat_message_as_per_tick_expr,
132
+ where=str(where),
133
+ scope=scope.upper(),
134
+ error_code=error_code,
135
+ throw_before_query_execution=throw_before_query_execution,
136
+ )
137
+ )
138
+ return self
139
+
140
+
141
+ @inplace_operation
142
+ def logf(
143
+ self: 'Source', message: str, severity: str, *args, where: Optional['otp.Operation'] = None, inplace: bool = False
144
+ ) -> Optional['Source']:
145
+ """
146
+ Call built-in OneTick ``LOGF`` function.
147
+
148
+ Parameters
149
+ ----------
150
+ message: str
151
+ Log message/format string. The underlying formatting engine is the Boost Format Library:
152
+ https://www.boost.org/doc/libs/1_53_0/libs/format/doc/format.html
153
+
154
+ severity: str
155
+ Severity of message. Supported values: ``ERROR``, ``WARNING`` and ``INFO``.
156
+
157
+ where: Operation
158
+ A condition that allows to filter ticks to call ``LOGF`` on. ``None`` for no filtering.
159
+
160
+ inplace: bool
161
+ The flag controls whether operation should be applied inplace or not.
162
+ If ``inplace=True``, then it returns nothing. Otherwise method returns a new modified
163
+ object.
164
+
165
+ args: list
166
+ Parameters for format string (optional).
167
+
168
+ Returns
169
+ -------
170
+ :class:`Source`
171
+
172
+ Examples
173
+ --------
174
+ >>> data = otp.Ticks(PRICE=[97, 99, 103])
175
+ >>> data = data.logf("PRICE (%1%) is higher than 100", "WARNING", data["PRICE"], where=(data["PRICE"] > 100))
176
+ """
177
+
178
+ where_in_tick = where if where is not None else True
179
+
180
+ def per_tick_script(tick):
181
+ if where_in_tick:
182
+ otp.logf(message, severity, *args)
183
+
184
+ return self.script(per_tick_script, inplace=inplace)
185
+
186
+
187
+ def dump(
188
+ self: 'Source',
189
+ label: Optional[str] = None,
190
+ where: Optional['otp.Operation'] = None,
191
+ columns: Union[str, Tuple[str], List[str], None] = None,
192
+ callback: Optional[Callable] = None,
193
+ ):
194
+ """
195
+ Dumps the ``columns`` from ticks into std::out in runtime if they fit the ``where`` condition.
196
+ Every dump has a corresponding header that always includes the TIMESTAMP field. Other fields
197
+ could be configured using the ``columns`` parameter. A header could be augmented with a ``label`` parameter;
198
+ this label is an addition column that helps to distinguish ticks
199
+ from multiple dumps with the same schema, because ticks from different dumps could be mixed.
200
+ It might happen because of the OneTick multithreading, and there is the operating system
201
+ buffer between the OneTick and the actual output.
202
+
203
+ This method is helpful for debugging.
204
+
205
+ Parameters
206
+ ----------
207
+ label: str
208
+ A label for a dump. It adds a special column **_OUT_LABEL_** for all ticks and set to the
209
+ specified value. It helps to distinguish ticks from multiple dumps, because actual
210
+ output could contain mixed ticks due the concurrency. ``None`` means no label.
211
+ where: Operation
212
+ A condition that allows to filter ticks to dump. ``None`` means no filtering.
213
+ columns: str, tupel or list
214
+ List of columns that should be in the output. ``None`` means dump all columns.
215
+ callback : callable
216
+ Callable, which preprocess source before printing.
217
+
218
+ See also
219
+ --------
220
+ **WRITE_TEXT** OneTick event processor
221
+
222
+ Examples
223
+ --------
224
+ >>> # OTdirective: skip-snippet:;
225
+ >>> data.dump(label='Debug point', where=data['PRICE'] > 99.3, columns=['PRICE', 'QTY']) # doctest: +SKIP
226
+ >>> data.dump(columns="X", callback=lambda x: x.first(), label="first") # doctest: +SKIP
227
+ """
228
+
229
+ self_c = self.copy()
230
+ if callback:
231
+ self_c = callback(self_c)
232
+ if where is not None: # can't be simplified because the _Operation overrides __bool__
233
+ self_c, _ = self_c[(where)]
234
+ if columns:
235
+ self_c = self_c[columns if isinstance(columns, (list, tuple)) else [columns]]
236
+ if label:
237
+ self_c['_OUT_LABEL_'] = label
238
+
239
+ self_c.write_text(
240
+ formats_of_fields={'TIMESTAMP': f'%|{configuration.config.tz}|%d-%m-%Y %H:%M:%S.%J'},
241
+ prepend_timestamp=True,
242
+ prepend_symbol_name=False,
243
+ propagate_ticks=True,
244
+ inplace=True,
245
+ )
246
+
247
+ # print <no data> in case there are 0 ticks
248
+ if hasattr(otq, 'InsertAtEnd'):
249
+ self_c.sink(otq.InsertAtEnd(delimiter_name='AT_END'))
250
+ self_c.schema['AT_END'] = int
251
+ self_c.state_vars['COUNT'] = otp.state.var(0, scope='branch')
252
+ self_c.state_vars['COUNT'] += 1
253
+ self_c, _ = self_c[(self_c['AT_END'] == 1) & (self_c.state_vars['COUNT'] == 1)]
254
+ self_c['NO_DATA'] = '<no data>'
255
+ self_c = self_c[['NO_DATA']]
256
+ self_c.write_text(output_headers=False, prepend_timestamp=False, prepend_symbol_name=False,
257
+ propagate_ticks=False, inplace=True)
258
+
259
+ # Do not propagate ticks then, because we want just to write them into
260
+ # the std::out. We have to do that, because otherwise these ticks would
261
+ # go to a query output, that would mess real output.
262
+ self_c, _ = self_c[self_c['Time'] != self_c['Time']] # NOSONAR
263
+
264
+ # We have to merge the branch back to the main branch even that these
265
+ # branch does not generate ticks, because we do not introduce one more
266
+ # output point, because the OneTick would add it to the final output
267
+ # datastructure.
268
+ self.sink(otq.Merge(identify_input_ts=False))
269
+
270
+ self.source(self_c.node().copy_graph()) # NOSONAR
271
+ self.node().add_rules(self_c.node().copy_rules())
272
+ self._merge_tmp_otq(self_c)
@@ -0,0 +1,120 @@
1
+ from typing import TYPE_CHECKING, Any, List, Optional
2
+
3
+ from onetick.py.otq import otq
4
+
5
+ from .misc import inplace_operation
6
+
7
+ if TYPE_CHECKING:
8
+ from onetick.py.core.source import Source
9
+
10
+
11
+ @inplace_operation
12
+ def drop(self: 'Source', columns: List[Any], inplace=False) -> Optional['Source']:
13
+ r"""
14
+ Remove a list of columns specified by names or regular expressions from the Source.
15
+
16
+ If a column with such name wasn't found the error will be raised,
17
+ if the regex was specified and there aren't any matched columns, do nothing.
18
+
19
+ Regex is any string containing any of characters ***+?\:[]{}()**,
20
+ dot is a valid symbol for OneTick identifier,
21
+ so **a.b** will be passed to OneTick as an identifier,
22
+ if you want specify such regex use parenthesis - **(a.b)**
23
+
24
+ If a string without special characters or :py:class:`~onetick.py.Column` object is specified in the list,
25
+ then it is assumed that this is a literal name of the column, not regular expression.
26
+
27
+ Parameters
28
+ ----------
29
+ columns : str, Column or list of them
30
+ Column(s) to remove. You could specify a regex or collection of regexes, in such case columns with
31
+ match names will be deleted.
32
+ inplace: bool
33
+ A flag controls whether operation should be applied inplace.
34
+ If inplace=True, then it returns nothing. Otherwise method
35
+ returns a new modified object.
36
+
37
+ Returns
38
+ ----------
39
+ :class:`Source` or ``None``
40
+
41
+ See Also
42
+ --------
43
+ **PASSTHROUGH** OneTick event processor
44
+
45
+ Examples
46
+ --------
47
+
48
+ Drop a single field:
49
+
50
+ >>> data = otp.Ticks(X1=[1, 2, 3],
51
+ ... X2=[3, 2, 1],
52
+ ... A1=["A", "A", "A"])
53
+ >>> data = data.drop("X1") # OTdirective: snippet-name: Arrange.drop.one field;
54
+ >>> otp.run(data)
55
+ Time X2 A1
56
+ 0 2003-12-01 00:00:00.000 3 A
57
+ 1 2003-12-01 00:00:00.001 2 A
58
+ 2 2003-12-01 00:00:00.002 1 A
59
+
60
+ Regexes also could be specified in such case all matched columns will be deleted:
61
+
62
+ >>> data = otp.Ticks(X1=[1, 2, 3],
63
+ ... X2=[3, 2, 1],
64
+ ... A1=["A", "A", "A"])
65
+ >>> data = data.drop(r"X\d+") # OTdirective: snippet-name: Arrange.drop.regex;
66
+ >>> otp.run(data)
67
+ Time A1
68
+ 0 2003-12-01 00:00:00.000 A
69
+ 1 2003-12-01 00:00:00.001 A
70
+ 2 2003-12-01 00:00:00.002 A
71
+
72
+ Both column names and regular expressions can be specified at the same time:
73
+
74
+ >>> # OTdirective: snippet-name: Arrange.drop.multiple;
75
+ >>> data = otp.Ticks(X1=[1, 2, 3],
76
+ ... X2=[3, 2, 1],
77
+ ... Y1=[1, 2, 3],
78
+ ... Y2=[3, 2, 1],
79
+ ... Y11=["a", "b", "c"],
80
+ ... Y22=["A", "A", "A"])
81
+ >>> data = data.drop([r"X\d+", "Y1", data["Y2"]])
82
+ >>> otp.run(data)
83
+ Time Y11 Y22
84
+ 0 2003-12-01 00:00:00.000 a A
85
+ 1 2003-12-01 00:00:00.001 b A
86
+ 2 2003-12-01 00:00:00.002 c A
87
+
88
+ **a.b** will be passed to OneTick as an identifier,
89
+ if you want specify such regex use parenthesis - **(a.b)**:
90
+
91
+ >>> data = otp.Ticks({"COLUMN.A": [1, 2, 3], "COLUMN1A": [3, 2, 1],
92
+ ... "COLUMN1B": ["a", "b", "c"], "COLUMN2A": ["c", "b", "a"]})
93
+ >>> data = data.drop("COLUMN.A") # OTdirective: skip-snippet:;
94
+ >>> otp.run(data)
95
+ Time COLUMN1A COLUMN1B COLUMN2A
96
+ 0 2003-12-01 00:00:00.000 3 a c
97
+ 1 2003-12-01 00:00:00.001 2 b b
98
+ 2 2003-12-01 00:00:00.002 1 c a
99
+
100
+ >>> data = otp.Ticks({"COLUMN.A": [1, 2, 3], "COLUMN1A": [3, 2, 1],
101
+ ... "COLUMN1B": ["a", "b", "c"], "COLUMN2A": ["c", "b", "a"]})
102
+ >>> data = data.drop("(COLUMN.A)") # OTdirective: skip-snippet:;
103
+ >>> otp.run(data)
104
+ Time COLUMN1B
105
+ 0 2003-12-01 00:00:00.000 a
106
+ 1 2003-12-01 00:00:00.001 b
107
+ 2 2003-12-01 00:00:00.002 c
108
+ """
109
+ self.__delitem__(columns)
110
+ return self
111
+
112
+
113
+ def __delitem__(self: 'Source', obj):
114
+ if isinstance(obj, (list, tuple)):
115
+ objs = obj
116
+ else:
117
+ objs = (obj,)
118
+
119
+ items_to_passthrough, regex = self._columns_names_regex(objs, drop=True)
120
+ self.sink(otq.Passthrough(drop_fields=True, fields=",".join(items_to_passthrough), use_regex=regex))