onetick-py 1.162.2__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 +266 -0
  4. locator_parser/common.py +365 -0
  5. locator_parser/io.py +41 -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 +280 -0
  12. onetick/lib/__init__.py +4 -0
  13. onetick/lib/instance.py +138 -0
  14. onetick/py/__init__.py +290 -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 +645 -0
  19. onetick/py/aggregations/_docs.py +912 -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 +427 -0
  26. onetick/py/aggregations/other.py +1014 -0
  27. onetick/py/backports.py +26 -0
  28. onetick/py/cache.py +373 -0
  29. onetick/py/callback/__init__.py +5 -0
  30. onetick/py/callback/callback.py +275 -0
  31. onetick/py/callback/callbacks.py +131 -0
  32. onetick/py/compatibility.py +752 -0
  33. onetick/py/configuration.py +736 -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 +2307 -0
  45. onetick/py/core/_internal/_state_vars.py +87 -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 +810 -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 +270 -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 +1001 -0
  58. onetick/py/core/_source/source_methods/joins.py +1393 -0
  59. onetick/py/core/_source/source_methods/merges.py +566 -0
  60. onetick/py/core/_source/source_methods/misc.py +1325 -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 +702 -0
  68. onetick/py/core/_source/symbol.py +202 -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 +215 -0
  75. onetick/py/core/column_operations/_methods/methods.py +294 -0
  76. onetick/py/core/column_operations/_methods/op_types.py +150 -0
  77. onetick/py/core/column_operations/accessors/__init__.py +0 -0
  78. onetick/py/core/column_operations/accessors/_accessor.py +30 -0
  79. onetick/py/core/column_operations/accessors/decimal_accessor.py +92 -0
  80. onetick/py/core/column_operations/accessors/dt_accessor.py +464 -0
  81. onetick/py/core/column_operations/accessors/float_accessor.py +160 -0
  82. onetick/py/core/column_operations/accessors/str_accessor.py +1374 -0
  83. onetick/py/core/column_operations/base.py +1061 -0
  84. onetick/py/core/cut_builder.py +149 -0
  85. onetick/py/core/db_constants.py +20 -0
  86. onetick/py/core/eval_query.py +244 -0
  87. onetick/py/core/lambda_object.py +442 -0
  88. onetick/py/core/multi_output_source.py +193 -0
  89. onetick/py/core/per_tick_script.py +2253 -0
  90. onetick/py/core/query_inspector.py +465 -0
  91. onetick/py/core/source.py +1663 -0
  92. onetick/py/db/__init__.py +2 -0
  93. onetick/py/db/_inspection.py +1042 -0
  94. onetick/py/db/db.py +1423 -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 +2354 -0
  100. onetick/py/license.py +188 -0
  101. onetick/py/log.py +88 -0
  102. onetick/py/math.py +947 -0
  103. onetick/py/misc.py +437 -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 +211 -0
  108. onetick/py/pyomd_mock.py +47 -0
  109. onetick/py/run.py +841 -0
  110. onetick/py/servers.py +173 -0
  111. onetick/py/session.py +1342 -0
  112. onetick/py/sources/__init__.py +19 -0
  113. onetick/py/sources/cache.py +167 -0
  114. onetick/py/sources/common.py +126 -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 +1049 -0
  119. onetick/py/sources/empty.py +94 -0
  120. onetick/py/sources/odbc.py +337 -0
  121. onetick/py/sources/order_book.py +238 -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 +357 -0
  129. onetick/py/sources/ticks.py +825 -0
  130. onetick/py/sql.py +70 -0
  131. onetick/py/state.py +256 -0
  132. onetick/py/types.py +2056 -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 +499 -0
  141. onetick/py/utils/query.py +49 -0
  142. onetick/py/utils/render.py +1139 -0
  143. onetick/py/utils/script.py +244 -0
  144. onetick/py/utils/temp.py +471 -0
  145. onetick/py/utils/types.py +118 -0
  146. onetick/py/utils/tz.py +82 -0
  147. onetick_py-1.162.2.dist-info/METADATA +148 -0
  148. onetick_py-1.162.2.dist-info/RECORD +152 -0
  149. onetick_py-1.162.2.dist-info/WHEEL +5 -0
  150. onetick_py-1.162.2.dist-info/entry_points.txt +2 -0
  151. onetick_py-1.162.2.dist-info/licenses/LICENSE +21 -0
  152. onetick_py-1.162.2.dist-info/top_level.txt +2 -0
@@ -0,0 +1,736 @@
1
+ import os
2
+ from datetime import datetime
3
+ from typing import Iterable, Type, Union, Optional
4
+ from contextlib import suppress, contextmanager
5
+ from textwrap import dedent
6
+
7
+ import dotenv
8
+ from onetick.py.otq import otq
9
+ from .utils import default_license_dir, default_license_file, get_local_number_of_cores
10
+ import onetick.py.types as ott
11
+
12
+ DEFAULT_LICENSE_DIR = default_license_dir()
13
+ DEFAULT_LICENSE_FILE = default_license_file()
14
+
15
+ DATETIME_FORMATS = (
16
+ '%Y/%m/%d %H:%M:%S.%f',
17
+ '%Y/%m/%d %H:%M:%S',
18
+ )
19
+ DATETIME_DESCRIPTION = (
20
+ "Format of the env variable: "
21
+ f"{', '.join(':code:`{}`'.format(fmt) for fmt in DATETIME_FORMATS)}."
22
+ )
23
+
24
+
25
+ def parse_datetime(s):
26
+ for fmt in DATETIME_FORMATS:
27
+ with suppress(ValueError):
28
+ return datetime.strptime(s, fmt)
29
+ raise ValueError(
30
+ f"The datetime pattern is not supported for string '{s}'. "
31
+ f"Available patterns: {DATETIME_FORMATS}"
32
+ )
33
+
34
+
35
+ def _env_func_concurrency(value: str) -> Optional[int]:
36
+ if not value:
37
+ return None
38
+ if value == 'local_number_of_cores':
39
+ return get_local_number_of_cores()
40
+ return int(value)
41
+
42
+
43
+ def default_query_concurrency():
44
+ concurrency = config.default_concurrency
45
+ if concurrency is None:
46
+ from onetick.py.compatibility import is_zero_concurrency_supported
47
+ # TODO: this logic should be in the default value of otp.config.default_concurrency,
48
+ # but there are complex problems with circular import in this case
49
+ if is_zero_concurrency_supported():
50
+ concurrency = 0
51
+ else:
52
+ concurrency = 1
53
+ return concurrency
54
+
55
+
56
+ def default_presort_concurrency():
57
+ if config.presort_force_default_concurrency:
58
+ return default_query_concurrency()
59
+ else:
60
+ return None
61
+
62
+
63
+ class _nothing(type):
64
+ def __repr__(cls):
65
+ return cls.__name__
66
+
67
+
68
+ class nothing(metaclass=_nothing):
69
+ """
70
+ This is nothing.
71
+ """
72
+
73
+
74
+ class OtpProperty:
75
+ """
76
+ .. attribute:: {name}
77
+ :type: {base_type}
78
+ :value: {base_value}
79
+
80
+ {description}
81
+
82
+ {env_var_name}
83
+
84
+ {env_var_desc}
85
+ """
86
+ def __init__(self, description, base_default, env_var_name=None, env_var_func=None,
87
+ env_var_desc=None, set_value=nothing, allowed_types: Union[Type, Iterable] = nothing,
88
+ validator_func=None):
89
+ self._base_default = base_default
90
+ self._env_var_name = env_var_name
91
+ self._env_var_func = env_var_func
92
+ self._env_var_desc = env_var_desc
93
+ self._set_value = set_value
94
+ self._description = description
95
+ if self._base_default is nothing:
96
+ self._allowed_types = []
97
+ else:
98
+ self._allowed_types = [type(self._base_default)]
99
+ if allowed_types is not nothing:
100
+ if isinstance(allowed_types, Iterable):
101
+ self._allowed_types.extend(allowed_types)
102
+ else:
103
+ self._allowed_types.append(allowed_types)
104
+ self._allowed_types = tuple(set(self._allowed_types)) # type: ignore[assignment]
105
+ # will be monkeypatched later
106
+ self._name = None
107
+ if validator_func is None:
108
+ self._validator_func = lambda x: x
109
+ else:
110
+ self._validator_func = validator_func
111
+
112
+ def _get_doc(self, name):
113
+ env_var_name = ''
114
+ env_var_desc = ''
115
+ if self._env_var_name is not None:
116
+ env_var_name = f'Can be set using environment variable :envvar:`{self._env_var_name}`.'
117
+ if self._env_var_desc is not None:
118
+ env_var_desc = self._env_var_desc
119
+ return self.__class__.__doc__.format(
120
+ name=name,
121
+ description=self._description,
122
+ base_type=','.join(t.__name__ for t in self._allowed_types),
123
+ base_value=repr(self._base_default),
124
+ env_var_name=env_var_name,
125
+ env_var_desc=env_var_desc
126
+ )
127
+
128
+ def __get__(self, obj, objtype=None):
129
+ if self._set_value is not nothing:
130
+ return self._set_value
131
+ if self._env_var_name:
132
+ env_var_value = os.environ.get(self._env_var_name, None)
133
+ if env_var_value is not None:
134
+ if self._env_var_func:
135
+ return self._env_var_func(env_var_value)
136
+ return env_var_value
137
+ if obj is not None:
138
+ # get value from default config
139
+ if self._env_var_name and self._env_var_name in obj.default_config:
140
+ var_value = obj.default_config[self._env_var_name]
141
+ if self._env_var_func:
142
+ return self._env_var_func(var_value)
143
+ return var_value
144
+ if self._base_default is nothing:
145
+ raise ValueError(f'onetick.py.config.{self._name} is not set!')
146
+ return self._base_default
147
+
148
+ def __set__(self, obj, value):
149
+ # assigning to nothing is permitted
150
+ # assigning to nothing will reset value to default
151
+ if not isinstance(value, self._allowed_types) and value is not nothing:
152
+ raise ValueError(f'Type of passed configuration value "{type(value)}" should be one of '
153
+ f'the allowed types for this configuration {self._allowed_types}')
154
+ if value is nothing:
155
+ self._set_value = value
156
+ else:
157
+ self._set_value = self._validator_func(value)
158
+
159
+
160
+ class OtpDerivedProperty:
161
+ """
162
+ .. attribute:: {name}
163
+ :type: {base_type}
164
+ :value: {base_value}
165
+
166
+ {description}
167
+ """
168
+
169
+ def __init__(self, description, definition_function):
170
+ self._description = description
171
+ self.__definition_function = definition_function
172
+
173
+ def __get__(self, obj, objtype=None):
174
+ return self.__definition_function(obj)
175
+
176
+ def _get_doc(self, name, base_object):
177
+ value = self.__definition_function(base_object, docs=True)
178
+ return self.__doc__.format(
179
+ name=name,
180
+ description=self._description,
181
+ base_type=type(value).__name__,
182
+ base_value=value,
183
+ )
184
+
185
+ def __set__(self, obj, value):
186
+ raise AttributeError('It\'s not allowed to change a derived property. Change source properties, and its value '
187
+ 'will be updated automatically.')
188
+
189
+
190
+ class OtpShowStackInfoProperty(OtpProperty):
191
+ """
192
+ .. attribute:: {name}
193
+ :type: {base_type}
194
+ :value: {base_value}
195
+
196
+ {description}
197
+ """
198
+ @staticmethod
199
+ def parser(value):
200
+ return str(value).lower() in ('1', 'true', 'yes')
201
+
202
+ def __init__(self, *args, **kwargs):
203
+ super().__init__(*args, **kwargs)
204
+ # set default value on module loading
205
+ self.__set_in_onetick_query__()
206
+
207
+ def __get__(self, obj, objtype=None):
208
+ value = super().__get__(obj, objtype)
209
+ return self.parser(value)
210
+
211
+ def __set__(self, obj, value):
212
+ super().__set__(obj, value)
213
+ self.__set_in_onetick_query__()
214
+
215
+ def __set_in_onetick_query__(self):
216
+ value = 1 if self.__get__(None) else 0
217
+ otq.API_CONFIG['SHOW_STACK_INFO'] = value
218
+
219
+
220
+ def document_config(cls):
221
+ manually_set_properties_doc = ''
222
+ changeable_properties_doc = ''
223
+ derived_properties_doc = ''
224
+
225
+ manually_set_options = cls.manually_set_options()
226
+ for b in manually_set_options:
227
+ manually_set_properties_doc += cls.__dict__[b]._get_doc(b)
228
+ for c in cls.get_changeable_config_options():
229
+ cls.__dict__[c]._name = c
230
+ if c not in manually_set_options:
231
+ changeable_properties_doc += cls.__dict__[c]._get_doc(c)
232
+ for d in cls.get_derived_config_options():
233
+ cls.__dict__[d]._name = d
234
+ derived_properties_doc += cls.__dict__[d]._get_doc(d, base_object=cls)
235
+
236
+ cls.__doc__ = cls.__doc__.format(
237
+ manually_set_properties=manually_set_properties_doc,
238
+ changeable_properties=changeable_properties_doc,
239
+ derived_properties=derived_properties_doc,
240
+ )
241
+ cls.__doc__ = dedent(cls.__doc__)
242
+
243
+ return cls
244
+
245
+
246
+ @document_config
247
+ class Config:
248
+ """
249
+ This object is used to access ``onetick.py`` configuration variables.
250
+
251
+ Configuration variables may be accessed via :code:`otp.config['...']` syntax, e.g. :code:`otp.config['tz']`.
252
+
253
+ Configuration variables may be changed by:
254
+
255
+ * during python runtime by modifying properties of object ``otp.config``,
256
+ * by setting environment variables *before* importing ``onetick.py`` module.
257
+
258
+ During python runtime you can modify properties of ``otp.config`` object either directly or via context manager:
259
+ ``with otp.config('property', 'value'):``
260
+
261
+ Also special environment variable ``OTP_DEFAULT_CONFIG_PATH`` can be used to specify a file,
262
+ from which configuration variables will be taken.
263
+ This file will be read only once on module loading or when getting one of the configuration variables
264
+ when the environment variable is discovered.
265
+ The names of the variables in this file are the same as the names of environment variables.
266
+
267
+ In case several methods of setting configuration variables are used,
268
+ the following order of priority is in place:
269
+
270
+ 1. Value that is set by modifying object ``otp.config``
271
+ 2. Value that is set via environment variable
272
+ 3. Value that is set in file ``OTP_DEFAULT_CONFIG_PATH``
273
+ 4. Default value specified in the source code
274
+
275
+ To reset configuration value that has been set by modifying object ``otp.config``,
276
+ special value ``otp.config.default`` should be assigned to it.
277
+
278
+ Most of the config vars are optional and have default values,
279
+ but some of them need to be set manually.
280
+
281
+ There are also some environment variables that do not have
282
+ corresponding property in ``otp.config`` object:
283
+
284
+ * ``OTP_BASE_FOLDER_FOR_GENERATED_RESOURCE``:
285
+ a folder where all intermediate queries, files and databases
286
+ generated by ``onetick-py`` are located.
287
+ The default value is system-dependent, e.g. some generated
288
+ directory with a unique name under a standard directory **/tmp** for Linux.
289
+
290
+ **The following properties must be set manually in most cases:**
291
+ {manually_set_properties}
292
+
293
+ **The following properties can be changed:**
294
+ {changeable_properties}
295
+
296
+ **The following properties are derived and thus read-only:**
297
+ {derived_properties}
298
+ """
299
+ __default_config = None
300
+
301
+ @property
302
+ def default_config(self):
303
+ default_config_path = os.environ.get('OTP_DEFAULT_CONFIG_PATH')
304
+ if not default_config_path:
305
+ return {}
306
+ if self.__default_config is None:
307
+ default_config = dotenv.dotenv_values(default_config_path)
308
+ available_option_names = []
309
+ for name, option in self.get_changeable_config_options().items():
310
+ if option._env_var_name:
311
+ available_option_names.append(option._env_var_name)
312
+ diff = set(default_config).difference(available_option_names)
313
+ if diff:
314
+ raise ValueError(f'Configuration options {diff} from file'
315
+ f' OTP_DEFAULT_CONFIG_PATH="{default_config_path}" are not supported.'
316
+ f' Available options: {available_option_names}.')
317
+ Config.__default_config = default_config
318
+ return self.__default_config or {}
319
+
320
+ def __getitem__(self, item):
321
+ if item not in self.__class__.__dict__.keys():
322
+ raise AttributeError(f'"{item}" is not in the list of onetick.py config options!')
323
+ return self.__class__.__dict__[item].__get__(self)
324
+
325
+ def __setitem__(self, item, value):
326
+ if item not in self.__class__.__dict__.keys():
327
+ raise AttributeError(f'"{item}" is not in the list of onetick.py config options!')
328
+ self.__class__.__dict__[item].__set__(self, value)
329
+
330
+ def get(self, key, default=None):
331
+ try:
332
+ return self.__getitem__(key)
333
+ except ValueError:
334
+ return default
335
+
336
+ def __setattr__(self, item, value):
337
+ """
338
+ To avoid accidental declaration of non-existing properties, e.g. `otp.config.timezone = "GMT"`
339
+ """
340
+ self.__setitem__(item, value)
341
+
342
+ @contextmanager
343
+ def __call__(self, name, value):
344
+ old_value = self[name]
345
+ try:
346
+ self[name] = value
347
+ yield
348
+ finally:
349
+ self[name] = old_value
350
+
351
+ @classmethod
352
+ def get_changeable_config_options(cls):
353
+ """
354
+ useful for tests where you may want to memorize all existing configuration options before changing them
355
+ """
356
+ return {
357
+ option: value
358
+ for option, value in cls.__dict__.items()
359
+ if isinstance(value, OtpProperty)
360
+ }
361
+
362
+ @classmethod
363
+ def get_derived_config_options(cls):
364
+ return {
365
+ option: value
366
+ for option, value in cls.__dict__.items()
367
+ if isinstance(value, OtpDerivedProperty)
368
+ }
369
+
370
+ @classmethod
371
+ def manually_set_options(cls):
372
+ return {
373
+ option: value
374
+ for option, value in cls.__dict__.items()
375
+ if isinstance(value, OtpProperty) and value._base_default is nothing
376
+ }
377
+
378
+ default = nothing
379
+
380
+ tz = OtpProperty(
381
+ description='Default timezone used for running queries and creating databases, '
382
+ 'e.g. with :py:func:`otp.run<onetick.py.run>`. '
383
+ 'Default value is the local timezone of your machine.',
384
+ base_default=None,
385
+ allowed_types=str,
386
+ env_var_name='OTP_DEFAULT_TZ',
387
+ )
388
+
389
+ context = OtpProperty(
390
+ description='Default context used for running queries, '
391
+ 'e.g. with :py:func:`otp.run<onetick.py.run>`.'
392
+ 'Note: In WebAPI mode it will have `None` value.',
393
+ base_default='DEFAULT' if not otq.webapi else None,
394
+ allowed_types=[str],
395
+ env_var_name='OTP_CONTEXT',
396
+ )
397
+
398
+ default_start_time = OtpProperty(
399
+ description='Default start time used for running queries, '
400
+ 'e.g. with :py:func:`otp.run<onetick.py.run>`.',
401
+ base_default=nothing,
402
+ allowed_types=[datetime, ott.datetime],
403
+ env_var_name='OTP_DEFAULT_START_TIME',
404
+ env_var_func=parse_datetime,
405
+ env_var_desc=DATETIME_DESCRIPTION,
406
+ )
407
+
408
+ default_end_time = OtpProperty(
409
+ description='Default end time used for running queries, '
410
+ 'e.g. with :py:func:`otp.run<onetick.py.run>`.',
411
+ base_default=nothing,
412
+ allowed_types=[datetime, ott.datetime],
413
+ env_var_name='OTP_DEFAULT_END_TIME',
414
+ env_var_func=parse_datetime,
415
+ env_var_desc=DATETIME_DESCRIPTION,
416
+ )
417
+
418
+ default_db = OtpProperty(
419
+ description='Default database name used for running queries, '
420
+ 'e.g. with :py:func:`otp.run<onetick.py.run>`.',
421
+ base_default=nothing,
422
+ allowed_types=str,
423
+ env_var_name='OTP_DEFAULT_DB',
424
+ )
425
+
426
+ default_symbol = OtpProperty(
427
+ description='Default symbol name used for running queries, '
428
+ 'e.g. with :py:func:`otp.run<onetick.py.run>`.',
429
+ base_default=nothing,
430
+ allowed_types=str,
431
+ env_var_name='OTP_DEFAULT_SYMBOL',
432
+ )
433
+
434
+ default_symbology = OtpProperty(
435
+ description='Default database symbology.',
436
+ base_default='BZX',
437
+ env_var_name='OTP_DEFAULT_SYMBOLOGY',
438
+ )
439
+
440
+ def _default_db_symbol(obj, docs=False): # noqa
441
+ try:
442
+ return obj.default_db + '::' + obj.default_symbol
443
+ except (ValueError, TypeError):
444
+ if not docs:
445
+ raise
446
+
447
+ default_db_symbol = OtpDerivedProperty(
448
+ description='Default symbol with database. '
449
+ 'Defined with :py:attr:`default_db` and :py:attr:`default_symbol` '
450
+ 'as string **default_db::default_symbol**.',
451
+ definition_function=_default_db_symbol,
452
+ )
453
+
454
+ def _default_date(obj, docs=False): # noqa
455
+ try:
456
+ return datetime.combine(obj.default_start_time.date(), datetime.min.time())
457
+ except (ValueError, TypeError, AttributeError):
458
+ if not docs:
459
+ raise
460
+
461
+ default_date = OtpDerivedProperty(
462
+ description='Default date. '
463
+ 'Defined as a date part of :py:attr:`default_start_time`.',
464
+ definition_function=_default_date,
465
+ )
466
+
467
+ default_concurrency = OtpProperty(
468
+ description='Default concurrency level used for running queries, '
469
+ 'e.g. with :py:func:`otp.run<onetick.py.run>`. '
470
+ 'Default value is ``None`` which means that the value is adaptive '
471
+ 'and is set to 0 (meaning concurrency will be auto-assigned by OneTick server) '
472
+ 'on the latest OneTick versions where it is supported '
473
+ 'or to 1 (meaning no concurrency) on older versions. '
474
+ 'Special value ``local_number_of_cores`` can be used to set concurrency '
475
+ 'to the number of cores of the machine where python code executes '
476
+ '(this corresponds to the previous default logic still expected by some users).',
477
+ base_default=None,
478
+ allowed_types=[type(None), int, str],
479
+ env_var_name='OTP_DEFAULT_CONCURRENCY',
480
+ env_var_func=_env_func_concurrency,
481
+ validator_func=lambda x: _env_func_concurrency(str(x) if x is not None else '')
482
+ )
483
+
484
+ presort_force_default_concurrency = OtpProperty(
485
+ description='By default concurrency value for PRESORT EPs is empty '
486
+ 'and inherited from the concurrency level set in the query where this EP is used. '
487
+ 'However, is some cases it may be desirable '
488
+ 'to force setting default concurrency level for all PRESORT EPs '
489
+ '(this corresponds to the previous default logic still expected by some users), '
490
+ 'for example when PRESORT is located in the first stage query and cannot inherit '
491
+ 'concurrency from the main query.',
492
+ base_default=False,
493
+ allowed_types=[bool],
494
+ env_var_name='OTP_PRESORT_FORCE_DEFAULT_CONCURRENCY',
495
+ env_var_func=OtpShowStackInfoProperty.parser,
496
+ )
497
+
498
+ # default batch size is set to 0, so the number of symbols in batch is not limited
499
+ # it should work better in simple cases, but may use too much memory for complex queries
500
+ default_batch_size = OtpProperty(
501
+ description='Default batch size used for running queries, '
502
+ 'e.g. with :py:func:`otp.run<onetick.py.run>`. '
503
+ 'Batch size is the maximum number of symbols that are processed at once. '
504
+ 'The value of 0 means unlimited -- works faster for simple queries, '
505
+ 'but may consume too much memory for complex queries.',
506
+ base_default=0,
507
+ env_var_name='OTP_DEFAULT_BATCH_SIZE',
508
+ env_var_func=int,
509
+ )
510
+
511
+ default_license_dir = OtpProperty(
512
+ description='Default path for license directory. '
513
+ 'Needed for user to be allowed to use OneTick API. '
514
+ 'Default value is system-dependent: '
515
+ '**/license** for Linux systems and '
516
+ '**C:/OMD/client_data/config/license_repository** for Windows systems.',
517
+ base_default=DEFAULT_LICENSE_DIR,
518
+ env_var_name='OTP_DEFAULT_LICENSE_DIR',
519
+ allowed_types=str,
520
+ )
521
+
522
+ default_license_file = OtpProperty(
523
+ description='Default path for license file. '
524
+ 'Needed for user to be allowed to use OneTick API. '
525
+ 'Default value is system-dependent: '
526
+ '**/license/license.dat** for Linux systems and '
527
+ '**C:/OMD/client_data/config/license.dat** for Windows systems.',
528
+ base_default=DEFAULT_LICENSE_FILE,
529
+ env_var_name='OTP_DEFAULT_LICENSE_FILE',
530
+ allowed_types=str,
531
+ )
532
+
533
+ default_fault_tolerance = OtpProperty(
534
+ description='Default value for USE_FT query property.',
535
+ base_default='FALSE',
536
+ env_var_name='OTP_DEFAULT_FAULT_TOLERANCE',
537
+ allowed_types=str,
538
+ )
539
+
540
+ default_auth_username = OtpProperty(
541
+ description='Default username used for authentication.',
542
+ base_default=None,
543
+ allowed_types=str,
544
+ env_var_name='OTP_DEFAULT_AUTH_USERNAME',
545
+ )
546
+
547
+ default_password = OtpProperty(
548
+ description='Default password used for authentication.',
549
+ base_default=None,
550
+ allowed_types=str,
551
+ env_var_name='OTP_DEFAULT_PASSWORD',
552
+ )
553
+
554
+ http_address = OtpProperty(
555
+ description='Default HTTP server used as WebAPI endpoint.',
556
+ base_default=None,
557
+ allowed_types=str,
558
+ env_var_name='OTP_HTTP_ADDRESS',
559
+ )
560
+
561
+ http_username = OtpProperty(
562
+ description='Username used for WebAPI authentication.',
563
+ base_default=None,
564
+ allowed_types=str,
565
+ env_var_name='OTP_HTTP_USERNAME',
566
+ )
567
+
568
+ http_password = OtpProperty(
569
+ description='Password used for WebAPI authentication.',
570
+ base_default=None,
571
+ allowed_types=str,
572
+ env_var_name='OTP_HTTP_PASSWORD',
573
+ )
574
+
575
+ http_proxy = OtpProperty(
576
+ description='HTTP proxy used for WebAPI requests.',
577
+ base_default=None,
578
+ allowed_types=str,
579
+ env_var_name='HTTP_PROXY',
580
+ )
581
+
582
+ https_proxy = OtpProperty(
583
+ description='HTTPS proxy used for WebAPI requests.',
584
+ base_default=None,
585
+ allowed_types=str,
586
+ env_var_name='HTTPS_PROXY',
587
+ )
588
+
589
+ access_token = OtpProperty(
590
+ description='SSO access token for WebAPI endpoint.',
591
+ base_default=None,
592
+ allowed_types=str,
593
+ env_var_name='OTP_ACCESS_TOKEN',
594
+ )
595
+
596
+ client_id = OtpProperty(
597
+ description='Client ID for obtaining SSO access token.',
598
+ base_default=None,
599
+ allowed_types=str,
600
+ env_var_name='OTP_CLIENT_ID',
601
+ )
602
+
603
+ client_secret = OtpProperty(
604
+ description='Client Secret for obtaining SSO access token.',
605
+ base_default=None,
606
+ allowed_types=str,
607
+ env_var_name='OTP_CLIENT_SECRET',
608
+ )
609
+
610
+ access_token_url = OtpProperty(
611
+ description='URL for obtaining SSO access token.',
612
+ base_default=None,
613
+ allowed_types=str,
614
+ env_var_name='OTP_ACCESS_TOKEN_URL',
615
+ )
616
+
617
+ trusted_certificates_file = OtpProperty(
618
+ description='Path to the file with list of trusted Certificate Authority certificates for WebAPI requests.',
619
+ base_default=None,
620
+ allowed_types=str,
621
+ env_var_name='OTP_SSL_CERT_FILE',
622
+ )
623
+
624
+ max_expected_ticks_per_symbol = OtpProperty(
625
+ description='Expected maximum number of ticks per symbol (used for performance optimizations).',
626
+ base_default=2000,
627
+ allowed_types=int,
628
+ env_var_name='OTP_MAX_EXPECTED_TICKS_PER_SYMBOL',
629
+ )
630
+
631
+ show_stack_info = OtpShowStackInfoProperty(
632
+ description='Show stack info (filename and line or stack trace) in OneTick exceptions.',
633
+ base_default=False,
634
+ allowed_types=(str, bool, int),
635
+ env_var_name='OTP_SHOW_STACK_INFO',
636
+ env_var_func=OtpShowStackInfoProperty.parser,
637
+ )
638
+
639
+ log_symbol = OtpProperty(
640
+ description='Log currently executed symbol. Note, this only works with unbound symbols. '
641
+ 'Note, in this case :py:func:`otp.run<onetick.py.run>` does not produce the output '
642
+ 'so it should be used only for debugging purposes.',
643
+ base_default=False,
644
+ allowed_types=(str, bool, int),
645
+ env_var_name='OTP_LOG_SYMBOL',
646
+ env_var_func=OtpShowStackInfoProperty.parser,
647
+ )
648
+
649
+ ignore_ticks_in_unentitled_time_range = OtpProperty(
650
+ description='Default value for IGNORE_TICKS_IN_UNENTITLED_TIME_RANGE query property.',
651
+ base_default=False,
652
+ env_var_name='OTP_IGNORE_TICKS_IN_UNENTITLED_TIME_RANGE',
653
+ allowed_types=(str, bool, int),
654
+ env_var_func=OtpShowStackInfoProperty.parser,
655
+ )
656
+
657
+ main_query_generated_filename = OtpProperty(
658
+ description='The name of the .otq file with generated main query executed by otp.run.',
659
+ base_default='',
660
+ env_var_name='OTP_MAIN_QUERY_GENERATED_FILENAME',
661
+ allowed_types=str,
662
+ )
663
+
664
+ logging = OtpProperty(
665
+ description='The logging level string or path to the file with configuration. '
666
+ 'Check the documentation of python logging module for the configuration formats. '
667
+ 'JSON format (in the file with .json suffix) and python configparser formats are supported.',
668
+ base_default='WARNING',
669
+ env_var_name='OTP_LOGGING',
670
+ allowed_types=str,
671
+ )
672
+
673
+ otq_debug_mode = OtpProperty(
674
+ description='Enable .otq files debug mode. '
675
+ 'If set to True, onetick.py will keep all generated otq files and '
676
+ 'log their paths to the console.',
677
+ base_default=False,
678
+ env_var_name='OTP_OTQ_DEBUG_MODE',
679
+ allowed_types=(str, bool, int),
680
+ env_var_func=OtpShowStackInfoProperty.parser,
681
+ )
682
+
683
+ allow_lowercase_in_saved_fields = OtpProperty(
684
+ description='Allow using lower case characters in field names that are being stored in Onetick databases. '
685
+ 'If set to False, onetick.py would not allow saving fields with lower case characters '
686
+ 'to a database.',
687
+ base_default=True,
688
+ allowed_types=bool,
689
+ )
690
+
691
+ clean_up_tmp_files = OtpProperty(
692
+ description='Control deleting temporary files created by onetick-py. '
693
+ 'Temporary files are OneTick configuration files and generated .otq queries.',
694
+ base_default=True,
695
+ env_var_name='OTP_CLEAN_UP_TMP_FILES',
696
+ allowed_types=(str, bool, int),
697
+ env_var_func=OtpShowStackInfoProperty.parser,
698
+ )
699
+
700
+ default_schema_policy = OtpProperty(
701
+ description='Default schema policy when querying onetick database. '
702
+ 'See parameter ``schema_policy`` in :class:`otp.DataSource <onetick.py.DataSource>` '
703
+ 'for the list of supported values.',
704
+ base_default=None,
705
+ env_var_name='OTP_DEFAULT_SCHEMA_POLICY',
706
+ allowed_types=str,
707
+ )
708
+
709
+ disable_compatibility_checks = OtpProperty(
710
+ description='Disable compatibility checks when querying OneTick database. '
711
+ 'Using this parameter outside test environment could lead to unexpected errors.',
712
+ base_default=False,
713
+ allowed_types=bool,
714
+ env_var_name='OTP_DISABLE_COMPATIBILITY_CHECKS',
715
+ )
716
+
717
+
718
+ def get_options_table(cls):
719
+ options_table = ('\n'
720
+ '.. csv-table::\n'
721
+ ' :header: "Name", "Environment Variable", "Description"\n'
722
+ ' :widths: auto\n\n')
723
+ for name, prop in cls.get_changeable_config_options().items():
724
+ name = f':py:attr:`otp.config.{name}<onetick.py.configuration.Config.{name}>`'
725
+ options_table += f' {name},"``{prop._env_var_name}``","{prop._description}"\n'
726
+ for name, prop in cls.get_derived_config_options().items():
727
+ name = f':py:attr:`otp.config.{name}<onetick.py.configuration.Config.{name}>`'
728
+ options_table += f' {name},"","{prop._description}"\n'
729
+ return options_table
730
+
731
+
732
+ class OptionsTable:
733
+ __doc__ = get_options_table(Config)
734
+
735
+
736
+ config = Config()