onetick-py 1.177.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. locator_parser/__init__.py +0 -0
  2. locator_parser/acl.py +73 -0
  3. locator_parser/actions.py +262 -0
  4. locator_parser/common.py +368 -0
  5. locator_parser/io.py +43 -0
  6. locator_parser/locator.py +150 -0
  7. onetick/__init__.py +101 -0
  8. onetick/doc_utilities/__init__.py +3 -0
  9. onetick/doc_utilities/napoleon.py +40 -0
  10. onetick/doc_utilities/ot_doctest.py +140 -0
  11. onetick/doc_utilities/snippets.py +279 -0
  12. onetick/lib/__init__.py +4 -0
  13. onetick/lib/instance.py +141 -0
  14. onetick/py/__init__.py +293 -0
  15. onetick/py/_stack_info.py +89 -0
  16. onetick/py/_version.py +2 -0
  17. onetick/py/aggregations/__init__.py +11 -0
  18. onetick/py/aggregations/_base.py +648 -0
  19. onetick/py/aggregations/_docs.py +948 -0
  20. onetick/py/aggregations/compute.py +286 -0
  21. onetick/py/aggregations/functions.py +2216 -0
  22. onetick/py/aggregations/generic.py +104 -0
  23. onetick/py/aggregations/high_low.py +80 -0
  24. onetick/py/aggregations/num_distinct.py +83 -0
  25. onetick/py/aggregations/order_book.py +501 -0
  26. onetick/py/aggregations/other.py +1014 -0
  27. onetick/py/backports.py +26 -0
  28. onetick/py/cache.py +374 -0
  29. onetick/py/callback/__init__.py +5 -0
  30. onetick/py/callback/callback.py +276 -0
  31. onetick/py/callback/callbacks.py +131 -0
  32. onetick/py/compatibility.py +798 -0
  33. onetick/py/configuration.py +771 -0
  34. onetick/py/core/__init__.py +0 -0
  35. onetick/py/core/_csv_inspector.py +93 -0
  36. onetick/py/core/_internal/__init__.py +0 -0
  37. onetick/py/core/_internal/_manually_bound_value.py +6 -0
  38. onetick/py/core/_internal/_nodes_history.py +250 -0
  39. onetick/py/core/_internal/_op_utils/__init__.py +0 -0
  40. onetick/py/core/_internal/_op_utils/every_operand.py +9 -0
  41. onetick/py/core/_internal/_op_utils/is_const.py +10 -0
  42. onetick/py/core/_internal/_per_tick_scripts/tick_list_sort_template.script +121 -0
  43. onetick/py/core/_internal/_proxy_node.py +140 -0
  44. onetick/py/core/_internal/_state_objects.py +2312 -0
  45. onetick/py/core/_internal/_state_vars.py +93 -0
  46. onetick/py/core/_source/__init__.py +0 -0
  47. onetick/py/core/_source/_symbol_param.py +95 -0
  48. onetick/py/core/_source/schema.py +97 -0
  49. onetick/py/core/_source/source_methods/__init__.py +0 -0
  50. onetick/py/core/_source/source_methods/aggregations.py +809 -0
  51. onetick/py/core/_source/source_methods/applyers.py +296 -0
  52. onetick/py/core/_source/source_methods/columns.py +141 -0
  53. onetick/py/core/_source/source_methods/data_quality.py +301 -0
  54. onetick/py/core/_source/source_methods/debugs.py +272 -0
  55. onetick/py/core/_source/source_methods/drops.py +120 -0
  56. onetick/py/core/_source/source_methods/fields.py +619 -0
  57. onetick/py/core/_source/source_methods/filters.py +1002 -0
  58. onetick/py/core/_source/source_methods/joins.py +1413 -0
  59. onetick/py/core/_source/source_methods/merges.py +605 -0
  60. onetick/py/core/_source/source_methods/misc.py +1455 -0
  61. onetick/py/core/_source/source_methods/pandases.py +155 -0
  62. onetick/py/core/_source/source_methods/renames.py +356 -0
  63. onetick/py/core/_source/source_methods/sorts.py +183 -0
  64. onetick/py/core/_source/source_methods/switches.py +142 -0
  65. onetick/py/core/_source/source_methods/symbols.py +117 -0
  66. onetick/py/core/_source/source_methods/times.py +627 -0
  67. onetick/py/core/_source/source_methods/writes.py +986 -0
  68. onetick/py/core/_source/symbol.py +205 -0
  69. onetick/py/core/_source/tmp_otq.py +222 -0
  70. onetick/py/core/column.py +209 -0
  71. onetick/py/core/column_operations/__init__.py +0 -0
  72. onetick/py/core/column_operations/_methods/__init__.py +4 -0
  73. onetick/py/core/column_operations/_methods/_internal.py +28 -0
  74. onetick/py/core/column_operations/_methods/conversions.py +216 -0
  75. onetick/py/core/column_operations/_methods/methods.py +292 -0
  76. onetick/py/core/column_operations/_methods/op_types.py +160 -0
  77. onetick/py/core/column_operations/accessors/__init__.py +0 -0
  78. onetick/py/core/column_operations/accessors/_accessor.py +28 -0
  79. onetick/py/core/column_operations/accessors/decimal_accessor.py +104 -0
  80. onetick/py/core/column_operations/accessors/dt_accessor.py +537 -0
  81. onetick/py/core/column_operations/accessors/float_accessor.py +184 -0
  82. onetick/py/core/column_operations/accessors/str_accessor.py +1367 -0
  83. onetick/py/core/column_operations/base.py +1121 -0
  84. onetick/py/core/cut_builder.py +150 -0
  85. onetick/py/core/db_constants.py +20 -0
  86. onetick/py/core/eval_query.py +245 -0
  87. onetick/py/core/lambda_object.py +441 -0
  88. onetick/py/core/multi_output_source.py +232 -0
  89. onetick/py/core/per_tick_script.py +2256 -0
  90. onetick/py/core/query_inspector.py +464 -0
  91. onetick/py/core/source.py +1744 -0
  92. onetick/py/db/__init__.py +2 -0
  93. onetick/py/db/_inspection.py +1128 -0
  94. onetick/py/db/db.py +1327 -0
  95. onetick/py/db/utils.py +64 -0
  96. onetick/py/docs/__init__.py +0 -0
  97. onetick/py/docs/docstring_parser.py +112 -0
  98. onetick/py/docs/utils.py +81 -0
  99. onetick/py/functions.py +2398 -0
  100. onetick/py/license.py +190 -0
  101. onetick/py/log.py +88 -0
  102. onetick/py/math.py +935 -0
  103. onetick/py/misc.py +470 -0
  104. onetick/py/oqd/__init__.py +22 -0
  105. onetick/py/oqd/eps.py +1195 -0
  106. onetick/py/oqd/sources.py +325 -0
  107. onetick/py/otq.py +216 -0
  108. onetick/py/pyomd_mock.py +47 -0
  109. onetick/py/run.py +916 -0
  110. onetick/py/servers.py +173 -0
  111. onetick/py/session.py +1347 -0
  112. onetick/py/sources/__init__.py +19 -0
  113. onetick/py/sources/cache.py +167 -0
  114. onetick/py/sources/common.py +128 -0
  115. onetick/py/sources/csv.py +642 -0
  116. onetick/py/sources/custom.py +85 -0
  117. onetick/py/sources/data_file.py +305 -0
  118. onetick/py/sources/data_source.py +1045 -0
  119. onetick/py/sources/empty.py +94 -0
  120. onetick/py/sources/odbc.py +337 -0
  121. onetick/py/sources/order_book.py +271 -0
  122. onetick/py/sources/parquet.py +168 -0
  123. onetick/py/sources/pit.py +191 -0
  124. onetick/py/sources/query.py +495 -0
  125. onetick/py/sources/snapshots.py +419 -0
  126. onetick/py/sources/split_query_output_by_symbol.py +198 -0
  127. onetick/py/sources/symbology_mapping.py +123 -0
  128. onetick/py/sources/symbols.py +374 -0
  129. onetick/py/sources/ticks.py +825 -0
  130. onetick/py/sql.py +70 -0
  131. onetick/py/state.py +251 -0
  132. onetick/py/types.py +2131 -0
  133. onetick/py/utils/__init__.py +70 -0
  134. onetick/py/utils/acl.py +93 -0
  135. onetick/py/utils/config.py +186 -0
  136. onetick/py/utils/default.py +49 -0
  137. onetick/py/utils/file.py +38 -0
  138. onetick/py/utils/helpers.py +76 -0
  139. onetick/py/utils/locator.py +94 -0
  140. onetick/py/utils/perf.py +498 -0
  141. onetick/py/utils/query.py +49 -0
  142. onetick/py/utils/render.py +1374 -0
  143. onetick/py/utils/script.py +244 -0
  144. onetick/py/utils/temp.py +471 -0
  145. onetick/py/utils/types.py +120 -0
  146. onetick/py/utils/tz.py +84 -0
  147. onetick_py-1.177.0.dist-info/METADATA +137 -0
  148. onetick_py-1.177.0.dist-info/RECORD +152 -0
  149. onetick_py-1.177.0.dist-info/WHEEL +5 -0
  150. onetick_py-1.177.0.dist-info/entry_points.txt +2 -0
  151. onetick_py-1.177.0.dist-info/licenses/LICENSE +21 -0
  152. onetick_py-1.177.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,70 @@
1
+ from .helpers import (
2
+ get_symbol_list_from_df,
3
+ JSONEncoder,
4
+ json_dumps,
5
+ query_properties_to_dict,
6
+ query_properties_from_dict,
7
+ symbol_date_to_str,
8
+ )
9
+ from .temp import (
10
+ File,
11
+ PermanentFile,
12
+ TmpFile,
13
+ TmpDir,
14
+ GeneratedDir,
15
+ TMP_CONFIGS_DIR,
16
+ ONE_TICK_TMP_DIR,
17
+ )
18
+ from .default import (
19
+ get_local_number_of_cores,
20
+ default_license_dir,
21
+ default_license_file,
22
+ default_day_boundary_tz,
23
+ )
24
+ from .acl import (
25
+ if_db_in_acl,
26
+ add_user_to_acl,
27
+ remove_user_from_acl,
28
+ if_user_in_acl,
29
+ tmp_acl,
30
+ )
31
+ from .config import (
32
+ reload_config,
33
+ modify_config_param,
34
+ get_config_param,
35
+ is_param_in_config,
36
+ tmp_config,
37
+ )
38
+ from .locator import (
39
+ get_dbs_locations_from_locator,
40
+ tmp_locator,
41
+ empty_locator,
42
+ )
43
+ from .script import (
44
+ write_config_for_tick_server_run,
45
+ create_file_to_run_config,
46
+ omd_dist_path,
47
+ )
48
+ from .query import (
49
+ abspath_to_query_by_otq_path,
50
+ abspath_to_query_by_name,
51
+ query_to_path_and_name,
52
+ )
53
+ from .types import (
54
+ get_type_that_includes,
55
+ adaptive,
56
+ adaptive_to_default,
57
+ default,
58
+ range,
59
+ )
60
+ from .tz import (
61
+ get_tzfile_by_name,
62
+ get_timezone_from_datetime,
63
+ convert_timezone,
64
+ )
65
+ from .file import (
66
+ FileBuffer,
67
+ file,
68
+ )
69
+ from .render import render_otq
70
+ from . import perf
@@ -0,0 +1,93 @@
1
+ import getpass
2
+ import os
3
+
4
+ from locator_parser.io import PrintWriter, FileReader, FileWriter
5
+ from locator_parser.actions import Get, Add, Delete
6
+ from locator_parser.acl import DB, User, Role, parse_acl
7
+ from locator_parser.common import apply_actions
8
+
9
+ from .temp import TmpFile
10
+ from .types import default
11
+
12
+
13
+ def if_db_in_acl(acl, db_name):
14
+ get_db = Get()
15
+ get_db.add_where(DB, id=db_name)
16
+
17
+ return apply_actions(parse_acl, FileReader(acl), PrintWriter(), [get_db], flush=True)
18
+
19
+
20
+ def add_user_to_acl(acl, user):
21
+ add_user = Add(User(name=user))
22
+ add_user.add_where(Role, name="Admin")
23
+
24
+ assert apply_actions(parse_acl, FileReader(acl), FileWriter(acl), [add_user], flush=True)
25
+
26
+
27
+ def remove_user_from_acl(acl, user):
28
+ remove_user = Delete()
29
+ remove_user.add_where(Role, name="Admin")
30
+ remove_user.add_where(User, name=user)
31
+
32
+ assert apply_actions(parse_acl, FileReader(acl), FileWriter(acl), [remove_user], flush=True)
33
+
34
+
35
+ def if_user_in_acl(acl, user):
36
+ get_user = Get()
37
+ get_user.add_where(Role, name="Admin")
38
+ get_user.add_where(User, name=user)
39
+
40
+ return apply_actions(parse_acl, FileReader(acl), PrintWriter(), [get_user], flush=True)
41
+
42
+
43
+ def tmp_acl(clean_up=default):
44
+ data = []
45
+ data.append("<roles>")
46
+ data.append('<role name="Admin">')
47
+ data.append(f'<user name="{getpass.getuser()}" />')
48
+ data.append('<user name="onetick" />')
49
+
50
+ ext_users = os.environ.get("TEST_SESSION_ACL_USERS", None)
51
+
52
+ if ext_users:
53
+ for usr in ext_users.split(","):
54
+ data.append(f'<user name="{usr}" />')
55
+
56
+ data.append("</role>")
57
+ data.append("</roles>")
58
+
59
+ data.append("<databases>")
60
+ data.append("</databases>")
61
+
62
+ data.append("<event_processors>")
63
+ data.append("")
64
+ data.append('<ep ID="RELOAD_CONFIG">')
65
+ data.append('<allow role="Admin" />')
66
+ data.append("</ep>")
67
+ data.append("")
68
+ data.append('<ep ID="WRITE_TEXT">')
69
+ data.append('<allow role="Admin" />')
70
+ data.append("</ep>")
71
+ data.append("")
72
+ data.append('<ep ID="COMMAND_EXECUTE">')
73
+ data.append('<allow role="Admin" />')
74
+ data.append("</ep>")
75
+ data.append("")
76
+ data.append('<ep ID="READ_FROM_RAW">')
77
+ data.append('<allow role="Admin" />')
78
+ data.append("</ep>")
79
+ data.append("")
80
+ data.append('<ep ID="SAVE_SNAPSHOT">')
81
+ data.append('<allow role="Admin" />')
82
+ data.append("</ep>")
83
+ data.append("</event_processors>")
84
+
85
+ if os.getenv('OTP_WEBAPI_TEST_MODE'):
86
+ tmp_file = TmpFile(name="acl.xml", clean_up=clean_up, force=True)
87
+ else:
88
+ tmp_file = TmpFile(suffix=".acl", clean_up=clean_up)
89
+
90
+ with open(tmp_file, "w") as fout:
91
+ fout.write("\n".join(data))
92
+
93
+ return tmp_file
@@ -0,0 +1,186 @@
1
+ import difflib
2
+ import os
3
+ import sysconfig
4
+ import warnings
5
+ from collections import OrderedDict
6
+
7
+ from onetick.py.otq import otq
8
+
9
+ from .temp import TmpFile, TmpDir, ONE_TICK_TMP_DIR
10
+ from ..core import db_constants
11
+ from . import types
12
+
13
+
14
+ def reload_config(db=None, config_type='LOCATOR'):
15
+ import onetick.py as otp
16
+
17
+ if db is not None:
18
+ warnings.warn("Parameter 'db' is deprecated and has no meaning")
19
+
20
+ return otp.run(
21
+ otq.ReloadConfig(config_type=config_type).tick_type('ANY'),
22
+ symbols='LOCAL::',
23
+ # start and end times don't matter for this query, use some constants
24
+ start=db_constants.DEFAULT_START_DATE,
25
+ end=db_constants.DEFAULT_END_DATE,
26
+ )
27
+
28
+
29
+ def _remove_quotes(s):
30
+ return s.replace('"', "").replace("'", "")
31
+
32
+
33
+ def _read_config_params(path, _included_paths=None):
34
+ params = OrderedDict()
35
+
36
+ if _included_paths is None:
37
+ _included_paths = set()
38
+
39
+ with open(path, "r") as fin:
40
+ for line in fin:
41
+ line = line.strip()
42
+
43
+ if line.startswith("#"):
44
+ continue
45
+
46
+ if line.startswith("INCLUDE"):
47
+ included_path = os.path.expandvars(_remove_quotes(line.split()[1]))
48
+ if included_path in _included_paths:
49
+ raise RecursionError(f"Path '{included_path}' is included more than once")
50
+ _included_paths.add(included_path)
51
+ included_params = _read_config_params(included_path, _included_paths)
52
+ params.update({
53
+ k: v for k, v in included_params.items()
54
+ if k not in params
55
+ })
56
+ continue
57
+
58
+ values = line.split("=")
59
+ key, value = values[0].strip(), os.path.expandvars("".join(values[1:]).strip())
60
+
61
+ if key and key not in params:
62
+ params[key] = value.strip()
63
+
64
+ return params
65
+
66
+
67
+ def _write_config_params(path, params):
68
+ with open(path, "w") as fout:
69
+ for key, value in params.items():
70
+ fout.write(f"{key}={value}\n")
71
+
72
+
73
+ def _check_param_in_params(param, params, throw_exception=True):
74
+ if param in params:
75
+ return True
76
+ if not throw_exception:
77
+ return False
78
+ closest = difflib.get_close_matches(param, params.keys())
79
+ msg = f"Parameter '{param}' is not in the config file."
80
+ if closest:
81
+ msg = f"{msg} It might be you supposed '{closest[0]}'?"
82
+ raise AttributeError(msg)
83
+
84
+
85
+ def modify_config_param(path, param, value, throw_on_missing=True):
86
+ params = _read_config_params(path)
87
+
88
+ _check_param_in_params(param, params, throw_on_missing)
89
+
90
+ params[param] = f'"{value}"'
91
+
92
+ _write_config_params(path, params)
93
+
94
+
95
+ def get_config_param(path, param, default=None):
96
+ params = _read_config_params(path)
97
+
98
+ res = _check_param_in_params(param, params, throw_exception=(default is None))
99
+
100
+ if res:
101
+ return _remove_quotes(params[param])
102
+ return default
103
+
104
+
105
+ def is_param_in_config(path, param):
106
+ params = _read_config_params(path)
107
+
108
+ return _check_param_in_params(param, params, throw_exception=False)
109
+
110
+
111
+ def tmp_config(
112
+ locator=None,
113
+ acl=None,
114
+ otq_path=None,
115
+ csv_path=None,
116
+ clean_up=types.default,
117
+ license_path=None,
118
+ license_dir=None,
119
+ license_servers=None,
120
+ ):
121
+ data = []
122
+
123
+ if otq_path is None:
124
+ otq_path = []
125
+
126
+ if ONE_TICK_TMP_DIR():
127
+ otq_path.append(ONE_TICK_TMP_DIR())
128
+
129
+ if csv_path is None:
130
+ csv_path = []
131
+
132
+ otq_path = list(map(os.path.normpath, otq_path))
133
+ csv_path = list(map(os.path.normpath, csv_path))
134
+
135
+ data.append("ONE_TICK_CONFIG.ALLOW_ENV_VARS=Yes")
136
+ data.append("")
137
+ config_vars = sysconfig.get_config_vars()
138
+ data.append(f"PYTHON_VERSION='{config_vars['py_version_short']}{config_vars['abiflags']}'")
139
+
140
+ if locator:
141
+ data.append(f'DB_LOCATOR.DEFAULT="{_remove_quotes(str(locator))}"')
142
+
143
+ if acl:
144
+ data.append(f'ACCESS_CONTROL_FILE="{_remove_quotes(str(acl))}"')
145
+
146
+ if license_path:
147
+ data.append(f'ONE_TICK_LICENSE_FILE="{_remove_quotes(str(license_path))}"')
148
+
149
+ if license_dir:
150
+ data.append(f'LICENSE_REPOSITORY_DIR="{_remove_quotes(str(license_dir))}"')
151
+
152
+ if license_servers:
153
+ data.append(f'LICENSE_TICK_SERVERS="{_remove_quotes(str(license_servers))}"')
154
+
155
+ if otq_path:
156
+ data.append(f'OTQ_FILE_PATH="{",".join(otq_path)}"')
157
+
158
+ if csv_path:
159
+ data.append(f'CSV_FILE_PATH="{",".join(csv_path)}"')
160
+
161
+ if os.getenv('OTP_WEBAPI_TEST_MODE'):
162
+ tmp_dir = TmpDir()
163
+ data.append(f'TICK_SERVER_CSV_CACHE_DIR="{tmp_dir}"')
164
+ data.append(f'TICK_SERVER_DATA_CACHE_DIR="{tmp_dir}"')
165
+ data.append(f'TICK_SERVER_OTQ_CACHE_DIR="{tmp_dir}"')
166
+
167
+ data.append("")
168
+ data.append("ALLOW_REMOTE_CONTROL=Yes")
169
+ data.append("ALLOW_NO_CERTIFICATE=true")
170
+ # to be able to run otp.ODBC
171
+ data.append("LOAD_ODBC_UDF=true")
172
+
173
+ # # let's not strip quotes around params by default, this is the old behaviour
174
+ # new default behaviour breaks backward-compatibility (BEXRTS-1340, BEXRTS-1342)
175
+ # new behaviour can be achieved by setting STRIP_QUOTES_WHEN_ASSIGNING_SYMBOL_AND_OTQ_PARAMS param in JWQ EP
176
+ data.append("COMPATIBILITY.JOIN_WITH_QUERY.STRIP_QUOTES_AROUND_SYMBOL_AND_OTQ_PARAMS=FALSE")
177
+
178
+ if os.getenv('OTP_WEBAPI_TEST_MODE'):
179
+ tmp_file = TmpFile(name="onetick.cfg", clean_up=clean_up, force=True)
180
+ else:
181
+ tmp_file = TmpFile(suffix=".cfg", clean_up=clean_up)
182
+
183
+ with open(tmp_file, "w") as fout:
184
+ fout.write("\n".join(data))
185
+
186
+ return tmp_file
@@ -0,0 +1,49 @@
1
+ import os
2
+ import sys
3
+ import multiprocessing
4
+ import warnings
5
+
6
+
7
+ def get_local_number_of_cores():
8
+ try:
9
+ # number of cores allowed for user
10
+ return len(os.sched_getaffinity(0))
11
+ except Exception:
12
+ # number of cores
13
+ return multiprocessing.cpu_count()
14
+
15
+
16
+ def default_license_dir():
17
+ if sys.platform == "linux":
18
+ return os.path.join("/", "license")
19
+ elif sys.platform == "win32":
20
+ return os.path.join("C:\\", "OMD", "client_data", "config", "license_repository")
21
+ elif sys.platform == "darwin":
22
+ return os.path.join("/", "Library", "Application Support", "OneTick")
23
+ return None
24
+
25
+
26
+ def default_license_file():
27
+ if sys.platform == "linux":
28
+ return os.path.join("/", "license", "license.dat")
29
+ elif sys.platform == "win32":
30
+ return os.path.join("C:\\", "OMD", "client_data", "config", "license.dat")
31
+ elif sys.platform == "darwin":
32
+ return os.path.join("/", "Library", "Application Support", "OneTick")
33
+ return None
34
+
35
+
36
+ def default_day_boundary_tz(db_name):
37
+ import onetick.py as otp
38
+ if otp.config.tz:
39
+ return otp.config.tz
40
+ warnings.warn(
41
+ "Database property 'day_boundary_tz' can't be set to default timezone "
42
+ "because default timezone is local and is not known at this moment. "
43
+ "Default value for this property will be 'GMT'. "
44
+ f"It may produce unexpected results "
45
+ f"when reading from or writing to database '{db_name}'. "
46
+ "Set otp.config.tz property to some known value to avoid this situation.",
47
+ stacklevel=2,
48
+ )
49
+ return None
@@ -0,0 +1,38 @@
1
+ import os
2
+ import zlib
3
+
4
+ from pathlib import Path
5
+ from typing import Union
6
+
7
+
8
+ class FileBuffer:
9
+ '''
10
+ Class holds the file content with goal to delivery
11
+ it to the execution side in case of remote executions.
12
+
13
+ The basic implementation reads file content to a property
14
+ that allows to transfer file content as pickled object
15
+ to the server side since the pickling stores all class property
16
+ values.
17
+ '''
18
+
19
+ def __init__(self, path: Union[str, os.PathLike]):
20
+ content = Path(path).read_text()
21
+ self._content = zlib.compress(content.encode('utf-8'), level=9)
22
+
23
+ def get(self):
24
+ ''' Returns file content '''
25
+ return zlib.decompress(self._content).decode('utf-8')
26
+
27
+
28
+ def file(path: Union[str, os.PathLike]) -> FileBuffer:
29
+ '''
30
+ Helps to build a file buffer that could be used to
31
+ delivery on the remote site to be processed there.
32
+ For example it could be passed as input to the :class:`CSV <onetick.py.CSV>`
33
+
34
+ See Also
35
+ --------
36
+ :class:`CSV <onetick.py.CSV>`
37
+ '''
38
+ return FileBuffer(path)
@@ -0,0 +1,76 @@
1
+ import json
2
+
3
+ from onetick.py.otq import otq, pyomd
4
+ from datetime import datetime
5
+
6
+
7
+ def get_symbol_list_from_df(df, symbol_name_column='SYMBOL_NAME'):
8
+ """
9
+ Creates a onetick.query.Symbol object that may be passed as a symbol list from the dataframe
10
+ with query results. SYMBOL_NAME column is interpreted as symbol names, while other columns are
11
+ interpreted as symbol params.
12
+ """
13
+ if symbol_name_column not in df.columns:
14
+ raise ValueError(f'Dataframe used as symbol list does not contain a {symbol_name_column} column')
15
+
16
+ df = df.drop(columns=['Time'])
17
+
18
+ def symbol_from_dict(params):
19
+ name = params[symbol_name_column]
20
+ del params[symbol_name_column]
21
+ return otq.Symbol(name=name, params=params)
22
+
23
+ symbols = [symbol_from_dict(row) for row in df.to_dict(orient='records')]
24
+ return symbols
25
+
26
+
27
+ class JSONEncoder(json.JSONEncoder):
28
+ """
29
+ onetick.py json encoder that also supports some of the onetick.py objects like otp.adaptive.
30
+ """
31
+ def default(self, o):
32
+ # let's use python str representation by default, all objects in python should have it
33
+ # maybe we will add better representations for some types later
34
+ return str(o)
35
+
36
+
37
+ def json_dumps(obj, **kwargs) -> str:
38
+ """
39
+ Wrapper around json.dumps that also supports some of the onetick.py objects like otp.adaptive.
40
+ ``kwargs`` arguments are propagated to json.dumps function.
41
+ By default ``cls`` parameter is set to otp.utils.JSONEncoder.
42
+ """
43
+ kwargs.setdefault('cls', JSONEncoder)
44
+ return json.dumps(obj, **kwargs)
45
+
46
+
47
+ def query_properties_to_dict(query_properties: pyomd.QueryProperties) -> dict: # type: ignore[valid-type]
48
+ """
49
+ Convert :py:class:`pyomd.QueryProperties` to dictionary.
50
+ """
51
+
52
+ str_qp = query_properties.convert_to_name_value_pairs_string() # type: ignore[attr-defined]
53
+ if not isinstance(str_qp, str):
54
+ str_qp = str_qp.c_str()
55
+ pairs = str_qp.split(',') if str_qp else []
56
+ return dict(pair.split('=', maxsplit=1) for pair in pairs)
57
+
58
+
59
+ def query_properties_from_dict(query_properties_dict: dict) -> pyomd.QueryProperties: # type: ignore[valid-type]
60
+ """
61
+ Convert dictionary to :py:class:`pyomd.QueryProperties`.
62
+ """
63
+ query_properties = pyomd.QueryProperties()
64
+ for k, v in query_properties_dict.items():
65
+ query_properties.set_property_value(k, v)
66
+ return query_properties
67
+
68
+
69
+ def symbol_date_to_str(symbol_date) -> str:
70
+ if isinstance(symbol_date, int):
71
+ symbol_date = str(symbol_date)
72
+ if isinstance(symbol_date, str):
73
+ symbol_date = datetime.strptime(symbol_date, '%Y%m%d')
74
+ if hasattr(symbol_date, 'strftime'):
75
+ symbol_date = symbol_date.strftime('%Y%m%d')
76
+ return symbol_date
@@ -0,0 +1,94 @@
1
+ import os
2
+ from locator_parser.io import PrintWriter, FileReader
3
+ from locator_parser.actions import GetAll
4
+ from locator_parser.locator import Location, parse_locator
5
+ from locator_parser.common import apply_actions
6
+
7
+ from .temp import TmpFile
8
+ from .types import default
9
+
10
+
11
+ def get_dbs_locations_from_locator(locator):
12
+ action = GetAll()
13
+ action.add_where(Location)
14
+
15
+ apply_actions(parse_locator, FileReader(locator), PrintWriter(), [action])
16
+
17
+ return map(lambda x: x.location, action.result)
18
+
19
+
20
+ def tmp_locator(clean_up=default, empty=False):
21
+ import onetick.py as otp
22
+
23
+ STUBS = {'COMMON'}
24
+ default_db = otp.config.get('default_db')
25
+ if default_db:
26
+ STUBS.add(default_db)
27
+
28
+ data = []
29
+ data.append('<VERSION_INFO VERSION="2"/>')
30
+ data.append("<DATABASES>")
31
+ data.append("")
32
+
33
+ if not empty:
34
+ for stub_name in STUBS:
35
+ data.append(
36
+ f'<db ID="{stub_name}" symbology="{otp.config.default_symbology}" time_series_is_composite="YES">'
37
+ )
38
+ data.append("<locations>")
39
+ day_boundary_tz = otp.config.get('tz')
40
+ day_boundary_tz = f'day_boundary_tz="{day_boundary_tz}"' if day_boundary_tz else ''
41
+ data.append(
42
+ '<location access_method="file" location="/opt/one_market_data/one_tick/examples/data/demo_level1" '
43
+ 'start_time="20001201000000" end_time="20301031050000" '
44
+ f'{day_boundary_tz}/>'
45
+ )
46
+ data.append("</locations>")
47
+ data.append('<feed type="heartbeat_generator">')
48
+ data.append('<options format="native" />')
49
+ data.append('</feed>')
50
+ data.append("</db>")
51
+ data.append("")
52
+ data.append("")
53
+
54
+ data.append("</DATABASES>")
55
+
56
+ data.append("<TICK_SERVERS>")
57
+ data.append("</TICK_SERVERS>")
58
+ data.append("<CEP_TICK_SERVERS>")
59
+ data.append("</CEP_TICK_SERVERS>")
60
+ data.append("<INCLUDES>")
61
+ data.append("</INCLUDES>")
62
+
63
+ tmp_file = new_tmp_locator(clean_up)
64
+
65
+ with open(tmp_file, "w") as fout:
66
+ fout.write("\n".join(data))
67
+
68
+ return tmp_file
69
+
70
+
71
+ def new_tmp_locator(clean_up):
72
+ if os.getenv('OTP_WEBAPI_TEST_MODE'):
73
+ tmp_file = TmpFile(name="locator.default", clean_up=clean_up, force=True)
74
+ else:
75
+ tmp_file = TmpFile(suffix=".locator", clean_up=clean_up)
76
+ return tmp_file
77
+
78
+
79
+ def empty_locator(clean_up=default):
80
+ data = []
81
+ data.append('<VERSION_INFO VERSION="2"/>')
82
+ data.append("<DATABASES>")
83
+ data.append("</DATABASES>")
84
+ data.append("<TICK_SERVERS>")
85
+ data.append("</TICK_SERVERS>")
86
+ data.append("<CEP_TICK_SERVERS>")
87
+ data.append("</CEP_TICK_SERVERS>")
88
+ data.append("<INCLUDES>")
89
+ data.append("</INCLUDES>")
90
+
91
+ tmp_file = new_tmp_locator(clean_up)
92
+ with open(tmp_file, "w") as fout:
93
+ fout.write("\n".join(data))
94
+ return tmp_file