onetick-py 1.173.0__tar.gz → 1.174.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.173.0/src/onetick_py.egg-info → onetick_py-1.174.0}/PKG-INFO +2 -2
- {onetick_py-1.173.0 → onetick_py-1.174.0}/requirements.strict.txt +1 -1
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/_version.py +1 -1
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/_base.py +1 -1
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/order_book.py +13 -7
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/other.py +2 -2
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/misc.py +59 -13
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/_methods/conversions.py +3 -2
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/_methods/op_types.py +12 -3
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/base.py +2 -2
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/source.py +9 -1
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/functions.py +3 -2
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/types.py +115 -40
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/render.py +271 -58
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/types.py +2 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0/src/onetick_py.egg-info}/PKG-INFO +2 -2
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick_py.egg-info/requires.txt +1 -1
- {onetick_py-1.173.0 → onetick_py-1.174.0}/LICENSE +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/README.md +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/pyproject.toml +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/requirements.txt +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/setup.cfg +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/setup.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/locator_parser/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/locator_parser/acl.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/locator_parser/actions.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/locator_parser/common.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/locator_parser/io.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/locator_parser/locator.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/doc_utilities/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/doc_utilities/napoleon.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/doc_utilities/ot_doctest.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/doc_utilities/snippets.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/lib/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/lib/instance.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/_stack_info.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/_docs.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/compute.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/functions.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/generic.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/high_low.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/aggregations/num_distinct.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/backports.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/cache.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/callback/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/callback/callback.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/callback/callbacks.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/compatibility.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/configuration.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_csv_inspector.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/_manually_bound_value.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/_nodes_history.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/_op_utils/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/_op_utils/every_operand.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/_op_utils/is_const.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/_per_tick_scripts/tick_list_sort_template.script +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/_proxy_node.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/_state_objects.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_internal/_state_vars.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/_symbol_param.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/schema.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/aggregations.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/applyers.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/columns.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/data_quality.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/debugs.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/drops.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/fields.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/filters.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/joins.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/merges.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/pandases.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/renames.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/sorts.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/switches.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/symbols.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/times.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/writes.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/symbol.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/tmp_otq.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/_methods/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/_methods/_internal.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/_methods/methods.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/accessors/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/accessors/_accessor.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/accessors/decimal_accessor.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/accessors/dt_accessor.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/accessors/float_accessor.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/accessors/str_accessor.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/cut_builder.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/db_constants.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/eval_query.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/lambda_object.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/multi_output_source.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/per_tick_script.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/query_inspector.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/db/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/db/_inspection.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/db/db.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/db/utils.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/docs/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/docs/docstring_parser.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/docs/utils.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/license.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/log.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/math.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/misc.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/oqd/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/oqd/eps.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/oqd/sources.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/otq.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/pyomd_mock.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/run.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/servers.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/session.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/cache.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/common.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/csv.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/custom.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/data_file.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/data_source.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/empty.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/odbc.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/order_book.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/parquet.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/pit.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/query.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/snapshots.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/split_query_output_by_symbol.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/symbology_mapping.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/symbols.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sources/ticks.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/sql.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/state.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/__init__.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/acl.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/config.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/default.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/file.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/helpers.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/locator.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/perf.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/query.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/script.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/temp.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/utils/tz.py +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick_py.egg-info/SOURCES.txt +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick_py.egg-info/dependency_links.txt +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick_py.egg-info/entry_points.txt +0 -0
- {onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick_py.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: onetick-py
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.174.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
|
|
@@ -36,7 +36,7 @@ Requires-Dist: numpy==1.26.4; python_version == "3.12" and extra == "strict"
|
|
|
36
36
|
Requires-Dist: pandas==1.5.2; python_version == "3.9" and extra == "strict"
|
|
37
37
|
Requires-Dist: pandas==1.5.3; python_version == "3.10" and extra == "strict"
|
|
38
38
|
Requires-Dist: pandas==1.5.3; python_version == "3.11" and extra == "strict"
|
|
39
|
-
Requires-Dist: pandas==2.2.
|
|
39
|
+
Requires-Dist: pandas==2.2.1; python_version == "3.12" and extra == "strict"
|
|
40
40
|
Requires-Dist: pandas==2.3.0; python_version == "3.13" and extra == "strict"
|
|
41
41
|
Requires-Dist: pandas==2.3.3; python_version == "3.14" and extra == "strict"
|
|
42
42
|
Provides-Extra: webapi
|
|
@@ -5,6 +5,6 @@ numpy==1.26.4; python_version == '3.12'
|
|
|
5
5
|
pandas==1.5.2; python_version == '3.9'
|
|
6
6
|
pandas==1.5.3; python_version == '3.10'
|
|
7
7
|
pandas==1.5.3; python_version == '3.11'
|
|
8
|
-
pandas==2.2.
|
|
8
|
+
pandas==2.2.1; python_version == '3.12'
|
|
9
9
|
pandas==2.3.0; python_version == '3.13'
|
|
10
10
|
pandas==2.3.3; python_version == '3.14'
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# This file was generated automatically. DO NOT CHANGE.
|
|
2
|
-
VERSION = '1.
|
|
2
|
+
VERSION = '1.174.0'
|
|
@@ -547,7 +547,7 @@ class _AggregationTSSelection(_Aggregation):
|
|
|
547
547
|
|
|
548
548
|
class _FloatAggregation(_Aggregation):
|
|
549
549
|
|
|
550
|
-
require_type = (int, float, ott._inf)
|
|
550
|
+
require_type = (int, float, ott._inf, ott.decimal)
|
|
551
551
|
|
|
552
552
|
"""
|
|
553
553
|
Aggregation that expect int or float as input
|
|
@@ -229,6 +229,9 @@ class ObSnapshot(_OrderBookAggregation):
|
|
|
229
229
|
# we don't want to set hard limit on the output of order book aggregations
|
|
230
230
|
if self.show_full_detail:
|
|
231
231
|
kwargs['all_fields'] = True
|
|
232
|
+
self._size_type = int
|
|
233
|
+
if self.size_max_fractional_digits > 0:
|
|
234
|
+
self._size_type = float # type: ignore[assignment]
|
|
232
235
|
super().__init__(*args, **kwargs)
|
|
233
236
|
|
|
234
237
|
def _param_validation(self):
|
|
@@ -244,7 +247,7 @@ class ObSnapshot(_OrderBookAggregation):
|
|
|
244
247
|
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
245
248
|
schema = {
|
|
246
249
|
'PRICE': float,
|
|
247
|
-
'SIZE':
|
|
250
|
+
'SIZE': self._size_type,
|
|
248
251
|
'LEVEL': int,
|
|
249
252
|
'UPDATE_TIME': otp.nsectime,
|
|
250
253
|
'BUY_SELL_FLAG': int,
|
|
@@ -265,10 +268,10 @@ class ObSnapshotWide(ObSnapshot):
|
|
|
265
268
|
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
266
269
|
schema = {
|
|
267
270
|
'BID_PRICE': float,
|
|
268
|
-
'BID_SIZE':
|
|
271
|
+
'BID_SIZE': self._size_type,
|
|
269
272
|
'BID_UPDATE_TIME': otp.nsectime,
|
|
270
273
|
'ASK_PRICE': float,
|
|
271
|
-
'ASK_SIZE':
|
|
274
|
+
'ASK_SIZE': self._size_type,
|
|
272
275
|
'ASK_UPDATE_TIME': otp.nsectime,
|
|
273
276
|
'LEVEL': int,
|
|
274
277
|
}
|
|
@@ -299,10 +302,10 @@ class ObSnapshotFlat(ObSnapshot):
|
|
|
299
302
|
for level in range(1, self.max_levels + 1):
|
|
300
303
|
schema.update({
|
|
301
304
|
f'BID_PRICE{level}': float,
|
|
302
|
-
f'BID_SIZE{level}':
|
|
305
|
+
f'BID_SIZE{level}': self._size_type,
|
|
303
306
|
f'BID_UPDATE_TIME{level}': otp.nsectime,
|
|
304
307
|
f'ASK_PRICE{level}': float,
|
|
305
|
-
f'ASK_SIZE{level}':
|
|
308
|
+
f'ASK_SIZE{level}': self._size_type,
|
|
306
309
|
f'ASK_UPDATE_TIME{level}': otp.nsectime,
|
|
307
310
|
})
|
|
308
311
|
return schema
|
|
@@ -343,6 +346,9 @@ class ObSummary(_OrderBookAggregation):
|
|
|
343
346
|
self.state_key_max_inactivity_sec = state_key_max_inactivity_sec
|
|
344
347
|
self.size_max_fractional_digits = size_max_fractional_digits
|
|
345
348
|
self.include_market_order_ticks = include_market_order_ticks
|
|
349
|
+
self._size_type = int
|
|
350
|
+
if self.size_max_fractional_digits > 0:
|
|
351
|
+
self._size_type = float # type: ignore[assignment]
|
|
346
352
|
super().__init__(*args, **kwargs)
|
|
347
353
|
|
|
348
354
|
def _param_validation(self):
|
|
@@ -357,12 +363,12 @@ class ObSummary(_OrderBookAggregation):
|
|
|
357
363
|
|
|
358
364
|
def _get_output_schema(self, src: 'Source', name: Optional[str] = None) -> dict:
|
|
359
365
|
schema = {
|
|
360
|
-
'BID_SIZE':
|
|
366
|
+
'BID_SIZE': self._size_type,
|
|
361
367
|
'BID_VWAP': float,
|
|
362
368
|
'BEST_BID_PRICE': float,
|
|
363
369
|
'WORST_BID_PRICE': float,
|
|
364
370
|
'NUM_BID_LEVELS': int,
|
|
365
|
-
'ASK_SIZE':
|
|
371
|
+
'ASK_SIZE': self._size_type,
|
|
366
372
|
'ASK_VWAP': float,
|
|
367
373
|
'BEST_ASK_PRICE': float,
|
|
368
374
|
'WORST_ASK_PRICE': float,
|
|
@@ -100,7 +100,7 @@ class Vwap(_Aggregation):
|
|
|
100
100
|
FIELDS_TO_SKIP: List = ['column_name']
|
|
101
101
|
|
|
102
102
|
output_field_type = float
|
|
103
|
-
require_type = (int, float, ott.nsectime)
|
|
103
|
+
require_type = (int, float, ott.nsectime, ott.decimal)
|
|
104
104
|
|
|
105
105
|
def __init__(self,
|
|
106
106
|
price_column: str,
|
|
@@ -271,7 +271,7 @@ class Average(_FloatAggregation):
|
|
|
271
271
|
class StdDev(_Aggregation): # Stddev does not support inf, so no need to use _FloatAggregation
|
|
272
272
|
NAME = "STDDEV"
|
|
273
273
|
EP = otq.Stddev
|
|
274
|
-
require_type = (int, float)
|
|
274
|
+
require_type = (int, float, ott.decimal)
|
|
275
275
|
output_field_type = float
|
|
276
276
|
FIELDS_MAPPING = deepcopy(_Aggregation.FIELDS_MAPPING)
|
|
277
277
|
FIELDS_MAPPING['biased'] = 'BIASED'
|
{onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/_source/source_methods/misc.py
RENAMED
|
@@ -618,6 +618,9 @@ def pnl_realized(
|
|
|
618
618
|
The name of the field with price, default is **PRICE**.
|
|
619
619
|
buy_sell_flag_field: str, :py:class:`otp.Column <onetick.py.Column>`
|
|
620
620
|
The name of the field with buy/sell flag, default is **BUY_SELL_FLAG**.
|
|
621
|
+
If the type of this field is string, then possible values are 'B' or 'b' for buy and 'S' or 's' for sell.
|
|
622
|
+
If the type of this field is integer, then possible values are 0 for buy and 1 for sell.
|
|
623
|
+
|
|
621
624
|
|
|
622
625
|
See also
|
|
623
626
|
--------
|
|
@@ -625,20 +628,63 @@ def pnl_realized(
|
|
|
625
628
|
|
|
626
629
|
Examples
|
|
627
630
|
--------
|
|
631
|
+
Let's generate some data:
|
|
628
632
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
633
|
+
>>> trades = otp.Ticks(
|
|
634
|
+
... PRICE=[1.0, 2.0, 3.0, 2.5, 4.0, 5.0, 6.0, 7.0, 3.0, 4.0, 1.0],
|
|
635
|
+
... SIZE=[700, 20, 570, 600, 100, 100, 100, 100, 150, 10, 100],
|
|
636
|
+
... SELL_FLAG=[0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1],
|
|
637
|
+
... SIDE=['B', 'B', 'B', 'S', 'S', 'S', 'S', 'S', 'B', 'B', 'S'],
|
|
638
|
+
... )
|
|
639
|
+
>>> otp.run(trades)
|
|
640
|
+
Time PRICE SIZE SELL_FLAG SIDE
|
|
641
|
+
0 2003-12-01 00:00:00.000 1.0 700 0 B
|
|
642
|
+
1 2003-12-01 00:00:00.001 2.0 20 0 B
|
|
643
|
+
2 2003-12-01 00:00:00.002 3.0 570 0 B
|
|
644
|
+
3 2003-12-01 00:00:00.003 2.5 600 1 S
|
|
645
|
+
4 2003-12-01 00:00:00.004 4.0 100 1 S
|
|
646
|
+
5 2003-12-01 00:00:00.005 5.0 100 1 S
|
|
647
|
+
6 2003-12-01 00:00:00.006 6.0 100 1 S
|
|
648
|
+
7 2003-12-01 00:00:00.007 7.0 100 1 S
|
|
649
|
+
8 2003-12-01 00:00:00.008 3.0 150 0 B
|
|
650
|
+
9 2003-12-01 00:00:00.009 4.0 10 0 B
|
|
651
|
+
10 2003-12-01 00:00:00.010 1.0 100 1 S
|
|
652
|
+
|
|
653
|
+
And then calculate profit and loss metric for it.
|
|
654
|
+
|
|
655
|
+
First let's use string ``buy_sell_flag_field`` field:
|
|
656
|
+
|
|
657
|
+
>>> data = trades.pnl_realized(buy_sell_flag_field='SIDE') # doctest: +SKIP
|
|
658
|
+
>>> otp.run(data)[['Time', 'PRICE', 'SIZE', 'SIDE', 'PNL_REALIZED']] # doctest: +SKIP
|
|
659
|
+
Time PRICE SIZE SIDE PNL_REALIZED
|
|
660
|
+
0 2003-12-01 00:00:00.000 1.0 700 B 0.0
|
|
661
|
+
1 2003-12-01 00:00:00.001 2.0 20 B 0.0
|
|
662
|
+
2 2003-12-01 00:00:00.002 3.0 570 B 0.0
|
|
663
|
+
3 2003-12-01 00:00:00.003 2.5 600 S 900.0
|
|
664
|
+
4 2003-12-01 00:00:00.004 4.0 100 S 300.0
|
|
665
|
+
5 2003-12-01 00:00:00.005 5.0 100 S 220.0
|
|
666
|
+
6 2003-12-01 00:00:00.006 6.0 100 S 300.0
|
|
667
|
+
7 2003-12-01 00:00:00.007 7.0 100 S 400.0
|
|
668
|
+
8 2003-12-01 00:00:00.008 3.0 150 B 0.0
|
|
669
|
+
9 2003-12-01 00:00:00.009 4.0 10 B 0.0
|
|
670
|
+
10 2003-12-01 00:00:00.010 1.0 100 S -200.0
|
|
671
|
+
|
|
672
|
+
We can get the same result using integer ``buy_sell_flag_field`` field:
|
|
673
|
+
|
|
674
|
+
>>> data = trades.pnl_realized(buy_sell_flag_field='SELL_FLAG') # doctest: +SKIP
|
|
675
|
+
>>> otp.run(data)[['Time', 'PRICE', 'SIZE', 'SELL_FLAG', 'PNL_REALIZED']] # doctest: +SKIP
|
|
676
|
+
Time PRICE SIZE SELL_FLAG PNL_REALIZED
|
|
677
|
+
0 2003-12-01 00:00:00.000 1.0 700 0 0.0
|
|
678
|
+
1 2003-12-01 00:00:00.001 2.0 20 0 0.0
|
|
679
|
+
2 2003-12-01 00:00:00.002 3.0 570 0 0.0
|
|
680
|
+
3 2003-12-01 00:00:00.003 2.5 600 1 900.0
|
|
681
|
+
4 2003-12-01 00:00:00.004 4.0 100 1 300.0
|
|
682
|
+
5 2003-12-01 00:00:00.005 5.0 100 1 220.0
|
|
683
|
+
6 2003-12-01 00:00:00.006 6.0 100 1 300.0
|
|
684
|
+
7 2003-12-01 00:00:00.007 7.0 100 1 400.0
|
|
685
|
+
8 2003-12-01 00:00:00.008 3.0 150 0 0.0
|
|
686
|
+
9 2003-12-01 00:00:00.009 4.0 10 0 0.0
|
|
687
|
+
10 2003-12-01 00:00:00.010 1.0 100 1 -200.0
|
|
642
688
|
"""
|
|
643
689
|
if computation_method not in ['fifo']:
|
|
644
690
|
raise ValueError(
|
|
@@ -31,7 +31,7 @@ def float_to_str(prev_op, dtype=str):
|
|
|
31
31
|
return MethodResult(op_str, dtype)
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
def
|
|
34
|
+
def num_to_decimal(prev_op):
|
|
35
35
|
return MethodResult(f'decimal({str(prev_op)})', ott.decimal)
|
|
36
36
|
|
|
37
37
|
|
|
@@ -192,7 +192,7 @@ class _ConversionsDict(UserDict):
|
|
|
192
192
|
|
|
193
193
|
CONVERSIONS = _ConversionsDict({(float, int): float_to_int,
|
|
194
194
|
(float, str): float_to_str,
|
|
195
|
-
(float, ott.decimal):
|
|
195
|
+
(float, ott.decimal): num_to_decimal,
|
|
196
196
|
(ott.decimal, int): float_to_int,
|
|
197
197
|
(ott.decimal, str): decimal_to_str,
|
|
198
198
|
(ott.decimal, float): decimal_to_float,
|
|
@@ -206,6 +206,7 @@ CONVERSIONS = _ConversionsDict({(float, int): float_to_int,
|
|
|
206
206
|
(int, float): int_to_float,
|
|
207
207
|
(int, ott.nsectime): int_to_nsectime,
|
|
208
208
|
(int, ott.msectime): int_to_msectime,
|
|
209
|
+
(int, ott.decimal): num_to_decimal,
|
|
209
210
|
(str, float): str_to_float,
|
|
210
211
|
(str, ott.decimal): str_to_decimal,
|
|
211
212
|
(str, int): str_to_int,
|
{onetick_py-1.173.0 → onetick_py-1.174.0}/src/onetick/py/core/column_operations/_methods/op_types.py
RENAMED
|
@@ -8,9 +8,12 @@ from onetick.py import types as ott
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def are_numerics(*dtypes):
|
|
11
|
-
return all(
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
return all(
|
|
12
|
+
inspect.isclass(dtype)
|
|
13
|
+
and (issubclass(dtype, (float, int)) or np.issubdtype(dtype, np.integer) or issubclass(dtype, ott.decimal))
|
|
14
|
+
and not issubclass(dtype, (ott.nsectime, ott.msectime))
|
|
15
|
+
for dtype in dtypes
|
|
16
|
+
)
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
def are_ints_not_time(*dtypes):
|
|
@@ -109,6 +112,12 @@ def _get_widest_type(left, right):
|
|
|
109
112
|
(<class '...MyTime'>, None, <class '...MyNSec'>)
|
|
110
113
|
"""
|
|
111
114
|
|
|
115
|
+
# decimal takes precedence before integer and floating point types
|
|
116
|
+
if issubclass(left, ott.decimal) and are_numerics(right):
|
|
117
|
+
return left
|
|
118
|
+
if are_numerics(left) and issubclass(right, ott.decimal):
|
|
119
|
+
return right
|
|
120
|
+
|
|
112
121
|
if issubclass(left, float) and issubclass(right, float):
|
|
113
122
|
# between np.float and float we choose base float
|
|
114
123
|
if left is not float and np.issubdtype(left, np.floating):
|
|
@@ -476,7 +476,7 @@ class Operation:
|
|
|
476
476
|
Property that provides access to
|
|
477
477
|
methods specific to float type.
|
|
478
478
|
"""
|
|
479
|
-
if issubclass(self.dtype, float)
|
|
479
|
+
if issubclass(self.dtype, float):
|
|
480
480
|
from onetick.py.core.column_operations.accessors.float_accessor import _FloatAccessor
|
|
481
481
|
return _FloatAccessor(self)
|
|
482
482
|
else:
|
|
@@ -1043,7 +1043,7 @@ class Raw(Operation):
|
|
|
1043
1043
|
def __init__(self, raw, dtype):
|
|
1044
1044
|
if dtype is str:
|
|
1045
1045
|
warnings.warn(
|
|
1046
|
-
f'Be careful, default string length in OneTick is {ott.string.DEFAULT_LENGTH}.'
|
|
1046
|
+
f'Be careful, default string length in OneTick is {ott.string.DEFAULT_LENGTH}. '
|
|
1047
1047
|
"Length of the result raw expression can't be calculated automatically, "
|
|
1048
1048
|
"so you'd better use onetick.py.string type.",
|
|
1049
1049
|
stacklevel=2,
|
|
@@ -947,7 +947,9 @@ class Source:
|
|
|
947
947
|
view: bool = False,
|
|
948
948
|
line_limit: Optional[Tuple[int, int]] = (10, 30),
|
|
949
949
|
parse_eval_from_params: bool = False,
|
|
950
|
+
render_debug_info: bool = False,
|
|
950
951
|
debug: bool = False,
|
|
952
|
+
graphviz_compat_mode: bool = False,
|
|
951
953
|
**kwargs,
|
|
952
954
|
):
|
|
953
955
|
"""
|
|
@@ -973,8 +975,13 @@ class Source:
|
|
|
973
975
|
If one of tuple values set to zero the corresponding limit disabled.
|
|
974
976
|
parse_eval_from_params: bool
|
|
975
977
|
Enable parsing and printing `eval` sub-queries from EP parameters.
|
|
978
|
+
render_debug_info: bool
|
|
979
|
+
Render additional debug information.
|
|
976
980
|
debug: bool
|
|
977
981
|
Allow to print stdout or stderr from `Graphviz` render.
|
|
982
|
+
graphviz_compat_mode: bool
|
|
983
|
+
Change internal parameters of result graph for better compatibility with old `Graphviz` versions.
|
|
984
|
+
Could produce larger and less readable graphs.
|
|
978
985
|
kwargs:
|
|
979
986
|
Additional arguments to be passed to :py:meth:`onetick.py.Source.to_otq` method (except
|
|
980
987
|
``file_name``, ``file_suffix`` and ``query_name`` parameters)
|
|
@@ -1006,7 +1013,8 @@ class Source:
|
|
|
1006
1013
|
|
|
1007
1014
|
otq_path = self.to_otq(**kwargs)
|
|
1008
1015
|
return render_otq(
|
|
1009
|
-
otq_path, image_path, output_format, load_external_otqs, view, line_limit, parse_eval_from_params,
|
|
1016
|
+
otq_path, image_path, output_format, load_external_otqs, view, line_limit, parse_eval_from_params,
|
|
1017
|
+
render_debug_info, debug, graphviz_compat_mode,
|
|
1010
1018
|
)
|
|
1011
1019
|
|
|
1012
1020
|
def copy(self, ep=None, columns=None, deep=False) -> 'Source':
|
|
@@ -327,6 +327,7 @@ def merge(sources, align_schema=True, symbols=None, identify_input_ts=False,
|
|
|
327
327
|
|
|
328
328
|
if enforce_order:
|
|
329
329
|
result.drop('OMDSEQ', inplace=True)
|
|
330
|
+
merged_columns.pop('OMDSEQ')
|
|
330
331
|
|
|
331
332
|
if identify_input_ts:
|
|
332
333
|
result.schema['SYMBOL_NAME' + added_field_name_suffix] = str
|
|
@@ -2030,7 +2031,7 @@ def _add_element(cur_res, element, format_spec_additional=None):
|
|
|
2030
2031
|
if isinstance(element, Operation):
|
|
2031
2032
|
if format_spec_additional is None:
|
|
2032
2033
|
cur_res += element.apply(str)
|
|
2033
|
-
elif issubclass(element.dtype, float) and re.fullmatch(r'\.\d+f', format_spec_additional):
|
|
2034
|
+
elif issubclass(element.dtype, (float, ott.decimal)) and re.fullmatch(r'\.\d+f', format_spec_additional):
|
|
2034
2035
|
# float has strange behavior when precision=0
|
|
2035
2036
|
decimal_elem = element.apply(ott.decimal)
|
|
2036
2037
|
precision_str = re.findall(r'\d+', format_spec_additional)[0]
|
|
@@ -2047,7 +2048,7 @@ def _add_element(cur_res, element, format_spec_additional=None):
|
|
|
2047
2048
|
else:
|
|
2048
2049
|
if format_spec_additional is None:
|
|
2049
2050
|
cur_res += str(element)
|
|
2050
|
-
elif isinstance(element, float):
|
|
2051
|
+
elif isinstance(element, (float, ott.decimal)):
|
|
2051
2052
|
formatting = f'{{:{format_spec_additional}}}'
|
|
2052
2053
|
cur_res += formatting.format(element)
|
|
2053
2054
|
else:
|
|
@@ -2,6 +2,7 @@ import ctypes
|
|
|
2
2
|
import functools
|
|
3
3
|
import inspect
|
|
4
4
|
import warnings
|
|
5
|
+
import decimal as _decimal
|
|
5
6
|
from typing import Optional, Type, Union
|
|
6
7
|
from datetime import date as _date
|
|
7
8
|
from datetime import datetime as _datetime
|
|
@@ -707,18 +708,23 @@ class _inf(float, metaclass=_nan_base):
|
|
|
707
708
|
inf = _inf()
|
|
708
709
|
|
|
709
710
|
|
|
710
|
-
class
|
|
711
|
-
def __str__(cls):
|
|
712
|
-
return 'decimal'
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
class decimal(float, metaclass=_decimal_str):
|
|
711
|
+
class decimal:
|
|
716
712
|
"""
|
|
717
713
|
Object that represents decimal OneTick value.
|
|
718
714
|
Decimal is 128 bit base 10 floating point number.
|
|
719
715
|
|
|
716
|
+
Parameters
|
|
717
|
+
----------
|
|
718
|
+
value: int, float, str
|
|
719
|
+
The value to initialize decimal from.
|
|
720
|
+
Note that float values may be converted with precision lost.
|
|
721
|
+
|
|
720
722
|
Examples
|
|
721
723
|
--------
|
|
724
|
+
|
|
725
|
+
:py:class:`~onetick.py.types.decimal` objects can be used in tick generators
|
|
726
|
+
and column operations as any other onetick-py type:
|
|
727
|
+
|
|
722
728
|
>>> t = otp.Ticks({'A': [otp.decimal(1), otp.decimal(2)]})
|
|
723
729
|
>>> t['B'] = otp.decimal(1.23456789)
|
|
724
730
|
>>> t['C'] = t['A'] / 0
|
|
@@ -727,43 +733,107 @@ class decimal(float, metaclass=_decimal_str):
|
|
|
727
733
|
Time A B C D
|
|
728
734
|
0 2003-12-01 00:00:00.000 1.0 1.234568 inf NaN
|
|
729
735
|
1 2003-12-01 00:00:00.001 2.0 1.234568 inf NaN
|
|
730
|
-
"""
|
|
731
|
-
def __wrap(self, res):
|
|
732
|
-
# if parent class doesn't support some operation, it returns NotImplemented and so do we
|
|
733
|
-
# In other case we wrap float result with our decimal class
|
|
734
|
-
if isinstance(res, type(NotImplemented)):
|
|
735
|
-
return NotImplemented
|
|
736
|
-
return self.__class__(res)
|
|
737
|
-
|
|
738
|
-
def __add__(self, other):
|
|
739
|
-
return self.__wrap(super().__add__(other))
|
|
740
736
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
def __sub__(self, other):
|
|
745
|
-
return self.__wrap(super().__sub__(other))
|
|
737
|
+
Additionally, any arithmetic operation with :py:class:`~onetick.py.types.decimal` object will return
|
|
738
|
+
an :py:class:`~onetick.py.Operation` object:
|
|
746
739
|
|
|
747
|
-
|
|
748
|
-
|
|
740
|
+
>>> t = otp.Tick(A=1)
|
|
741
|
+
>>> t['X'] = otp.decimal(1) / 0
|
|
742
|
+
>>> otp.run(t)
|
|
743
|
+
Time A X
|
|
744
|
+
0 2003-12-01 1 inf
|
|
745
|
+
|
|
746
|
+
Note that converting from float (first row) may result in losing precision.
|
|
747
|
+
:py:class:`~onetick.py.types.decimal` objects are created from strings or integers, so they don't lose precision:
|
|
748
|
+
|
|
749
|
+
>>> t0 = otp.Tick(A=0.1)
|
|
750
|
+
>>> t1 = otp.Tick(A=otp.decimal(0.01))
|
|
751
|
+
>>> t2 = otp.Tick(A=otp.decimal('0.001'))
|
|
752
|
+
>>> t3 = otp.Tick(A=otp.decimal(1) / otp.decimal(10_000))
|
|
753
|
+
>>> t = otp.merge([t0, t1, t2, t3], enforce_order=True)
|
|
754
|
+
>>> t['STR_A'] = t['A'].decimal.str(34)
|
|
755
|
+
>>> otp.run(t)
|
|
756
|
+
Time A STR_A
|
|
757
|
+
0 2003-12-01 0.1000 0.1000000000000000055511151231257827
|
|
758
|
+
1 2003-12-01 0.0100 0.0100000000000000000000000000000000
|
|
759
|
+
2 2003-12-01 0.0010 0.0010000000000000000000000000000000
|
|
760
|
+
3 2003-12-01 0.0001 0.0001000000000000000000000000000000
|
|
749
761
|
|
|
750
|
-
|
|
751
|
-
|
|
762
|
+
Note that :py:class:`otp.Ticks <onetick.py.Ticks>` will convert everything from string under the hood,
|
|
763
|
+
so even the float values will not lose precision:
|
|
752
764
|
|
|
753
|
-
|
|
754
|
-
|
|
765
|
+
>>> t = otp.Ticks({'A': [0.1, otp.decimal(0.01), otp.decimal('0.001'), otp.decimal(1e-4)]})
|
|
766
|
+
>>> t['STR_A'] = t['A'].decimal.str(34)
|
|
767
|
+
>>> otp.run(t)
|
|
768
|
+
Time A STR_A
|
|
769
|
+
0 2003-12-01 00:00:00.000 0.1000 0.1000000000000000000000000000000000
|
|
770
|
+
1 2003-12-01 00:00:00.001 0.0100 0.0100000000000000000000000000000000
|
|
771
|
+
2 2003-12-01 00:00:00.002 0.0010 0.0010000000000000000000000000000000
|
|
772
|
+
3 2003-12-01 00:00:00.003 0.0001 0.0001000000000000000000000000000000
|
|
773
|
+
"""
|
|
774
|
+
def __new__(cls, *args, **kwargs):
|
|
775
|
+
# this method dynamically adds properties and methods
|
|
776
|
+
# from otp.Operation class to this one
|
|
777
|
+
|
|
778
|
+
# otp.decimal class doesn't fit well in onetick-py type system,
|
|
779
|
+
# so this class is a mix of both type and Operation logic
|
|
780
|
+
|
|
781
|
+
# Basically it works like this:
|
|
782
|
+
# otp.decimal is a OneTick type
|
|
783
|
+
# otp.decimal(1) is a decimal type object
|
|
784
|
+
# Doing anything with this object returns an otp.Operation:
|
|
785
|
+
# otp.decimal(1) / 2
|
|
786
|
+
|
|
787
|
+
def proxy_wrap(attr, value):
|
|
788
|
+
if callable(value):
|
|
789
|
+
@functools.wraps(value)
|
|
790
|
+
def f(self, *args, **kwargs):
|
|
791
|
+
op = self.to_operation()
|
|
792
|
+
return getattr(op, attr)(*args, **kwargs)
|
|
793
|
+
return f
|
|
794
|
+
else:
|
|
795
|
+
@functools.wraps(value)
|
|
796
|
+
def f(self):
|
|
797
|
+
op = self.to_operation()
|
|
798
|
+
return getattr(op, attr)
|
|
799
|
+
return property(f)
|
|
800
|
+
|
|
801
|
+
for attr, value in inspect.getmembers(otp.Operation):
|
|
802
|
+
# comparison methods are defined by default for some reason,
|
|
803
|
+
# but we want to get them from otp.Operation
|
|
804
|
+
if not hasattr(cls, attr) or attr in ('__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__'):
|
|
805
|
+
setattr(cls, attr, proxy_wrap(attr, value))
|
|
806
|
+
|
|
807
|
+
return super().__new__(cls)
|
|
808
|
+
|
|
809
|
+
def __init__(self, value):
|
|
810
|
+
supported_types = (str, int, float)
|
|
811
|
+
if not isinstance(value, supported_types):
|
|
812
|
+
raise TypeError("Parameter 'value' must be one of these types: {supported_types}")
|
|
813
|
+
self.__value = value
|
|
814
|
+
|
|
815
|
+
@classmethod
|
|
816
|
+
def _to_onetick_type_string(cls):
|
|
817
|
+
# called by ott.type2str
|
|
818
|
+
return 'decimal'
|
|
755
819
|
|
|
756
|
-
def
|
|
757
|
-
|
|
820
|
+
def _to_onetick_string(self):
|
|
821
|
+
# called by ott.value2str
|
|
822
|
+
value = str(self.__value)
|
|
823
|
+
return f'STRING_TO_DECIMAL({value2str(value)})'
|
|
758
824
|
|
|
759
|
-
def
|
|
760
|
-
return
|
|
825
|
+
def to_operation(self):
|
|
826
|
+
return otp.Operation(op_str=self._to_onetick_string(), dtype=decimal)
|
|
761
827
|
|
|
762
828
|
def __str__(self):
|
|
763
|
-
|
|
829
|
+
# called by otp.CSV, we don't need to convert the value with OneTick functions in this case
|
|
830
|
+
return str(self.__value)
|
|
764
831
|
|
|
765
832
|
def __repr__(self):
|
|
766
|
-
return f"{self.__class__.__name__}({self})"
|
|
833
|
+
return f"{self.__class__.__name__}({value2str(self.__value)})"
|
|
834
|
+
|
|
835
|
+
def __format__(self, __format_spec: str) -> str:
|
|
836
|
+
return _decimal.Decimal(self.__value).__format__(__format_spec)
|
|
767
837
|
|
|
768
838
|
# --------------------------------------------------------------- #
|
|
769
839
|
# AUXILIARY FUNCTIONS
|
|
@@ -809,7 +879,7 @@ def get_source_base_type(value):
|
|
|
809
879
|
value_type = nsectime
|
|
810
880
|
|
|
811
881
|
# check valid value type
|
|
812
|
-
if get_base_type(value_type) not in [int, float, str, bool]:
|
|
882
|
+
if get_base_type(value_type) not in [int, float, str, bool, decimal]:
|
|
813
883
|
raise TypeError(f'Type "{repr(value_type)}" is not supported.')
|
|
814
884
|
|
|
815
885
|
if not is_type_basic(value_type):
|
|
@@ -818,7 +888,7 @@ def get_source_base_type(value):
|
|
|
818
888
|
|
|
819
889
|
|
|
820
890
|
def is_type_supported(dtype):
|
|
821
|
-
return get_base_type(dtype) in [int, float, str, bool] or issubclass(dtype, (datetime, date))
|
|
891
|
+
return get_base_type(dtype) in [int, float, str, bool, decimal] or issubclass(dtype, (datetime, date))
|
|
822
892
|
|
|
823
893
|
|
|
824
894
|
def get_base_type(obj):
|
|
@@ -830,6 +900,8 @@ def get_base_type(obj):
|
|
|
830
900
|
return int
|
|
831
901
|
elif issubclass(obj, float):
|
|
832
902
|
return float
|
|
903
|
+
elif issubclass(obj, decimal):
|
|
904
|
+
return decimal
|
|
833
905
|
|
|
834
906
|
return type(None)
|
|
835
907
|
|
|
@@ -1686,6 +1758,8 @@ def type2str(t):
|
|
|
1686
1758
|
return "double"
|
|
1687
1759
|
if t is None:
|
|
1688
1760
|
return ''
|
|
1761
|
+
if t is decimal:
|
|
1762
|
+
return t._to_onetick_type_string()
|
|
1689
1763
|
return str(t)
|
|
1690
1764
|
|
|
1691
1765
|
|
|
@@ -1841,15 +1915,16 @@ def value2str(v):
|
|
|
1841
1915
|
# there is no escape, so replacing double quotes with concatenation with it
|
|
1842
1916
|
return '"' + str(v).replace('"', '''"+'"'+"''') + '"'
|
|
1843
1917
|
|
|
1844
|
-
if isinstance(v,
|
|
1918
|
+
if isinstance(v, decimal):
|
|
1919
|
+
return v._to_onetick_string()
|
|
1920
|
+
|
|
1921
|
+
if isinstance(v, float) and not (isinstance(v, (_inf, _nan))):
|
|
1845
1922
|
# PY-286: support science notation
|
|
1846
1923
|
s = str(v)
|
|
1847
1924
|
if "e" in s:
|
|
1848
|
-
|
|
1925
|
+
return f'atof({value2str(s)})'
|
|
1849
1926
|
if s == "nan":
|
|
1850
1927
|
return str(nan)
|
|
1851
|
-
if isinstance(v, decimal):
|
|
1852
|
-
return f'DECIMAL({s})'
|
|
1853
1928
|
return s
|
|
1854
1929
|
|
|
1855
1930
|
if is_time_type(v):
|
|
@@ -1960,7 +2035,7 @@ def default_by_type(dtype):
|
|
|
1960
2035
|
>>> otp.default_by_type(float)
|
|
1961
2036
|
nan
|
|
1962
2037
|
>>> otp.default_by_type(otp.decimal)
|
|
1963
|
-
decimal(0
|
|
2038
|
+
decimal(0)
|
|
1964
2039
|
>>> otp.default_by_type(int)
|
|
1965
2040
|
0
|
|
1966
2041
|
>>> otp.default_by_type(otp.ulong)
|