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,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))
|