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,325 @@
1
+ from functools import partial
2
+
3
+ import pandas as pd
4
+
5
+ import onetick.py as otp
6
+ from onetick.py.otq import otq
7
+
8
+ from onetick.py import utils
9
+ from onetick.py.sources.data_source import _start_doc, _end_doc, _symbol_doc
10
+ from onetick.py.docs.utils import docstring, param_doc
11
+
12
+
13
+ COMMON_SOURCE_DOC_PARAMS = [_start_doc, _end_doc, _symbol_doc]
14
+ OQD_TICK_TYPE = 'OQD::*'
15
+
16
+
17
+ def _modify_query_times(src):
18
+ src.sink(otq.ModifyQueryTimes(
19
+ start_time=('parse_time("%Y%m%d %H:%M:%S.%q", '
20
+ 'time_format("%Y%m%d", _START_TIME, _TIMEZONE) + " 00:00:00.000", "GMT")'),
21
+ end_time=('parse_time("%Y%m%d %H:%M:%S.%q", '
22
+ 'time_format("%Y%m%d", _END_TIME, _TIMEZONE) + " 24:00:00.000", "GMT")'),
23
+ output_timestamp='min(max(TIMESTAMP,_START_TIME),_END_TIME)'
24
+ ))
25
+
26
+
27
+ _exch_doc = param_doc(
28
+ name='exch',
29
+ desc="""
30
+ The OneQuantData exchange code for the desired price series. Possible values:
31
+
32
+ - 'all'
33
+ return data for all exchanges;
34
+
35
+ - 'main'
36
+ return data main pricing exchange;
37
+
38
+ - any other string value will treated as exchange name to filter data.
39
+
40
+ Default: 'all'.
41
+ """,
42
+ str_annotation="str, 'all', 'main'",
43
+ default='all',
44
+ )
45
+
46
+
47
+ class OHLCV(otp.Source):
48
+ @docstring(parameters=[_exch_doc] + COMMON_SOURCE_DOC_PARAMS, add_self=True)
49
+ def __init__(
50
+ self,
51
+ exch='all',
52
+ symbol=utils.adaptive,
53
+ start=utils.adaptive,
54
+ end=utils.adaptive,
55
+ **kwargs
56
+ ):
57
+ """
58
+ OneQuantData™ source to retrieve a time series of unadjusted
59
+ prices for a symbol for one particular pricing exchange of daily OHLCV data.
60
+ Output ticks have fields: OPEN, HIGH, LOW, CLOSE, VOLUME, CURRENCY, EXCH.
61
+
62
+ Examples
63
+ --------
64
+ >>> src = otp.oqd.sources.OHLCV(exch="USPRIM") # doctest: +SKIP
65
+ >>> otp.run(src, # doctest: +SKIP
66
+ ... symbols='BTKR::::GOOGL US',
67
+ ... start=otp.dt(2018, 8, 1),
68
+ ... end=otp.dt(2018, 8, 2),
69
+ ... symbol_date=otp.dt(2018, 8, 1))
70
+ Time OID EXCH CURRENCY OPEN HIGH LOW CLOSE VOLUME
71
+ 0 2018-08-01 00:00:00 74143 USPRIM USD 1242.73 1245.72 1225.00 1232.99 605680.0
72
+ 1 2018-08-01 20:00:00 74143 USPRIM USD 1219.69 1244.25 1218.06 1241.13 596960.0
73
+ """
74
+ if self._try_default_constructor(**kwargs):
75
+ return
76
+
77
+ super().__init__(
78
+ _symbols=symbol,
79
+ _start=start,
80
+ _end=end,
81
+ _base_ep_func=partial(self.build, exch=exch)
82
+ )
83
+
84
+ self.schema.set(OID=str,
85
+ EXCH=str,
86
+ CURRENCY=str,
87
+ OPEN=float,
88
+ HIGH=float,
89
+ LOW=float,
90
+ CLOSE=float,
91
+ VOLUME=float)
92
+
93
+ def build(self, exch):
94
+ ep = None
95
+ if exch == 'all':
96
+ ep = otp.oqd.eps.OqdSourceDprcAll()
97
+ elif exch == 'main':
98
+ ep = otp.oqd.eps.OqdSourceDprcMain()
99
+ else:
100
+ ep = otp.oqd.eps.OqdSourceDprcExch(exch=exch)
101
+
102
+ src = otp.Source(ep)
103
+ src.tick_type(OQD_TICK_TYPE)
104
+ _modify_query_times(src)
105
+ return src
106
+
107
+
108
+ class CorporateActions(otp.Source):
109
+ """
110
+ OneQuantData™ source EP to retrieve a time series of corporate
111
+ actions for a symbol.
112
+
113
+ This source will return all corporate action fields available for a symbol
114
+ with EX-Dates between the query start time and end time. The
115
+ timestamp of the series is equal to the EX-Date of the corporate
116
+ action with a time of 0:00:00 GMT.
117
+
118
+ Examples
119
+ --------
120
+ >>> src = otp.oqd.sources.CorporateActions() # doctest: +SKIP
121
+ >>> otp.run(src, # doctest: +SKIP
122
+ ... symbols='TDEQ::::AAPL',
123
+ ... start=otp.dt(2021, 1, 1),
124
+ ... end=otp.dt(2021, 8, 6),
125
+ ... symbol_date=otp.dt(2021, 2, 18),
126
+ ... timezone='GMT')
127
+ Time OID ACTION_ID ACTION_TYPE ACTION_ADJUST ACTION_CURRENCY ANN_DATE EX_DATE PAY_DATE REC_DATE\
128
+ TERM_NOTE TERM_RECORD_TYPE ACTION_STATUS
129
+ 0 2021-02-05 9706 16799540 CASH_DIVIDEND 0.205 USD 20210127 20210205 20210211 20210208\
130
+ CASH:0.205@USD NORMAL
131
+ 1 2021-05-07 9706 17098817 CASH_DIVIDEND 0.220 USD 20210428 20210507 20210513 20210510\
132
+ CASH:0.22@USD NORMAL
133
+ 2 2021-08-06 9706 17331864 CASH_DIVIDEND 0.220 USD 20210727 20210806 20210812 20210809\
134
+ CASH:0.22@USD NORMAL
135
+
136
+ """
137
+
138
+ @docstring(parameters=COMMON_SOURCE_DOC_PARAMS, add_self=True)
139
+ def __init__(
140
+ self,
141
+ symbol=utils.adaptive,
142
+ start=utils.adaptive,
143
+ end=utils.adaptive,
144
+ **kwargs
145
+ ):
146
+ if self._try_default_constructor(**kwargs):
147
+ return
148
+
149
+ super().__init__(
150
+ _symbols=symbol,
151
+ _start=start,
152
+ _end=end,
153
+ _base_ep_func=partial(self.build)
154
+ )
155
+
156
+ self.schema.set(OID=str,
157
+ ACTION_ID=int,
158
+ ACTION_TYPE=str,
159
+ ACTION_ADJUST=float,
160
+ ACTION_CURRENCY=str,
161
+ ANN_DATE=int,
162
+ EX_DATE=int,
163
+ PAY_DATE=int,
164
+ REC_DATE=int,
165
+ TERM_NOTE=str,
166
+ TERM_RECORD_TYPE=str,
167
+ ACTION_STATUS=str)
168
+
169
+ def build(self):
170
+ ep = otp.oqd.eps.OqdSourceCacs()
171
+ src = otp.Source(ep)
172
+ src.tick_type(OQD_TICK_TYPE)
173
+ _modify_query_times(src)
174
+ return src
175
+
176
+
177
+ class DescriptiveFields(otp.Source):
178
+ """OneQuantData™ source to retrieve a time series of descriptive fields for a symbol.
179
+ There will only be ticks on days when some field in the descriptive data changes.
180
+ Output ticks will have fields:
181
+ OID, END_DATE, COUNTRY, EXCH, NAME,
182
+ ISSUE_DESC, ISSUE_CLASS, ISSUE_TYPE, ISSUE_STATUS,
183
+ SIC_CODE, IDSYM, TICKER, CALENDAR.
184
+
185
+ Note: currently actual fields have 9999 year in END_DATE, but it could not fit the
186
+ nanosecond timestamp, so it is replaced with 2035-01-01 date.
187
+
188
+ Examples
189
+ --------
190
+ >>> src = otp.oqd.sources.DescriptiveFields() # doctest: +SKIP
191
+ >>> otp.run(src, # doctest: +SKIP
192
+ ... symbols='1000001589',
193
+ ... start=otp.dt(2020, 3, 1),
194
+ ... end=otp.dt(2023, 3, 2),
195
+ ... timezone='GMT').iloc[:6]
196
+ Time OID END_DATE COUNTRY EXCH NAME ISSUE_DESC\
197
+ ISSUE_CLASS ISSUE_TYPE ISSUE_STATUS SIC_CODE IDSYM TICKER CALENDAR
198
+ 0 2020-03-01 1000001589 2020-03-23 LUX EL^X INVESTEC GLOBAL ST EUROPEAN HIGH YLD BD INC 2\
199
+ FUND NORMAL B2PT4G9
200
+ 1 2020-03-23 1000001589 2020-04-01 LUX EL^X NINETY ONE LIMITED EUROPEAN HIGH YLD BD INC 2\
201
+ FUND NORMAL B2PT4G9
202
+ 2 2020-04-01 1000001589 2021-01-01 LUX EL^X NINETY ONE LUX S.A EUROPEAN HIGH YLD BD INC 2\
203
+ FUND NORMAL B2PT4G9
204
+ 3 2021-01-01 1000001589 2021-06-18 LUX EL^X NINETY ONE LUX S.A EUROPEAN HIGH YLD BD INC 2\
205
+ FUND NORMAL B2PT4G9
206
+ 4 2021-06-18 1000001589 2022-01-01 LUX EL^X NINETY ONE LUX S.A GSF GBL HIGH YLD A2 EUR DIS\
207
+ FUND NORMAL B2PT4G9
208
+ 5 2022-01-01 1000001589 2022-01-28 LUX EL^X NINETY ONE LUX S.A GSF GBL HIGH YLD A2 EUR DIS\
209
+ FUND NORMAL B2PT4G9
210
+ """
211
+
212
+ @docstring(parameters=COMMON_SOURCE_DOC_PARAMS, add_self=True)
213
+ def __init__(
214
+ self,
215
+ symbol=utils.adaptive,
216
+ start=utils.adaptive,
217
+ end=utils.adaptive,
218
+ **kwargs
219
+ ):
220
+ if self._try_default_constructor(**kwargs):
221
+ return
222
+
223
+ super().__init__(
224
+ _symbols=symbol,
225
+ _start=start,
226
+ _end=end,
227
+ _base_ep_func=partial(self.build)
228
+ )
229
+
230
+ self.schema.set(
231
+ OID=str,
232
+ END_DATE=otp.nsectime,
233
+ COUNTRY=str,
234
+ EXCH=str,
235
+ NAME=str,
236
+ ISSUE_DESC=str,
237
+ ISSUE_CLASS=str,
238
+ ISSUE_TYPE=str,
239
+ ISSUE_STATUS=str,
240
+ SIC_CODE=str,
241
+ IDSYM=str,
242
+ TICKER=str,
243
+ CALENDAR=str,)
244
+
245
+ def build(self):
246
+ ep = otp.oqd.eps.OqdSourceDes()
247
+ src = otp.Source(ep)
248
+ src.tick_type(OQD_TICK_TYPE)
249
+ _modify_query_times(src)
250
+
251
+ # work-around to resolve problem with pandas timestamp out of bounds
252
+ pd_max = pd.Timestamp.max.strftime('%Y%m%d%H%M%S')
253
+ src.sink(otq.UpdateFields(
254
+ set='END_DATE=PARSE_NSECTIME("%Y-%m-%d", "2035-01-01", _TIMEZONE)',
255
+ where=f'AS_YYYYMMDDHHMMSS(END_DATE) > {pd_max}'))
256
+ return src
257
+
258
+
259
+ class SharesOutstanding(otp.Source):
260
+ """
261
+ Logic is implemented in OQD_SOURCE_SHO EP to retrieve a time series of shares
262
+ outstanding for a stock.
263
+
264
+ The source retrieves a time series of shares outstanding
265
+ for a stock. This source only applies to stocks or securities that have
266
+ published shares outstanding data.
267
+
268
+ The series represents total shares outstanding and is not free float
269
+ adjusted.
270
+
271
+ Note: currently actual fields have 9999 year in END_DATE, but it could not fit the
272
+ nanosecond timestamp, so it is replaced with 2035-01-01 date.
273
+
274
+
275
+ Examples
276
+ --------
277
+ >>> src = otp.oqd.sources.SharesOutstanding() # doctest: +SKIP
278
+ >>> otp.run(src, # doctest: +SKIP
279
+ ... symbols='TDEQ::::AAPL',
280
+ ... start=otp.dt(2021, 1, 1),
281
+ ... end=otp.dt(2021, 8, 6),
282
+ ... symbol_date=otp.dt(2021, 2, 18),
283
+ ... timezone='GMT')
284
+ Time OID END_DATE REPORT_MONTH SHARES
285
+ 0 2021-01-01 9706 2021-01-06 202009 1.700180e+10
286
+ 1 2021-01-06 9706 2021-01-29 202009 1.682326e+10
287
+ 2 2021-01-29 9706 2021-05-03 202012 1.678810e+10
288
+ 3 2021-05-03 9706 2021-07-30 202103 1.668763e+10
289
+ 4 2021-07-30 9706 2021-10-29 202106 1.653017e+10
290
+ """
291
+ @docstring(parameters=COMMON_SOURCE_DOC_PARAMS, add_self=True)
292
+ def __init__(
293
+ self,
294
+ symbol=otp.utils.adaptive,
295
+ start=otp.utils.adaptive,
296
+ end=otp.utils.adaptive,
297
+ **kwargs
298
+ ):
299
+ if self._try_default_constructor(**kwargs):
300
+ return
301
+
302
+ super().__init__(
303
+ _symbols=symbol,
304
+ _start=start,
305
+ _end=end,
306
+ _base_ep_func=partial(self.build)
307
+ )
308
+
309
+ self.schema.set(OID=str,
310
+ END_DATE=otp.nsectime,
311
+ REPORT_MONTH=int,
312
+ SHARES=int)
313
+
314
+ def build(self):
315
+ ep = otp.oqd.eps.OqdSourceSho()
316
+ src = otp.Source(ep)
317
+ src.tick_type(OQD_TICK_TYPE)
318
+ _modify_query_times(src)
319
+
320
+ # work-around to resolve problem with pandas timestamp out of bounds
321
+ pd_max = pd.Timestamp.max.strftime('%Y%m%d%H%M%S')
322
+ src.sink(otq.UpdateFields(
323
+ set='END_DATE=PARSE_NSECTIME("%Y-%m-%d", "2035-01-01", _TIMEZONE)',
324
+ where=f'AS_YYYYMMDDHHMMSS(END_DATE) > {pd_max}'))
325
+ return src
onetick/py/otq.py ADDED
@@ -0,0 +1,216 @@
1
+ # This file is used to import the correct query module:
2
+ # onetick.query or onetick.query_webapi
3
+ # based on the environment variable OTP_WEBAPI
4
+ # Re-use this file in your tests to import the correct onetick.query module
5
+ # Also it is override pyomd and OneTickLib classes with mock classes
6
+
7
+ import getpass
8
+ import inspect
9
+ import os
10
+ import tempfile
11
+ import warnings
12
+ import onetick.py as otp
13
+
14
+
15
+ class OneTickLib:
16
+ # mock class for OneTickLib, used for webapi and onetick-query-stubs
17
+ # maybe it is not right to combine this namesake classes (onetick.lib.OneTickLib and pyomd.OneTickLib)
18
+ # but it is done to simplify the code and it is not affecting anything except tests
19
+ LOGGING_LEVEL_MIN = 0
20
+ LOGGING_LEVEL_LOW = 1
21
+ LOGGING_LEVEL_MEDIUM = 2
22
+ LOGGING_LEVEL_MAX = 3
23
+ set_authentication_token = None
24
+
25
+ def __init__(self, *args, **kwargs): # NOSONAR
26
+ pass
27
+
28
+ def set_log_file(self, log_file): # NOSONAR
29
+ pass
30
+
31
+ def cleanup(self): # NOSONAR
32
+ pass
33
+
34
+
35
+ if os.getenv("OTP_SKIP_OTQ_VALIDATION"):
36
+ import onetick_stubs as otq # noqa: F401
37
+ import pyomd # noqa: F401
38
+
39
+ class ConfigStub:
40
+ API_CONFIG: dict = {}
41
+
42
+ class otli:
43
+ OneTickLib = OneTickLib # NOSONAR
44
+
45
+ for key, value in otq.query.__dict__.items():
46
+ setattr(otq, key, value)
47
+ setattr(otq, 'webapi', False)
48
+ setattr(otq, 'config', ConfigStub)
49
+ setattr(otq, 'graph_components', otq)
50
+
51
+ elif otp.__webapi__:
52
+ import onetick.query_webapi as otq # noqa: F401
53
+ setattr(otq, 'webapi', True)
54
+
55
+ from onetick.py.pyomd_mock import pyomd
56
+
57
+ __original_run = otq.run
58
+
59
+ def run(*args, **kwargs):
60
+ from onetick.py import config # noqa
61
+ from onetick.py.compatibility import is_max_concurrency_with_webapi_supported
62
+
63
+ if not config.http_address and 'http_address' not in kwargs:
64
+ raise ValueError('otp.run() http_address keyword param, '
65
+ 'otp.config.http_address or OTP_HTTP_ADDRESS '
66
+ 'environment variable are required '
67
+ 'when using WebAPI mode.')
68
+
69
+ # TODO WEBAPI review this
70
+ # if file name is not in single quotes, then put it in single quotes
71
+ query_name = None
72
+ query = kwargs.get('query', None)
73
+ if isinstance(query, str):
74
+ if query[0] == "'" and query[-1] == "'":
75
+ query = query.replace("'", "")
76
+ if '::' in query:
77
+ query_name = query.split('::')[-1]
78
+ query = query.replace(f'::{query_name}', '')
79
+ kwargs['query'] = query
80
+ kwargs['query_name'] = query_name
81
+
82
+ del_params = [
83
+ 'start_time_expression',
84
+ 'end_time_expression',
85
+ 'alternative_username',
86
+ 'batch_size',
87
+ 'treat_byte_arrays_as_strings',
88
+ 'output_matrix_per_field',
89
+ 'return_utc_times',
90
+ 'connection',
91
+ 'svg_path',
92
+ 'use_connection_pool',
93
+ 'time_as_nsec',
94
+ 'max_expected_ticks_per_symbol',
95
+ ]
96
+ ignore_deleted_params = [
97
+ 'treat_byte_arrays_as_strings',
98
+ 'time_as_nsec',
99
+ 'alternative_username',
100
+ 'max_expected_ticks_per_symbol'
101
+ ]
102
+ for param in del_params:
103
+ if param in kwargs:
104
+ if kwargs[param] and param not in ignore_deleted_params:
105
+ warnings.warn(f'Parameter {param} is not supported in WebAPI mode and will be ignored.')
106
+ del kwargs[param]
107
+
108
+ from onetick.py import config # noqa
109
+ if 'http_address' not in kwargs:
110
+ kwargs['http_address'] = config.http_address
111
+
112
+ if kwargs.get('username'):
113
+ kwargs['http_username'] = kwargs['username']
114
+ del kwargs['username']
115
+ else:
116
+ kwargs['http_username'] = config.http_username
117
+
118
+ if kwargs.get('password'):
119
+ kwargs['http_password'] = kwargs['password']
120
+ del kwargs['password']
121
+ else:
122
+ kwargs['http_password'] = config.http_password
123
+
124
+ if 'access_token' not in kwargs:
125
+ if config.access_token:
126
+ kwargs['access_token'] = config.access_token
127
+ elif not kwargs['access_token']:
128
+ del kwargs['access_token']
129
+
130
+ access_token_url = kwargs.get('access_token_url', config.access_token_url)
131
+ if access_token_url:
132
+ if not hasattr(otq, 'get_access_token'):
133
+ raise RuntimeError('Current `onetick.query_webapi` version doesn\'t have `get_access_token` function')
134
+
135
+ if kwargs.get('access_token'):
136
+ raise ValueError('Both `access_token` and `access_token_url` set, instead of only one of them.')
137
+
138
+ if 'client_id' in kwargs:
139
+ client_id = kwargs.pop('client_id')
140
+ else:
141
+ client_id = config.client_id
142
+
143
+ if 'client_secret' in kwargs:
144
+ client_secret = kwargs.pop('client_secret')
145
+ else:
146
+ client_secret = config.client_secret
147
+
148
+ for param_name, param_value in zip(['client_id', 'client_secret'], [client_id, client_secret]):
149
+ if not param_value:
150
+ raise ValueError(f'`access_token_url` parameter set, however `{param_name}` parameter missing.')
151
+
152
+ kwargs['access_token'] = otq.get_access_token(access_token_url, client_id, client_secret)
153
+
154
+ if 'access_token_url' in kwargs:
155
+ del kwargs['access_token_url']
156
+
157
+ if 'http_proxy' not in kwargs:
158
+ kwargs['http_proxy'] = config.http_proxy
159
+
160
+ if 'https_proxy' not in kwargs:
161
+ kwargs['https_proxy'] = config.https_proxy
162
+
163
+ webapi_run_parameters = inspect.signature(__original_run).parameters
164
+
165
+ trusted_certificate_file_arg = kwargs.pop('trusted_certificates_file',
166
+ kwargs.pop('trusted_certificate_file', None))
167
+ trusted_certificate_file_value = (
168
+ trusted_certificate_file_arg if trusted_certificate_file_arg is not None
169
+ else config.trusted_certificates_file
170
+ )
171
+ if trusted_certificate_file_value is not None:
172
+ trusted_certificates_supported = set(webapi_run_parameters).intersection({'trusted_certificates_file',
173
+ 'trusted_certificate_file'})
174
+ if not trusted_certificates_supported:
175
+ raise ValueError(
176
+ "Parameter `trusted_certificates_file` was set,"
177
+ " however current version of OneTick doesn't support it."
178
+ )
179
+ trusted_certificates_supported_param = list(trusted_certificates_supported)[0]
180
+ kwargs[trusted_certificates_supported_param] = trusted_certificate_file_value
181
+
182
+ if 'callback' in kwargs and kwargs['callback'] is not None:
183
+ kwargs['output_mode'] = otq.QueryOutputMode.callback
184
+
185
+ if 'max_concurrency' in kwargs and not is_max_concurrency_with_webapi_supported():
186
+ kwargs['max_concurrency'] = None
187
+
188
+ return __original_run(*args, **kwargs)
189
+
190
+ otq.run = run
191
+
192
+ otq.OneTickLib = OneTickLib
193
+
194
+ class otli: # type: ignore # noqa: F401
195
+ OneTickLib = otq.OneTickLib # NOSONAR
196
+
197
+ else:
198
+ import onetick.query as otq # type: ignore # noqa: F401
199
+ import pyomd # type: ignore # noqa: F401
200
+ import onetick.lib.instance as otli # type: ignore # noqa: F401
201
+ setattr(otq, 'webapi', False)
202
+
203
+
204
+ def _tmp_otq_path():
205
+ # copied from onetick.test.fixtures _keep_generated_dir() with replacement to /tmp
206
+ # required with OTP_WEBAPI_TEST_MODE to separate otq files from shared dbs+config+locator+acl files
207
+ from onetick.py import utils # noqa
208
+ res = os.path.join(utils.TMP_CONFIGS_DIR(), os.environ.get("ONE_TICK_TMP_DIR", "otqs"))
209
+ res = res.replace(utils.temp.WEBAPI_TEST_MODE_SHARED_CONFIG,
210
+ os.path.join(tempfile.gettempdir(), "test_" + getpass.getuser()))
211
+
212
+ # % and + is some webapi related path bugs, probably would be fixed someday
213
+ return res.replace("%", "_").replace("+", "_")
214
+
215
+
216
+ __all__ = ['otq', 'pyomd', 'otli', '_tmp_otq_path']
@@ -0,0 +1,47 @@
1
+ import datetime
2
+ import onetick.py as otp
3
+
4
+
5
+ if otp.__webapi__:
6
+ try:
7
+ from onetick.query_webapi import QueryProperties # noqa: E0611
8
+ except ImportError as e:
9
+ try:
10
+ import onetick.query_webapi # noqa
11
+ raise RuntimeError("You're trying to use onetick.query_webapi module, "
12
+ "that is not compatible with onetick.py. "
13
+ "Please, use onetick.query module instead (unset OTP_WEBAPI), "
14
+ "or install onetick.query_webapi==1.24.20240715 or newer. "
15
+ "Also, check that your PYTHONPATH doesn't have onetick binary path, "
16
+ "because onetick distribution could have older onetick.query_webapi, "
17
+ "that mirror your pip-installed version.") from e
18
+ except ImportError as e2:
19
+ raise ImportError(
20
+ "OTP_WEBAPI environment variable is set,"
21
+ " but onetick.query_webapi module is not available."
22
+ " Please, install onetick.query_webapi to avoid import errors"
23
+ " or unset OTP_WEBAPI to use onetick.query module instead."
24
+ ) from e2
25
+
26
+ # copied from one_market_data/one_tick/bin/python/onetick/query/_internal_utils.py
27
+ def quoted(str_object):
28
+ if len(str_object) <= 1:
29
+ return str_object
30
+ if str_object[0] == "'" and str_object[-1] == "'" or str_object[0] == '"' and str_object[-1] == '"':
31
+ return str_object
32
+ return f"'{str_object}'"
33
+
34
+ class OT_time_nsec_mock: # NOSONAR
35
+ def __init__(self, number):
36
+ self.number = number
37
+
38
+ def __int__(self):
39
+ return int(self.number / 1e9)
40
+
41
+ class pyomd:
42
+ timeval_t = datetime.datetime # type: ignore
43
+ QueryProperties = QueryProperties # type: ignore # NOSONAR
44
+
45
+ @staticmethod
46
+ def OT_time_nsec(number): # NOSONAR
47
+ return int(number / 1e9)