onetick-py 1.177.0__tar.gz → 1.179.0__tar.gz
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.
- {onetick_py-1.177.0/src/onetick_py.egg-info → onetick_py-1.179.0}/PKG-INFO +2 -1
- {onetick_py-1.177.0 → onetick_py-1.179.0}/pyproject.toml +1 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/setup.py +1 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/__init__.py +1 -1
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/_version.py +1 -1
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/compatibility.py +81 -18
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/misc.py +73 -13
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/tmp_otq.py +8 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/source.py +25 -3
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/db/_inspection.py +113 -50
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/oqd/sources.py +22 -8
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/run.py +9 -5
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/__init__.py +1 -0
- onetick_py-1.179.0/src/onetick/py/sources/dataframe.py +370 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/symbols.py +4 -6
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/ticks.py +10 -2
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/types.py +36 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/__init__.py +1 -0
- onetick_py-1.179.0/src/onetick/py/utils/debug.py +17 -0
- onetick_py-1.179.0/src/onetick/py/utils/render_cli.py +88 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0/src/onetick_py.egg-info}/PKG-INFO +2 -1
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/SOURCES.txt +3 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/entry_points.txt +1 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/LICENSE +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/README.md +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/requirements.strict.txt +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/requirements.txt +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/setup.cfg +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/acl.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/actions.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/common.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/io.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/locator_parser/locator.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/doc_utilities/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/doc_utilities/napoleon.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/doc_utilities/ot_doctest.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/doc_utilities/snippets.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/lib/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/lib/instance.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/_stack_info.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/_base.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/_docs.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/compute.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/functions.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/generic.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/high_low.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/num_distinct.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/order_book.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/aggregations/other.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/backports.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/cache.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/callback/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/callback/callback.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/callback/callbacks.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/configuration.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_csv_inspector.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_manually_bound_value.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_nodes_history.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_op_utils/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_op_utils/every_operand.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_op_utils/is_const.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_per_tick_scripts/tick_list_sort_template.script +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_proxy_node.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_state_objects.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_internal/_state_vars.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/_symbol_param.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/schema.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/aggregations.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/applyers.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/columns.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/data_quality.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/debugs.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/drops.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/fields.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/filters.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/joins.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/merges.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/pandases.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/renames.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/sorts.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/switches.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/symbols.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/times.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/writes.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/symbol.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/_internal.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/conversions.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/methods.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/_methods/op_types.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/_accessor.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/decimal_accessor.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/dt_accessor.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/float_accessor.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/accessors/str_accessor.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/column_operations/base.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/cut_builder.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/db_constants.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/eval_query.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/lambda_object.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/multi_output_source.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/per_tick_script.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/query_inspector.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/db/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/db/db.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/db/utils.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/docs/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/docs/docstring_parser.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/docs/utils.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/functions.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/license.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/log.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/math.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/misc.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/oqd/__init__.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/oqd/eps.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/otq.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/pyomd_mock.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/servers.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/session.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/cache.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/common.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/csv.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/custom.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/data_file.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/data_source.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/empty.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/odbc.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/order_book.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/parquet.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/pit.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/query.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/snapshots.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/split_query_output_by_symbol.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sources/symbology_mapping.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/sql.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/state.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/acl.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/config.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/default.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/file.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/helpers.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/locator.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/perf.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/query.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/render.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/script.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/temp.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/types.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/utils/tz.py +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/dependency_links.txt +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/requires.txt +0 -0
- {onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick_py.egg-info/top_level.txt +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: onetick-py
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.179.0
|
|
4
4
|
Summary: Python package that allows you to work with OneTick
|
|
5
5
|
Author-email: solutions <solutions@onetick.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Documentation, https://docs.pip.distribution.sol.onetick.com
|
|
8
8
|
Project-URL: OneTick, https://onetick.com
|
|
9
9
|
Project-URL: GitHub, https://github.com/onemarketdata/onetick-py
|
|
10
|
+
Project-URL: Issues, https://github.com/onemarketdata/onetick-py/issues
|
|
10
11
|
Classifier: Topic :: Database :: Front-Ends
|
|
11
12
|
Classifier: Topic :: Scientific/Engineering
|
|
12
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
@@ -39,6 +39,7 @@ classifiers = [
|
|
|
39
39
|
Documentation = "https://docs.pip.distribution.sol.onetick.com"
|
|
40
40
|
OneTick = "https://onetick.com"
|
|
41
41
|
GitHub = "https://github.com/onemarketdata/onetick-py"
|
|
42
|
+
Issues = "https://github.com/onemarketdata/onetick-py/issues"
|
|
42
43
|
|
|
43
44
|
[tool.setuptools.packages.find]
|
|
44
45
|
where = ["src"]
|
|
@@ -192,7 +192,7 @@ from onetick.py.sources import (Tick, TTicks, Ticks, Orders, Trades, NBBO, Quote
|
|
|
192
192
|
Custom, query, Symbols, Empty, DataSource, LocalCSVTicks, SymbologyMapping,
|
|
193
193
|
ObSnapshot, ObSnapshotWide, ObSnapshotFlat, ObSummary, ObSize, ObVwap, ObNumLevels,
|
|
194
194
|
by_symbol, ODBC, SplitQueryOutputBySymbol, DataFile, PointInTime,
|
|
195
|
-
ReadSnapshot, ShowSnapshotList, FindSnapshotSymbols)
|
|
195
|
+
ReadSnapshot, ShowSnapshotList, FindSnapshotSymbols, ReadFromDataFrame)
|
|
196
196
|
from onetick.py.utils import adaptive, range, perf
|
|
197
197
|
from onetick.py.session import Session, TestSession, Config, Locator, HTTPSession
|
|
198
198
|
from onetick.py.servers import RemoteTS, LoadBalancing, FaultTolerance
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# This file was generated automatically. DO NOT CHANGE.
|
|
2
|
-
VERSION = '1.
|
|
2
|
+
VERSION = '1.179.0'
|
|
@@ -4,6 +4,7 @@ from dataclasses import dataclass, astuple
|
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
|
+
import pandas as pd
|
|
7
8
|
from packaging.version import parse as parse_version
|
|
8
9
|
|
|
9
10
|
import onetick.py as otp
|
|
@@ -103,6 +104,36 @@ def _parse_release_string(release_string: str, build_number: int) -> OnetickVers
|
|
|
103
104
|
raise ValueError(f"Unknown release type '{release_type}' in release string '{release_string}'")
|
|
104
105
|
|
|
105
106
|
|
|
107
|
+
def _get_locator_min_date(db_name, context):
|
|
108
|
+
graph = otq.GraphQuery(otq.DbShowConfiguredTimeRanges(db_name=db_name).tick_type('ANY')
|
|
109
|
+
>> otq.Table(fields='long START_DATE, long END_DATE'))
|
|
110
|
+
symbols = f'{db_name}::'
|
|
111
|
+
result = otq.run(graph,
|
|
112
|
+
symbols=symbols,
|
|
113
|
+
# start and end times don't matter for this query, use some constants
|
|
114
|
+
start=datetime(2003, 12, 1),
|
|
115
|
+
end=datetime(2003, 12, 1),
|
|
116
|
+
# GMT, because start/end timestamp in locator are in GMT
|
|
117
|
+
timezone='GMT',
|
|
118
|
+
context=context)
|
|
119
|
+
data = result.output(symbols).data
|
|
120
|
+
first_date = data['START_DATE'][0]
|
|
121
|
+
return datetime.fromtimestamp(first_date / 1000)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _get_onetick_version(symbols, context, start, end):
|
|
125
|
+
node = otq.TickGenerator(bucket_interval=0,
|
|
126
|
+
fields='BUILD=GET_ONETICK_VERSION(), RELEASE=GET_ONETICK_RELEASE()')
|
|
127
|
+
graph = otq.GraphQuery(node.tick_type('DUMMY'))
|
|
128
|
+
result = otq.run(graph,
|
|
129
|
+
symbols=symbols,
|
|
130
|
+
start=start,
|
|
131
|
+
end=end,
|
|
132
|
+
context=context,
|
|
133
|
+
timezone='UTC')
|
|
134
|
+
return result
|
|
135
|
+
|
|
136
|
+
|
|
106
137
|
@cache
|
|
107
138
|
def get_onetick_version(db=None, context=None) -> OnetickVersionFromServer:
|
|
108
139
|
"""
|
|
@@ -132,27 +163,31 @@ def get_onetick_version(db=None, context=None) -> OnetickVersionFromServer:
|
|
|
132
163
|
s = otp.Session()
|
|
133
164
|
else:
|
|
134
165
|
_ = otli.OneTickLib()
|
|
135
|
-
p = otq.TickGenerator(bucket_interval=0,
|
|
136
|
-
fields='BUILD=GET_ONETICK_VERSION(), RELEASE=GET_ONETICK_RELEASE()')
|
|
137
|
-
graph = otq.GraphQuery(p.tick_type('DUMMY'))
|
|
138
166
|
|
|
139
167
|
# if otp.config.default_db is set, then we use it to check compatibility
|
|
140
168
|
# otherwise we use LOCAL database available everywhere
|
|
141
169
|
db = db or otp.config.get('default_db', 'LOCAL')
|
|
142
|
-
|
|
170
|
+
symbols = f'{db}::'
|
|
143
171
|
context = context or otp.config.context
|
|
144
172
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
173
|
+
try:
|
|
174
|
+
# let's try some default time range first
|
|
175
|
+
start = end = datetime(2003, 12, 1)
|
|
176
|
+
result = _get_onetick_version(symbols, context, start, end)
|
|
177
|
+
except Exception:
|
|
178
|
+
if db != 'LOCAL':
|
|
179
|
+
# for real db we need to set time range correctly
|
|
180
|
+
# otherwise we may get error "Database locator has a gap"
|
|
181
|
+
start = end = _get_locator_min_date(db, context)
|
|
182
|
+
result = _get_onetick_version(symbols, context, start, end)
|
|
183
|
+
else:
|
|
184
|
+
raise
|
|
185
|
+
finally:
|
|
186
|
+
if s:
|
|
187
|
+
s.close()
|
|
153
188
|
|
|
154
|
-
build_number = result[
|
|
155
|
-
release_string = result[
|
|
189
|
+
build_number = result[symbols]["BUILD"][0]
|
|
190
|
+
release_string = result[symbols]["RELEASE"][0]
|
|
156
191
|
|
|
157
192
|
try:
|
|
158
193
|
onetick_version = _parse_release_string(release_string, build_number=build_number)
|
|
@@ -667,7 +702,22 @@ def is_percentile_bug_fixed():
|
|
|
667
702
|
|
|
668
703
|
|
|
669
704
|
def is_limit_ep_supported():
|
|
670
|
-
|
|
705
|
+
# Implemented 0034293: LIMIT ep
|
|
706
|
+
return (
|
|
707
|
+
hasattr(otq, 'Limit') and
|
|
708
|
+
_is_min_build_or_version(1.25, 20241229055942,
|
|
709
|
+
20241018120000, min_update_number=1)
|
|
710
|
+
)
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
def is_limit_tick_offset_supported():
|
|
714
|
+
# Implemented OTDEV-37257: LIMIT EP should support TICK_OFFSET parameter
|
|
715
|
+
return (
|
|
716
|
+
is_limit_ep_supported() and
|
|
717
|
+
'tick_offset' in otq.Limit.Parameters.list_parameters() and
|
|
718
|
+
_is_min_build_or_version(None, None,
|
|
719
|
+
20251010120000, min_update_number=2)
|
|
720
|
+
)
|
|
671
721
|
|
|
672
722
|
|
|
673
723
|
def is_prefer_speed_over_accuracy_supported(**kwargs):
|
|
@@ -733,8 +783,11 @@ def is_multi_column_generic_aggregations_supported():
|
|
|
733
783
|
|
|
734
784
|
|
|
735
785
|
def is_max_concurrency_with_webapi_supported():
|
|
786
|
+
# 0036758: in onetick.query_webapi: max_concurrency is not being saved in otq file when set on otq.Query
|
|
787
|
+
# 0036759: in onetick.query_webapi:
|
|
788
|
+
# it's not possible to pass max_concurrency 0 in method otq.run when using otq file
|
|
736
789
|
return _is_min_build_or_version(None, None,
|
|
737
|
-
|
|
790
|
+
20250727120000, min_update_number=3)
|
|
738
791
|
|
|
739
792
|
|
|
740
793
|
def is_nanoseconds_fixed_in_run():
|
|
@@ -783,12 +836,16 @@ def is_show_db_list_show_description_supported():
|
|
|
783
836
|
|
|
784
837
|
def is_symbols_prepend_db_name_supported():
|
|
785
838
|
# 20250924: Implemented 0036753: FIND_DB_SYMBOLS should have EP parameter PREPEND_DB_NAME (true by default)
|
|
786
|
-
return hasattr(otq.FindDbSymbols.Parameters, 'prepend_db_name')
|
|
839
|
+
return hasattr(otq.FindDbSymbols.Parameters, 'prepend_db_name') and _is_min_build_or_version(
|
|
840
|
+
None, None, 20251010120000,
|
|
841
|
+
)
|
|
787
842
|
|
|
788
843
|
|
|
789
844
|
def is_diff_show_all_ticks_supported():
|
|
790
845
|
# 20250919: Implemented 0036784: Add SHOW_ALL_TICKS(false by default) ep parameter to DIFF EP.
|
|
791
|
-
return hasattr(otq.Diff.Parameters, 'show_all_ticks')
|
|
846
|
+
return hasattr(otq.Diff.Parameters, 'show_all_ticks') and _is_min_build_or_version(
|
|
847
|
+
None, None, 20251010120000,
|
|
848
|
+
)
|
|
792
849
|
|
|
793
850
|
|
|
794
851
|
def is_max_spread_supported():
|
|
@@ -796,3 +853,9 @@ def is_max_spread_supported():
|
|
|
796
853
|
# should also support parameter MAX_SPREAD
|
|
797
854
|
return _is_min_build_or_version(None, None,
|
|
798
855
|
20251010120000)
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
def is_not_fixed_bds_484():
|
|
859
|
+
# BDS-484: seems like timezone is ignored in otq.run in some cases
|
|
860
|
+
return _is_min_build_or_version(None, None,
|
|
861
|
+
20251010120000, min_update_number=2)
|
{onetick_py-1.177.0 → onetick_py-1.179.0}/src/onetick/py/core/_source/source_methods/misc.py
RENAMED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import re
|
|
3
|
+
import warnings
|
|
3
4
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
|
|
4
|
-
from onetick.py.backports import Literal
|
|
5
5
|
|
|
6
6
|
import onetick.py as otp
|
|
7
|
+
from onetick.py.backports import Literal
|
|
7
8
|
from onetick.py import types as ott
|
|
8
9
|
from onetick.py import utils
|
|
9
10
|
from onetick.py.core.column import _Column
|
|
@@ -1109,16 +1110,26 @@ def book_diff(self: 'Source', include_initial_book: bool = False, inplace=False)
|
|
|
1109
1110
|
|
|
1110
1111
|
|
|
1111
1112
|
@inplace_operation
|
|
1112
|
-
def limit(self: 'Source',
|
|
1113
|
+
def limit(self: 'Source',
|
|
1114
|
+
tick_limit: int,
|
|
1115
|
+
tick_offset: Optional[int] = None,
|
|
1116
|
+
inplace=False) -> Optional['Source']:
|
|
1113
1117
|
"""
|
|
1114
|
-
Propagates ticks until the count limit is reached.
|
|
1118
|
+
Propagates ticks until the count limit is reached.
|
|
1119
|
+
|
|
1120
|
+
Once the limit is reached,
|
|
1115
1121
|
hidden ticks will still continue to propagate until the next regular tick appears.
|
|
1116
1122
|
|
|
1117
1123
|
Parameters
|
|
1118
1124
|
----------
|
|
1119
1125
|
tick_limit: int
|
|
1120
|
-
The number of regular ticks to propagate.
|
|
1121
|
-
|
|
1126
|
+
The number of regular ticks to propagate.
|
|
1127
|
+
Must be a non-negative integer or -1, which means no limit.
|
|
1128
|
+
tick_offset: int
|
|
1129
|
+
The number of regular ticks to skip before starting to propagate.
|
|
1130
|
+
Must be a non-negative integer.
|
|
1131
|
+
By default no ticks are skipped.
|
|
1132
|
+
inplace: bool
|
|
1122
1133
|
The flag controls whether operation should be applied inplace or not.
|
|
1123
1134
|
If ``inplace=True``, then it returns nothing. Otherwise method returns a new modified
|
|
1124
1135
|
object.
|
|
@@ -1134,14 +1145,15 @@ def limit(self: 'Source', tick_limit: int, inplace=False) -> Optional['Source']:
|
|
|
1134
1145
|
Examples
|
|
1135
1146
|
--------
|
|
1136
1147
|
|
|
1137
|
-
|
|
1148
|
+
Simple example, get first 3 ticks:
|
|
1138
1149
|
|
|
1139
1150
|
.. testcode::
|
|
1140
1151
|
:skipif: not otp.compatibility.is_limit_ep_supported()
|
|
1141
1152
|
|
|
1142
1153
|
data = otp.Ticks(X=[1, 2, 3, 4, 5, 6])
|
|
1143
|
-
data = data.limit(
|
|
1144
|
-
|
|
1154
|
+
data = data.limit(3)
|
|
1155
|
+
df = otp.run(data)
|
|
1156
|
+
print(df)
|
|
1145
1157
|
|
|
1146
1158
|
.. testoutput::
|
|
1147
1159
|
|
|
@@ -1150,14 +1162,15 @@ def limit(self: 'Source', tick_limit: int, inplace=False) -> Optional['Source']:
|
|
|
1150
1162
|
1 2003-12-01 00:00:00.001 2
|
|
1151
1163
|
2 2003-12-01 00:00:00.002 3
|
|
1152
1164
|
|
|
1153
|
-
Disable limit
|
|
1165
|
+
Disable limit by setting it to -1:
|
|
1154
1166
|
|
|
1155
1167
|
.. testcode::
|
|
1156
1168
|
:skipif: not otp.compatibility.is_limit_ep_supported()
|
|
1157
1169
|
|
|
1158
1170
|
data = otp.Ticks(X=[1, 2, 3, 4, 5, 6])
|
|
1159
|
-
data = data.limit(
|
|
1160
|
-
|
|
1171
|
+
data = data.limit(-1)
|
|
1172
|
+
df = otp.run(data)
|
|
1173
|
+
print(df)
|
|
1161
1174
|
|
|
1162
1175
|
.. testoutput::
|
|
1163
1176
|
|
|
@@ -1168,14 +1181,61 @@ def limit(self: 'Source', tick_limit: int, inplace=False) -> Optional['Source']:
|
|
|
1168
1181
|
3 2003-12-01 00:00:00.003 4
|
|
1169
1182
|
4 2003-12-01 00:00:00.004 5
|
|
1170
1183
|
5 2003-12-01 00:00:00.005 6
|
|
1184
|
+
|
|
1185
|
+
Setting parameter ``tick_offset`` can be used to skip first ticks before propagating them.
|
|
1186
|
+
|
|
1187
|
+
For example, we can skip first 2 ticks and propagate all other:
|
|
1188
|
+
|
|
1189
|
+
.. testcode::
|
|
1190
|
+
:skipif: not otp.compatibility.is_limit_tick_offset_supported()
|
|
1191
|
+
|
|
1192
|
+
data = otp.Ticks(X=[1, 2, 3, 4, 5, 6])
|
|
1193
|
+
data = data.limit(-1, tick_offset=2)
|
|
1194
|
+
df = otp.run(data)
|
|
1195
|
+
print(df)
|
|
1196
|
+
|
|
1197
|
+
.. testoutput::
|
|
1198
|
+
|
|
1199
|
+
Time X
|
|
1200
|
+
0 2003-12-01 00:00:00.002 3
|
|
1201
|
+
1 2003-12-01 00:00:00.003 4
|
|
1202
|
+
2 2003-12-01 00:00:00.004 5
|
|
1203
|
+
3 2003-12-01 00:00:00.005 6
|
|
1204
|
+
|
|
1205
|
+
Or we can return ticks from the middle of the stream
|
|
1206
|
+
by skipping first 2 ticks and then returning next 2 ticks like this:
|
|
1207
|
+
|
|
1208
|
+
.. testcode::
|
|
1209
|
+
:skipif: not otp.compatibility.is_limit_tick_offset_supported()
|
|
1210
|
+
|
|
1211
|
+
data = otp.Ticks(X=[1, 2, 3, 4, 5, 6])
|
|
1212
|
+
data = data.limit(2, tick_offset=2)
|
|
1213
|
+
df = otp.run(data)
|
|
1214
|
+
print(df)
|
|
1215
|
+
|
|
1216
|
+
.. testoutput::
|
|
1217
|
+
|
|
1218
|
+
Time X
|
|
1219
|
+
0 2003-12-01 00:00:00.002 3
|
|
1220
|
+
1 2003-12-01 00:00:00.003 4
|
|
1171
1221
|
"""
|
|
1172
|
-
if not
|
|
1222
|
+
if not otp.compatibility.is_limit_ep_supported():
|
|
1173
1223
|
raise RuntimeError('LIMIT EP isn\'t supported by the current OneTick version.')
|
|
1174
1224
|
|
|
1175
1225
|
if tick_limit < 0 and tick_limit != -1:
|
|
1176
1226
|
raise ValueError('Negative values, except -1, not allowed as `tick_limit` in `limit` method.')
|
|
1177
1227
|
|
|
1178
|
-
|
|
1228
|
+
ep_kwargs = {}
|
|
1229
|
+
if tick_offset is not None:
|
|
1230
|
+
if not isinstance(tick_offset, int) or tick_offset < 0:
|
|
1231
|
+
raise ValueError("Parameter 'tick_offset' must be non-negative.")
|
|
1232
|
+
|
|
1233
|
+
if not otp.compatibility.is_limit_tick_offset_supported():
|
|
1234
|
+
warnings.warn("Parameter 'tick_offset' is set, but is not supported on this OneTick version")
|
|
1235
|
+
else:
|
|
1236
|
+
ep_kwargs = {'tick_offset': tick_offset}
|
|
1237
|
+
|
|
1238
|
+
self.sink(otq.Limit(tick_limit=tick_limit, **ep_kwargs))
|
|
1179
1239
|
return self
|
|
1180
1240
|
|
|
1181
1241
|
|
|
@@ -108,6 +108,14 @@ class TmpOtq:
|
|
|
108
108
|
res.merge(self)
|
|
109
109
|
return res
|
|
110
110
|
|
|
111
|
+
def _get_symbol_dates(self) -> list[str]:
|
|
112
|
+
# check if any of the saved queries have symbol date set and return them (as strings in %Y%m%d format)
|
|
113
|
+
return [
|
|
114
|
+
utils.symbol_date_to_str(query_params['symbol_date'])
|
|
115
|
+
for _, query_params in self.queries.values()
|
|
116
|
+
if 'symbol_date' in query_params
|
|
117
|
+
]
|
|
118
|
+
|
|
111
119
|
def save_to_file(self, query=None, query_name="main_query", file_path=None, file_suffix="",
|
|
112
120
|
start=None, end=None, start_time_expression=None, end_time_expression=None, timezone=None,
|
|
113
121
|
running_query_flag=None,
|
|
@@ -432,7 +432,7 @@ class Source:
|
|
|
432
432
|
end_time_expression=None,
|
|
433
433
|
symbol_date=None):
|
|
434
434
|
"""
|
|
435
|
-
Save
|
|
435
|
+
Save :class:`otp.Source <onetick.py.Source>` object to .otq file and return path to the saved file.
|
|
436
436
|
|
|
437
437
|
Parameters
|
|
438
438
|
----------
|
|
@@ -474,10 +474,17 @@ class Source:
|
|
|
474
474
|
|
|
475
475
|
Returns
|
|
476
476
|
-------
|
|
477
|
-
|
|
478
477
|
result: str
|
|
479
478
|
Relative (if ``file_name`` is relative) or absolute path to the created query
|
|
480
479
|
in the format ``file_name::query_name``
|
|
480
|
+
|
|
481
|
+
Examples
|
|
482
|
+
--------
|
|
483
|
+
Create the .otq file from a :class:`otp.Source <onetick.py.Source>` object:
|
|
484
|
+
|
|
485
|
+
>>> t = otp.Tick(A=1)
|
|
486
|
+
>>> t.to_otq() # doctest: +SKIP
|
|
487
|
+
'/tmp/test_user/run_20251202_181018_11054/impetuous-bullfrog.to_otq.otq::query'
|
|
481
488
|
"""
|
|
482
489
|
if raw is not None:
|
|
483
490
|
warnings.warn('The "raw" flag is deprecated and makes no effect', FutureWarning)
|
|
@@ -635,7 +642,22 @@ class Source:
|
|
|
635
642
|
timezone=timezone,
|
|
636
643
|
symbol_date=symbol_date)
|
|
637
644
|
|
|
638
|
-
|
|
645
|
+
# PY-1423: we should set symbol_date in otp.run always
|
|
646
|
+
symbol_date_to_run = None
|
|
647
|
+
if symbol_date is not None:
|
|
648
|
+
symbol_date_to_run = utils.symbol_date_to_str(symbol_date)
|
|
649
|
+
else:
|
|
650
|
+
symbol_dates_in_tmp_otq = obj._tmp_otq._get_symbol_dates()
|
|
651
|
+
if symbol_dates_in_tmp_otq:
|
|
652
|
+
symbol_date_to_run = symbol_dates_in_tmp_otq[0]
|
|
653
|
+
if len(set(symbol_dates_in_tmp_otq)) > 1:
|
|
654
|
+
warnings.warn(
|
|
655
|
+
f'There are different symbol dates in resulting .otq file: {set(symbol_dates_in_tmp_otq)}.'
|
|
656
|
+
'But no symbol date were specified in otp.run.\n'
|
|
657
|
+
f'In this case the first symbol_date ({symbol_date_to_run}) will be used automatically.'
|
|
658
|
+
)
|
|
659
|
+
|
|
660
|
+
return query_to_run, require_dict, node_name, symbol_date_to_run
|
|
639
661
|
|
|
640
662
|
def __call__(self, *args, **kwargs):
|
|
641
663
|
"""
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
import warnings
|
|
3
|
-
from
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from typing import Union, Iterable, Tuple, Optional, Literal
|
|
4
5
|
from datetime import date as dt_date, datetime, timedelta
|
|
6
|
+
from functools import wraps
|
|
5
7
|
|
|
6
8
|
import pandas as pd
|
|
7
9
|
from dateutil.tz import gettz
|
|
@@ -19,6 +21,39 @@ def _datetime2date(dt: Union[dt_date, datetime]) -> dt_date:
|
|
|
19
21
|
return dt_date(dt.year, dt.month, dt.day)
|
|
20
22
|
|
|
21
23
|
|
|
24
|
+
def _method_cache(meth):
|
|
25
|
+
"""
|
|
26
|
+
Cache the output of class method.
|
|
27
|
+
Cache is created inside of the self object (in self.__cache property)
|
|
28
|
+
and will be deleted when self object is destroyed.
|
|
29
|
+
|
|
30
|
+
This is a rewrite of functools.cache,
|
|
31
|
+
but it doesn't add self argument to cache key and thus doesn't keep reference to self forever.
|
|
32
|
+
"""
|
|
33
|
+
@wraps(meth)
|
|
34
|
+
def wrapper(self, *args, **kwargs):
|
|
35
|
+
|
|
36
|
+
# cache key is a tuple of all arguments
|
|
37
|
+
key = args
|
|
38
|
+
for kw_tup in kwargs.items():
|
|
39
|
+
key += kw_tup
|
|
40
|
+
key = hash(key)
|
|
41
|
+
|
|
42
|
+
if not hasattr(self, '__cache'):
|
|
43
|
+
self.__cache = defaultdict(dict)
|
|
44
|
+
|
|
45
|
+
method_cache = self.__cache[meth.__name__]
|
|
46
|
+
|
|
47
|
+
miss = object()
|
|
48
|
+
result = method_cache.get(key, miss)
|
|
49
|
+
if result is miss:
|
|
50
|
+
result = meth(self, *args, **kwargs)
|
|
51
|
+
method_cache[key] = result
|
|
52
|
+
return result
|
|
53
|
+
|
|
54
|
+
return wrapper
|
|
55
|
+
|
|
56
|
+
|
|
22
57
|
class DB:
|
|
23
58
|
|
|
24
59
|
"""
|
|
@@ -37,7 +72,11 @@ class DB:
|
|
|
37
72
|
self._locator_date_ranges = None
|
|
38
73
|
|
|
39
74
|
def __eq__(self, obj):
|
|
40
|
-
return
|
|
75
|
+
return all((
|
|
76
|
+
self.name == obj.name,
|
|
77
|
+
self.description == obj.description,
|
|
78
|
+
self.context == obj.context,
|
|
79
|
+
))
|
|
41
80
|
|
|
42
81
|
def __lt__(self, obj):
|
|
43
82
|
return str(self) < str(obj)
|
|
@@ -45,6 +84,7 @@ class DB:
|
|
|
45
84
|
def __str__(self):
|
|
46
85
|
return self.name
|
|
47
86
|
|
|
87
|
+
@_method_cache
|
|
48
88
|
def access_info(self, deep_scan=False, username=None) -> Union[pd.DataFrame, dict]:
|
|
49
89
|
"""
|
|
50
90
|
Get access info for this database and ``username``.
|
|
@@ -111,13 +151,19 @@ class DB:
|
|
|
111
151
|
>> otq.WhereClause(where=f'DB_NAME = "{name}"')
|
|
112
152
|
)
|
|
113
153
|
graph = otq.GraphQuery(node)
|
|
154
|
+
|
|
155
|
+
self._set_intervals()
|
|
156
|
+
# start and end times don't matter, but need to fit in the configured time ranges
|
|
157
|
+
start, end = self._locator_date_ranges[-1]
|
|
158
|
+
|
|
114
159
|
df = otp.run(graph,
|
|
115
|
-
symbols='
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
end=db_constants.DEFAULT_END_DATE,
|
|
160
|
+
symbols=f'{self.name}::',
|
|
161
|
+
start=start,
|
|
162
|
+
end=end,
|
|
119
163
|
# and timezone is GMT, because timestamp parameters in ACL are in GMT
|
|
120
164
|
timezone='GMT',
|
|
165
|
+
# ACCESS_INFO can return ACL violation error if we use database name as symbol
|
|
166
|
+
query_properties={'IGNORE_TICKS_IN_UNENTITLED_TIME_RANGE': 'TRUE'},
|
|
121
167
|
username=username,
|
|
122
168
|
context=self.context)
|
|
123
169
|
if not df.empty:
|
|
@@ -255,6 +301,20 @@ class DB:
|
|
|
255
301
|
end = start + otp.Day(1)
|
|
256
302
|
return self._fit_time_interval_in_acl(start, end, timezone)
|
|
257
303
|
|
|
304
|
+
@_method_cache
|
|
305
|
+
def _show_configured_time_ranges(self):
|
|
306
|
+
graph = otq.GraphQuery(otq.DbShowConfiguredTimeRanges(db_name=self.name).tick_type("ANY")
|
|
307
|
+
>> otq.Table(fields='long START_DATE, long END_DATE'))
|
|
308
|
+
result = otp.run(graph,
|
|
309
|
+
symbols=f'{self.name}::',
|
|
310
|
+
# start and end times don't matter for this query, use some constants
|
|
311
|
+
start=db_constants.DEFAULT_START_DATE,
|
|
312
|
+
end=db_constants.DEFAULT_END_DATE,
|
|
313
|
+
# GMT, because start/end timestamp in locator are in GMT
|
|
314
|
+
timezone='GMT',
|
|
315
|
+
context=self.context)
|
|
316
|
+
return result
|
|
317
|
+
|
|
258
318
|
def _set_intervals(self):
|
|
259
319
|
"""
|
|
260
320
|
Finds all date ranges from locators.
|
|
@@ -264,18 +324,7 @@ class DB:
|
|
|
264
324
|
"""
|
|
265
325
|
|
|
266
326
|
if self._locator_date_ranges is None:
|
|
267
|
-
|
|
268
|
-
>> otq.Table(fields='long START_DATE, long END_DATE'))
|
|
269
|
-
|
|
270
|
-
result = otp.run(graph,
|
|
271
|
-
symbols=f'{self.name}::',
|
|
272
|
-
# start and end times don't matter for this query, use some constants
|
|
273
|
-
start=db_constants.DEFAULT_START_DATE,
|
|
274
|
-
end=db_constants.DEFAULT_END_DATE,
|
|
275
|
-
# GMT, because start/end timestamp in locator are in GMT
|
|
276
|
-
timezone='GMT',
|
|
277
|
-
context=self.context)
|
|
278
|
-
|
|
327
|
+
result = self._show_configured_time_ranges()
|
|
279
328
|
date_ranges = []
|
|
280
329
|
|
|
281
330
|
tz_gmt = gettz('GMT')
|
|
@@ -316,10 +365,20 @@ class DB:
|
|
|
316
365
|
|
|
317
366
|
def _show_loaded_time_ranges(self, start, end, only_last=False, prefer_speed_over_accuracy=False):
|
|
318
367
|
kwargs = {}
|
|
368
|
+
# PY-1421: we aim to make this query as fast as possible
|
|
369
|
+
# There are two problems with this EP:
|
|
370
|
+
# 1. executing this query without using cache
|
|
371
|
+
# and/or without setting prefer_speed_over_accuracy parameter
|
|
372
|
+
# may be very slow for big time range
|
|
373
|
+
# 2. using cache sometimes returns not precise results
|
|
374
|
+
# So in case prefer_speed_over_accuracy parameter is available we are disabling cache.
|
|
319
375
|
if prefer_speed_over_accuracy:
|
|
320
|
-
kwargs['prefer_speed_over_accuracy'] =
|
|
376
|
+
kwargs['prefer_speed_over_accuracy'] = True
|
|
377
|
+
kwargs['use_cache'] = False
|
|
378
|
+
else:
|
|
379
|
+
kwargs['use_cache'] = True
|
|
321
380
|
|
|
322
|
-
eps = otq.DbShowLoadedTimeRanges(
|
|
381
|
+
eps = otq.DbShowLoadedTimeRanges(**kwargs).tick_type('ANY')
|
|
323
382
|
eps = eps >> otq.WhereClause(where='NUM_LOADED_PARTITIONS > 0')
|
|
324
383
|
if only_last:
|
|
325
384
|
eps = eps >> otq.LastTick()
|
|
@@ -528,32 +587,45 @@ class DB:
|
|
|
528
587
|
['QTE', 'TRD']
|
|
529
588
|
"""
|
|
530
589
|
date = self.last_date if date is None else date
|
|
590
|
+
|
|
531
591
|
if timezone is None:
|
|
532
592
|
timezone = configuration.config.tz
|
|
533
|
-
time_params: dict[str, Any] = {}
|
|
534
593
|
|
|
535
|
-
if date is
|
|
536
|
-
|
|
594
|
+
if date is None:
|
|
595
|
+
# in the usual case it would mean that there is no data in the database,
|
|
596
|
+
# but _show_loaded_time_ranges doesn't return dates for database views
|
|
597
|
+
# in this case let's just try to get the database schema with default time range
|
|
598
|
+
start = end = utils.adaptive
|
|
599
|
+
# also it seems that show_schema=True doesn't work for views either
|
|
600
|
+
show_schema = False
|
|
601
|
+
else:
|
|
602
|
+
start, end = self._fit_date_in_acl(date, timezone=timezone) # type: ignore[assignment]
|
|
603
|
+
show_schema = True
|
|
537
604
|
|
|
538
605
|
# PY-458: don't use cache, it can return different result in some cases
|
|
539
|
-
result =
|
|
540
|
-
show_schema=False,
|
|
541
|
-
include_memdb=True),
|
|
542
|
-
symbols=f'{self.name}::',
|
|
543
|
-
**time_params,
|
|
544
|
-
timezone=timezone,
|
|
545
|
-
context=self.context)
|
|
546
|
-
|
|
606
|
+
result = self._get_schema(use_cache=False, start=start, end=end, timezone=timezone, show_schema=show_schema)
|
|
547
607
|
if len(result) == 0:
|
|
548
608
|
return []
|
|
549
609
|
|
|
550
|
-
return result['TICK_TYPE_NAME'].tolist()
|
|
610
|
+
return result['TICK_TYPE_NAME'].unique().tolist()
|
|
551
611
|
|
|
552
612
|
def min_locator_date(self):
|
|
553
613
|
self._set_intervals()
|
|
554
614
|
min_date = min(obj[0] for obj in self._locator_date_ranges)
|
|
555
615
|
return _datetime2date(min_date)
|
|
556
616
|
|
|
617
|
+
@_method_cache
|
|
618
|
+
def _get_schema(self, start, end, timezone, use_cache, show_schema):
|
|
619
|
+
ep = otq.DbShowTickTypes(use_cache=use_cache,
|
|
620
|
+
show_schema=show_schema,
|
|
621
|
+
include_memdb=True)
|
|
622
|
+
return otp.run(ep,
|
|
623
|
+
symbols=f'{self.name}::',
|
|
624
|
+
start=start,
|
|
625
|
+
end=end,
|
|
626
|
+
timezone=timezone,
|
|
627
|
+
context=self.context)
|
|
628
|
+
|
|
557
629
|
def schema(self, date=None, tick_type=None, timezone=None, check_index_file=utils.adaptive) -> dict[str, type]:
|
|
558
630
|
"""
|
|
559
631
|
Gets the schema of the database.
|
|
@@ -615,25 +687,18 @@ class DB:
|
|
|
615
687
|
|
|
616
688
|
start, end = self._fit_date_in_acl(date, timezone=timezone)
|
|
617
689
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
symbols=f'{self.name}::',
|
|
625
|
-
start=start,
|
|
626
|
-
end=end,
|
|
627
|
-
timezone=timezone,
|
|
628
|
-
context=self.context)
|
|
629
|
-
|
|
630
|
-
result = get_schema(use_cache=True)
|
|
690
|
+
kwargs = dict(
|
|
691
|
+
start=start, end=end, timezone=timezone, show_schema=True,
|
|
692
|
+
)
|
|
693
|
+
# PY-458, BEXRTS-1220, PY-1421
|
|
694
|
+
# the results of the query may vary depending on using use_cache parameter, so we are trying both
|
|
695
|
+
result = self._get_schema(use_cache=False, **kwargs)
|
|
631
696
|
if result.empty:
|
|
632
|
-
|
|
633
|
-
result = get_schema(use_cache=False)
|
|
697
|
+
result = self._get_schema(use_cache=True, **kwargs)
|
|
634
698
|
|
|
635
|
-
fields: Iterable
|
|
699
|
+
fields: Iterable = []
|
|
636
700
|
if len(result):
|
|
701
|
+
result = result[result['TICK_TYPE_NAME'] == tick_type]
|
|
637
702
|
# filter schema by date
|
|
638
703
|
date_to_filter = None
|
|
639
704
|
if orig_date:
|
|
@@ -648,8 +713,6 @@ class DB:
|
|
|
648
713
|
fields = zip(result['FIELD_NAME'].tolist(),
|
|
649
714
|
result['FIELD_TYPE_NAME'].tolist(),
|
|
650
715
|
result['FIELD_SIZE'].tolist())
|
|
651
|
-
else:
|
|
652
|
-
fields = []
|
|
653
716
|
|
|
654
717
|
schema = {}
|
|
655
718
|
|