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,2216 @@
1
+ from typing import Union
2
+
3
+ import onetick.py as otp
4
+ from onetick.py.core.column import _Column
5
+ from .compute import Compute
6
+ from .high_low import Max, Min, HighTick, LowTick, HighTime, LowTime
7
+ from .other import (First, Last, FirstTime, LastTime, Count, Vwap, FirstTick,
8
+ LastTick, Distinct, Sum, Average, StdDev, TimeWeightedAvg,
9
+ Median, Correlation, OptionPrice, Ranking, Variance,
10
+ Percentile, FindValueForPercentile, ExpWAverage, ExpTwAverage,
11
+ StandardizedMoment, PortfolioPrice, MultiPortfolioPrice, Return, ImpliedVol,
12
+ LinearRegression)
13
+ from .order_book import (ObSnapshot, OB_SNAPSHOT_DOC_PARAMS,
14
+ ObSnapshotWide, OB_SNAPSHOT_WIDE_DOC_PARAMS,
15
+ ObSnapshotFlat, OB_SNAPSHOT_FLAT_DOC_PARAMS,
16
+ ObSummary, OB_SUMMARY_DOC_PARAMS,
17
+ ObSize, OB_SIZE_DOC_PARAMS,
18
+ ObVwap, OB_VWAP_DOC_PARAMS,
19
+ ObNumLevels, OB_NUM_LEVELS_DOC_PARAMS)
20
+ from .generic import Generic
21
+ from ._docs import (_column_doc,
22
+ _running_doc,
23
+ _all_fields_doc,
24
+ _bucket_interval_doc,
25
+ _bucket_time_doc,
26
+ _bucket_units_doc,
27
+ _bucket_end_condition_doc,
28
+ _end_condition_per_group_doc,
29
+ _boundary_tick_bucket_doc,
30
+ _group_by_doc,
31
+ _groups_to_display_doc,
32
+ _n_doc,
33
+ _keep_timestamp_doc,
34
+ _time_series_type_doc,
35
+ _time_series_type_w_doc,
36
+ _selection_doc,
37
+ _query_fun_doc,
38
+ _bucket_delimiter_doc,
39
+ _biased_doc,
40
+ _large_ints_doc,
41
+ _null_int_val_doc,
42
+ _skip_tick_if_doc,
43
+ _default_tick_doc,
44
+ _decay_doc,
45
+ _decay_value_type_doc,
46
+ _decay_value_type_hl_doc,
47
+ _degree_doc,
48
+ _weight_field_name_doc,
49
+ _weight_multiplier_field_name_doc,
50
+ _portfolio_side_doc,
51
+ _weight_type_doc,
52
+ _symbols_doc,
53
+ _portfolios_query_doc,
54
+ _portfolios_query_params_doc,
55
+ _portfolio_value_field_name_doc,
56
+ _columns_portfolio_doc,
57
+ _interest_rate_doc,
58
+ _price_field_doc,
59
+ _option_price_field_doc,
60
+ _method_doc,
61
+ _precision_doc,
62
+ _value_for_non_converge_doc,
63
+ _option_type_field_doc,
64
+ _strike_price_field_doc,
65
+ _days_in_year_doc,
66
+ _days_till_expiration_field_doc,
67
+ _expiration_date_field_doc)
68
+ from onetick.py.docs.utils import docstring, param_doc
69
+
70
+ # This module mostly focused on providing annotations and documentation for end user
71
+ # If you are looking for implementation check return object of each function
72
+
73
+
74
+ @docstring(parameters=[_running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc, _bucket_units_doc,
75
+ _bucket_end_condition_doc, _end_condition_per_group_doc, _boundary_tick_bucket_doc,
76
+ _group_by_doc, _groups_to_display_doc])
77
+ def compute(*args, **kwargs):
78
+ """
79
+ Generate object that collects aggregations
80
+
81
+ See also
82
+ --------
83
+ **COMPUTE** OneTick event processor
84
+
85
+ Examples
86
+ --------
87
+ >>> data = otp.Ticks(X=[1, 2, 3, 4], offset=[0, 1000, 1500, 3000])
88
+ >>> c = otp.agg.compute(running=True, bucket_interval=2)
89
+ >>> c.add('X_MEAN', otp.agg.average("X"))
90
+ >>> c.add('X_STD', otp.agg.stddev("X"))
91
+ >>> data = c.apply(data)
92
+ >>> otp.run(data)
93
+ Time X_MEAN X_STD
94
+ 0 2003-12-01 00:00:00.000 1.0 0.000000
95
+ 1 2003-12-01 00:00:01.000 1.5 0.500000
96
+ 2 2003-12-01 00:00:01.500 2.0 0.816497
97
+ 3 2003-12-01 00:00:02.000 2.5 0.500000
98
+ 4 2003-12-01 00:00:03.000 3.5 0.500000
99
+ 5 2003-12-01 00:00:03.500 4.0 0.000000
100
+ 6 2003-12-01 00:00:05.000 NaN NaN
101
+
102
+ """
103
+ return Compute(*args, **kwargs)
104
+
105
+
106
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
107
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
108
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
109
+ _time_series_type_doc, _large_ints_doc,
110
+ _null_int_val_doc])
111
+ def max(*args, **kwargs):
112
+ """
113
+ Return maximum value of input ``column``
114
+
115
+ See also
116
+ --------
117
+ **HIGH** OneTick event processor
118
+
119
+ Examples
120
+ --------
121
+ >>> data = otp.Ticks(X=[1, 2, 3, 4])
122
+ >>> data = data.agg({'RESULT': otp.agg.max('X')}) # OTdirective: snippet-name: Aggregations.max;
123
+ >>> otp.run(data)
124
+ Time RESULT
125
+ 0 2003-12-04 4
126
+ """
127
+ return Max(*args, **kwargs)
128
+
129
+
130
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
131
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
132
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
133
+ _time_series_type_doc, _large_ints_doc,
134
+ _null_int_val_doc])
135
+ def min(*args, **kwargs):
136
+ """
137
+ Return minimum value of input ``column``
138
+
139
+ See also
140
+ --------
141
+ **LOW** OneTick event processor
142
+
143
+ Examples
144
+ --------
145
+
146
+ >>> data = otp.Ticks(X=[1, 2, 3, 4])
147
+ >>> data = data.agg({'RESULT': otp.agg.min('X')}) # OTdirective: snippet-name: Aggregations.min;
148
+ >>> otp.run(data)
149
+ Time RESULT
150
+ 0 2003-12-04 1
151
+ """
152
+ return Min(*args, **kwargs)
153
+
154
+
155
+ @docstring(parameters=[_column_doc, _n_doc, _running_doc, _bucket_interval_doc, _bucket_time_doc,
156
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
157
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
158
+ _keep_timestamp_doc, _selection_doc,
159
+ _time_series_type_doc])
160
+ def high_tick(*args, **kwargs):
161
+ """
162
+ Select ``n`` ticks with the highest values in the ``column`` field
163
+
164
+ See also
165
+ --------
166
+ **HIGH_TICK** OneTick event processor
167
+
168
+ Examples
169
+ --------
170
+ >>> data = otp.Ticks(X=[1, 2, 3, 4], offset=[0, 1000, 1500, 3000])
171
+ >>> agg = otp.agg.high_tick('X', 2)
172
+ >>> data = agg.apply(data)
173
+ >>> otp.run(data)
174
+ Time X
175
+ 0 2003-12-01 00:00:01.500 3
176
+ 1 2003-12-01 00:00:03.000 4
177
+ """
178
+ return HighTick(*args, **kwargs)
179
+
180
+
181
+ @docstring(parameters=[_column_doc, _n_doc, _running_doc, _bucket_interval_doc, _bucket_time_doc,
182
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
183
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
184
+ _keep_timestamp_doc, _selection_doc,
185
+ _time_series_type_doc])
186
+ def low_tick(*args, **kwargs):
187
+ """
188
+ Select ``n`` ticks with the lowest values in the ``column`` field
189
+
190
+ See also
191
+ --------
192
+ **LOW_TICK** OneTick event processor
193
+
194
+ Examples
195
+ --------
196
+ >>> data = otp.Ticks(X=[1, 2, 3, 4], offset=[0, 1000, 1500, 3000])
197
+ >>> agg = otp.agg.low_tick('X', 2)
198
+ >>> data = agg.apply(data)
199
+ >>> otp.run(data)
200
+ Time X
201
+ 0 2003-12-01 00:00:00 1
202
+ 1 2003-12-01 00:00:01 2
203
+ """
204
+ return LowTick(*args, **kwargs)
205
+
206
+
207
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
208
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
209
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
210
+ _selection_doc, _time_series_type_doc])
211
+ def high_time(*args, **kwargs):
212
+ """
213
+ Returns timestamp of tick with highest value of input field
214
+
215
+ See also
216
+ --------
217
+ **HIGH_TIME** OneTick event processor
218
+
219
+ Examples
220
+ --------
221
+
222
+ >>> data = otp.Ticks(X=[1, 2, 4, 3], offset=[0, 1000, 1500, 3000])
223
+ >>> data = data.agg({'RESULT': otp.agg.high_time(['X'])}) # OTdirective: snippet-name: Aggregations.high time;
224
+ >>> otp.run(data)
225
+ Time RESULT
226
+ 0 2003-12-04 2003-12-01 00:00:01.500
227
+ """
228
+ return HighTime(*args, **kwargs)
229
+
230
+
231
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
232
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
233
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
234
+ _selection_doc, _time_series_type_doc])
235
+ def low_time(*args, **kwargs):
236
+ """
237
+ Returns timestamp of tick with lowest value of input field
238
+
239
+ See also
240
+ --------
241
+ **LOW_TIME** OneTick event processor
242
+
243
+ Examples
244
+ --------
245
+
246
+ >>> data = otp.Ticks(X=[2, 1, 3, 4], offset=[0, 1000, 1500, 3000])
247
+ >>> data = data.agg({'RESULT': otp.agg.low_time(['X'])}) # OTdirective: snippet-name: Aggregations.low time;
248
+ >>> otp.run(data)
249
+ Time RESULT
250
+ 0 2003-12-04 2003-12-01 00:00:01
251
+ """
252
+ return LowTime(*args, **kwargs)
253
+
254
+
255
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
256
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
257
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
258
+ _large_ints_doc, _null_int_val_doc,
259
+ _skip_tick_if_doc, _time_series_type_doc])
260
+ def first(*args, **kwargs):
261
+ """
262
+ Return first value of input field
263
+
264
+ See also
265
+ --------
266
+ **FIRST** OneTick event processor
267
+
268
+ Examples
269
+ --------
270
+
271
+ >>> data = otp.Ticks(X=[1, 2, 3, 4])
272
+ >>> agg = otp.agg.first('X')
273
+ >>> data = agg.apply(data)
274
+ >>> otp.run(data)
275
+ Time X
276
+ 0 2003-12-04 1
277
+ """
278
+ return First(*args, **kwargs)
279
+
280
+
281
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
282
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
283
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
284
+ _large_ints_doc, _null_int_val_doc,
285
+ _skip_tick_if_doc, _time_series_type_doc])
286
+ def last(*args, **kwargs):
287
+ """
288
+ Return last value of input field
289
+
290
+ See also
291
+ --------
292
+ **LAST** OneTick event processor
293
+
294
+ Examples
295
+ --------
296
+ >>> data = otp.Ticks(X=[1, 2, 3, 4])
297
+ >>> agg = otp.agg.last('X')
298
+ >>> data = agg.apply(data)
299
+ >>> otp.run(data)
300
+ Time X
301
+ 0 2003-12-04 4
302
+ """
303
+ return Last(*args, **kwargs)
304
+
305
+
306
+ @docstring(parameters=[_running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
307
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
308
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
309
+ _time_series_type_doc])
310
+ def first_time(*args, **kwargs):
311
+ """
312
+ Return timestamp of first tick
313
+
314
+ See also
315
+ --------
316
+ **FIRST_TIME** OneTick event processor
317
+
318
+ Examples
319
+ --------
320
+
321
+ >>> data = otp.Ticks(X=[1, 2, 3, 4], offset=[0, 1000, 1500, 3000])
322
+ >>> data = data.agg({'RESULT': otp.agg.first_time()}) # OTdirective: snippet-name: Aggregations.first time;
323
+ >>> otp.run(data)
324
+ Time RESULT
325
+ 0 2003-12-04 2003-12-01
326
+ """
327
+ return FirstTime(*args, **kwargs)
328
+
329
+
330
+ @docstring(parameters=[_running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
331
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
332
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
333
+ _time_series_type_doc])
334
+ def last_time(*args, **kwargs):
335
+ """
336
+ Return timestamp of last tick
337
+
338
+ See also
339
+ --------
340
+ **LAST_TIME** OneTick event processor
341
+
342
+ Examples
343
+ --------
344
+ >>> data = otp.Ticks(X=[1, 2, 3, 4], offset=[0, 1000, 1500, 3000])
345
+ >>> data = data.agg({'RESULT': otp.agg.last_time()}) # OTdirective: snippet-name: Aggregations.last time;
346
+ >>> otp.run(data)
347
+ Time RESULT
348
+ 0 2003-12-04 2003-12-01 00:00:03
349
+ """
350
+ return LastTime(*args, **kwargs)
351
+
352
+
353
+ @docstring(parameters=[_running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc, _bucket_units_doc,
354
+ _bucket_end_condition_doc, _end_condition_per_group_doc, _boundary_tick_bucket_doc,
355
+ _group_by_doc, _groups_to_display_doc])
356
+ def count(*args, **kwargs):
357
+ """
358
+ Returns number of ticks
359
+
360
+ See also
361
+ --------
362
+ **NUM_TICKS** OneTick event processor
363
+
364
+ Examples
365
+ --------
366
+ >>> data = otp.Ticks(X=[1, 2, 3, 4])
367
+ >>> data = data.agg({'RESULT': otp.agg.count()}) # OTdirective: snippet-name: Aggregations.count;
368
+ >>> otp.run(data)
369
+ Time RESULT
370
+ 0 2003-12-04 4
371
+ """
372
+ return Count(*args, **kwargs)
373
+
374
+
375
+ _price_doc = param_doc(name='price_column',
376
+ str_annotation='str or Column',
377
+ desc='price column for vwap',
378
+ annotation=Union[str, _Column])
379
+
380
+ _size_doc = param_doc(name='size_column',
381
+ str_annotation='str or Column',
382
+ desc='size column for vwap',
383
+ annotation=Union[str, _Column])
384
+
385
+
386
+ @docstring(parameters=[_price_doc, _size_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
387
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
388
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc])
389
+ def vwap(*args, **kwargs):
390
+ """
391
+ Returns volume weighted average price
392
+
393
+ See also
394
+ --------
395
+ **VWAP** OneTick event processor
396
+
397
+ Examples
398
+ --------
399
+ >>> # OTdirective: snippet-name: Aggregations.vwap;
400
+ >>> data = otp.Ticks(P=[1, 2, 3, 4], S=[10, 20, 30, 40])
401
+ >>> data = data.agg({'RESULT': otp.agg.vwap('P','S')})
402
+ >>> otp.run(data)
403
+ Time RESULT
404
+ 0 2003-12-04 3.0
405
+ """
406
+ return Vwap(*args, **kwargs)
407
+
408
+
409
+ @docstring(parameters=[_running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
410
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
411
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc])
412
+ def correlation(*args, **kwargs):
413
+ """
414
+ Returns Pearson correlation coefficient value between two numeric fields.
415
+
416
+ Parameters
417
+ ----------
418
+ column_name_1: str
419
+ The name of the field in the input stream whose value is to be used by the aggregation
420
+ column_name_2: str
421
+ The name of the field in the input stream whose value is to be used by the aggregation
422
+
423
+ See also
424
+ --------
425
+ **CORRELATION** OneTick event processor
426
+
427
+ Examples
428
+ --------
429
+ >>> # OTdirective: snippet-name: Aggregations.correlation;
430
+ >>> data = otp.Ticks(P=[1, 2, 3, 4], S=[10, 20, 30, 40])
431
+ >>> data = data.agg({'RESULT': otp.agg.correlation('P','S')})
432
+ >>> otp.run(data)
433
+ Time RESULT
434
+ 0 2003-12-04 1.0
435
+
436
+ >>> data = otp.Ticks(P=[1, 2, 3, 4], S=[40, 30, 20, 10])
437
+ >>> data = otp.agg.correlation('P', 'S').apply(data)
438
+ >>> otp.run(data)
439
+ Time CORRELATION
440
+ 0 2003-12-04 -1.0
441
+
442
+ >>> data = otp.Ticks(P=[1, 2, 3, 4], S=[40, 30, 10, 20])
443
+ >>> data = otp.agg.correlation('P', 'S', bucket_units='ticks', bucket_interval=2).apply(data)
444
+ >>> otp.run(data)
445
+ Time CORRELATION
446
+ 0 2003-12-01 00:00:00.001 -1.0
447
+ 1 2003-12-01 00:00:00.003 1.0
448
+ """
449
+ return Correlation(*args, **kwargs)
450
+
451
+
452
+ @docstring(parameters=[_n_doc, _running_doc, _bucket_interval_doc, _bucket_time_doc, _bucket_units_doc,
453
+ _bucket_end_condition_doc, _end_condition_per_group_doc, _boundary_tick_bucket_doc,
454
+ _group_by_doc, _groups_to_display_doc, _keep_timestamp_doc, _default_tick_doc])
455
+ def first_tick(*args, **kwargs):
456
+ """
457
+ Select the first **n** ticks
458
+
459
+ See also
460
+ --------
461
+ **FIRST_TICK** OneTick event processor
462
+
463
+ Examples
464
+ --------
465
+ >>> data = otp.Ticks(P=[1, 2, 3, 4], S=[10, 20, 30, 40])
466
+ >>> agg = otp.agg.first_tick()
467
+ >>> data = agg.apply(data)
468
+ >>> otp.run(data)
469
+ Time P S
470
+ 0 2003-12-01 1 10
471
+ """
472
+ return FirstTick(*args, **kwargs)
473
+
474
+
475
+ @docstring(parameters=[_n_doc, _running_doc, _bucket_interval_doc, _bucket_time_doc, _bucket_units_doc,
476
+ _bucket_end_condition_doc, _end_condition_per_group_doc, _boundary_tick_bucket_doc,
477
+ _group_by_doc, _groups_to_display_doc, _keep_timestamp_doc, _time_series_type_doc])
478
+ def last_tick(*args, **kwargs):
479
+ """
480
+ Select the last ``n`` ticks
481
+
482
+ See also
483
+ --------
484
+ **LAST_TICK** OneTick event processor
485
+
486
+ Examples
487
+ --------
488
+ >>> data = otp.Ticks(P=[1, 2, 3, 4], S=[10, 20, 30, 40], offset=[0, 1000, 1500, 3000])
489
+ >>> agg = otp.agg.last_tick()
490
+ >>> data = agg.apply(data)
491
+ >>> otp.run(data)
492
+ Time P S
493
+ 0 2003-12-01 00:00:03 4 40
494
+ """
495
+ return LastTick(*args, **kwargs)
496
+
497
+
498
+ @docstring(parameters=[_running_doc, _bucket_interval_doc, _bucket_time_doc, _bucket_units_doc,
499
+ _bucket_end_condition_doc, _boundary_tick_bucket_doc, _selection_doc])
500
+ def distinct(*args, **kwargs):
501
+ """
502
+ Outputs all distinct values for a specified set of key fields.
503
+
504
+ Parameters
505
+ ----------
506
+ keys: str or list
507
+ Specifies a list of tick attributes for which unique values are found. The ticks in the input time series
508
+ must contain those attributes.
509
+ key_attrs_only: bool
510
+ If set to true, output ticks will contain only key fields. Otherwise, output ticks will contain all fields
511
+ of an input tick in which a given distinct combination of key values was first encountered.
512
+
513
+ See also
514
+ --------
515
+ **DISTINCT** OneTick event processor
516
+
517
+ Examples
518
+ --------
519
+ >>> data = otp.Ticks(dict(x=[1, 3, 1, 5, 3]))
520
+ >>> d = otp.agg.distinct('x')
521
+ >>> data = d.apply(data)
522
+ >>> otp.run(data)
523
+ Time x
524
+ 0 2003-12-04 1
525
+ 1 2003-12-04 3
526
+ 2 2003-12-04 5
527
+ """
528
+ return Distinct(*args, **kwargs)
529
+
530
+
531
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
532
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
533
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc])
534
+ def sum(*args, **kwargs):
535
+ r"""
536
+ Implement sum aggregation
537
+
538
+ See also
539
+ --------
540
+ **SUM** OneTick event processor
541
+
542
+ Examples
543
+ --------
544
+
545
+ >>> data = otp.Ticks(X=[1, 2, 3, 4])
546
+ >>> data = data.agg({'RESULT': otp.agg.sum('X')}) # OTdirective: snippet-name: Aggregations.sum;
547
+ >>> otp.run(data)
548
+ Time RESULT
549
+ 0 2003-12-04 10
550
+
551
+ Note that **seconds** bucket unit doesn't take into account daylight-saving time of the timezone,
552
+ so you may not get expected results when using, for example, 24 * 60 * 60 seconds as bucket interval.
553
+
554
+ >>> data = otp.DataSource('CME', symbols=r'NQ\H23', tick_type='TRD') # doctest: +SKIP
555
+ >>> data = data.agg({'VOLUME': otp.agg.sum('SIZE')}, # doctest: +SKIP
556
+ ... bucket_interval=24*60*60, bucket_units='seconds', bucket_time='start')
557
+ >>> otp.run(data, start=otp.dt(2023, 3, 11), end=otp.dt(2023, 3, 15), timezone='EST5EDT') # doctest: +SKIP
558
+ Time VOLUME
559
+ 0 2023-03-11 00:00:00 0
560
+ 1 2023-03-12 00:00:00 66190
561
+ 2 2023-03-13 01:00:00 631750
562
+ 3 2023-03-14 01:00:00 345952
563
+
564
+ In such case use **days** bucket unit instead:
565
+
566
+ >>> data = otp.DataSource('CME', symbols=r'NQ\H23', tick_type='TRD') # doctest: +SKIP
567
+ >>> data = data.agg({'VOLUME': otp.agg.sum('SIZE')}, # doctest: +SKIP
568
+ ... bucket_interval=1, bucket_units='days', bucket_time='start')
569
+ >>> otp.run(data, start=otp.dt(2023, 3, 11), end=otp.dt(2023, 3, 15), timezone='EST5EDT') # doctest: +SKIP
570
+ Time VOLUME
571
+ 0 2023-03-11 0
572
+ 1 2023-03-12 62940
573
+ 2 2023-03-13 634172
574
+ 3 2023-03-14 346780
575
+ """
576
+ return Sum(*args, **kwargs)
577
+
578
+
579
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
580
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
581
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc])
582
+ def average(*args, **kwargs):
583
+ """
584
+ Implement average aggregation
585
+
586
+ See also
587
+ --------
588
+ **AVERAGE** OneTick event processor
589
+
590
+ Examples
591
+ --------
592
+
593
+ >>> data = otp.Ticks(X=[1, 2, 3, 4])
594
+ >>> data = data.agg({'RESULT': otp.agg.average('X')}) # OTdirective: snippet-name: Aggregations.average/mean;
595
+ >>> otp.run(data)
596
+ Time RESULT
597
+ 0 2003-12-04 2.5
598
+ """
599
+ return Average(*args, **kwargs)
600
+
601
+
602
+ def mean(*args, **kwargs):
603
+ """
604
+ Implement average aggregation.
605
+
606
+ See also
607
+ --------
608
+ | :func:`average`
609
+ | **AVERAGE** OneTick event processor
610
+
611
+ Examples
612
+ --------
613
+
614
+ >>> data = otp.Ticks(X=[1, 2, 3, 4])
615
+ >>> data = data.agg({'RESULT': otp.agg.mean('X')})
616
+ >>> otp.run(data)
617
+ Time RESULT
618
+ 0 2003-12-04 2.5
619
+ """
620
+ return average(*args, **kwargs)
621
+
622
+
623
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
624
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
625
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc, _biased_doc])
626
+ def stddev(*args, **kwargs):
627
+ """
628
+ Implement standard deviation aggregation
629
+
630
+ See also
631
+ --------
632
+ **STDDEV** OneTick event processor
633
+
634
+ Examples
635
+ --------
636
+
637
+ >>> data = otp.Ticks(X=[1, 2, 3, 4])
638
+ >>> data = data.agg({'RESULT': otp.agg.stddev('X')}) # OTdirective: snippet-name: Aggregations.stddev;
639
+ >>> otp.run(data)
640
+ Time RESULT
641
+ 0 2003-12-04 1.118034
642
+ """
643
+ return StdDev(*args, **kwargs)
644
+
645
+
646
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
647
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
648
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc, _time_series_type_w_doc])
649
+ def tw_average(*args, **kwargs):
650
+ """
651
+ Returns time weighted average of input field
652
+
653
+ See also
654
+ --------
655
+ **TW_AVERAGE** OneTick event processor
656
+
657
+ Examples
658
+ --------
659
+ >>> data = otp.Ticks(X=[1, 2, 3, 4], offset=[0, 1000, 1500, 3000])
660
+ >>> otp.run(data, start=otp.dt(2023, 4, 25), end=otp.dt(2023, 4, 25)+otp.Second(4))
661
+ Time X
662
+ 0 2023-04-25 00:00:00.000 1
663
+ 1 2023-04-25 00:00:01.000 2
664
+ 2 2023-04-25 00:00:01.500 3
665
+ 3 2023-04-25 00:00:03.000 4
666
+
667
+ >>> # OTdirective: snippet-name: Aggregations.time weighted average;
668
+ >>> data = otp.Ticks(X=[1, 2, 3, 4], offset=[0, 1000, 1500, 3000])
669
+ >>> data = data.agg({'RESULT': otp.agg.tw_average('X')})
670
+ >>> otp.run(data, start=otp.dt(2023, 4, 25), end=otp.dt(2023, 4, 25)+otp.Second(4))
671
+ Time RESULT
672
+ 0 2023-04-25 00:00:04 2.625
673
+ """
674
+ return TimeWeightedAvg(*args, **kwargs)
675
+
676
+
677
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
678
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
679
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc])
680
+ def median(*args, **kwargs):
681
+ """
682
+ Implement median aggregation
683
+
684
+ See also
685
+ --------
686
+ **MEDIAN** OneTick event processor
687
+
688
+ Examples
689
+ --------
690
+
691
+ >>> data = otp.Ticks(X=[1, 2, 3, 3, 4])
692
+ >>> data = data.agg({'RESULT': otp.agg.median('X')}) # OTdirective: snippet-name: Aggregations.median;
693
+ >>> otp.run(data)
694
+ Time RESULT
695
+ 0 2003-12-04 3.0
696
+ """
697
+ return Median(*args, **kwargs)
698
+
699
+
700
+ @docstring(parameters=OB_SNAPSHOT_DOC_PARAMS)
701
+ def ob_snapshot(*args, **kwargs):
702
+ """
703
+ Returns the order book state at the end of each bucket interval:
704
+ the price, the size, the side, and the time of the last update for a specified number of order book levels.
705
+
706
+ See also
707
+ --------
708
+ | :func:`onetick.py.ObSnapshot`
709
+ | **OB_SNAPSHOT** OneTick event processor
710
+
711
+
712
+ Examples
713
+ --------
714
+ >>> data = otp.DataSource(db='SOME_DB', tick_type='PRL', symbols='AA') # doctest: +SKIP
715
+ >>> data = otp.agg.ob_snapshot(max_levels=1).apply(data) # doctest: +SKIP
716
+ >>> otp.run(data) # doctest: +SKIP
717
+ Time PRICE UPDATE_TIME SIZE LEVEL BUY_SELL_FLAG
718
+ 0 2003-12-04 2.0 2003-12-01 00:00:00.003 6 1 1
719
+ 1 2003-12-04 5.0 2003-12-01 00:00:00.004 7 1 0
720
+ """
721
+ return ObSnapshot(*args, **kwargs)
722
+
723
+
724
+ @docstring(parameters=OB_SNAPSHOT_WIDE_DOC_PARAMS)
725
+ def ob_snapshot_wide(*args, **kwargs):
726
+ """
727
+ Returns a side by side order book state at the end of each interval:
728
+ the price, the size, and the time of the last update for a specified number of order book levels.
729
+
730
+ See also
731
+ --------
732
+ | :func:`onetick.py.ObSnapshotWide`
733
+ | **OB_SNAPSHOT_WIDE** OneTick event processor
734
+
735
+ Examples
736
+ --------
737
+ >>> data = otp.DataSource(db='SOME_DB', tick_type='PRL', symbols='AA') # doctest: +SKIP
738
+ >>> data = otp.agg.ob_snapshot_wide(max_levels=1).apply(data) # doctest: +SKIP
739
+ >>> otp.run(data) # doctest: +SKIP
740
+ Time BID_PRICE BID_UPDATE_TIME BID_SIZE ASK_PRICE ASK_UPDATE_TIME ASK_SIZE LEVEL
741
+ 0 2003-12-03 5.0 2003-12-01 00:00:00.004 7 2.0 2003-12-01 00:00:00.003 6 1
742
+ """
743
+ return ObSnapshotWide(*args, **kwargs)
744
+
745
+
746
+ @docstring(parameters=OB_SNAPSHOT_FLAT_DOC_PARAMS)
747
+ def ob_snapshot_flat(*args, **kwargs):
748
+ """
749
+ Returns the snapshot for a specified number of book levels as a single tick
750
+ with multiple field groups corresponding to book levels.
751
+
752
+ See also
753
+ --------
754
+ | :func:`onetick.py.ObSnapshotFlat`
755
+ | **OB_SNAPSHOT_FLAT** OneTick event processor
756
+
757
+ Examples
758
+ --------
759
+ >>> data = otp.DataSource(db='SOME_DB', tick_type='PRL', symbols='AA') # doctest: +SKIP
760
+ >>> data = otp.agg.ob_snapshot_flat(max_levels=1).apply(data) # doctest: +SKIP
761
+ >>> otp.run(data) # doctest: +SKIP
762
+ Time BID_PRICE1 BID_UPDATE_TIME1 BID_SIZE1 ASK_PRICE1 ASK_UPDATE_TIME1 ASK_SIZE1
763
+ 0 2003-12-03 5.0 2003-12-01 00:00:00.004 7 2.0 2003-12-01 00:00:00.003 6
764
+ """
765
+ return ObSnapshotFlat(*args, **kwargs)
766
+
767
+
768
+ @docstring(parameters=OB_SUMMARY_DOC_PARAMS)
769
+ def ob_summary(*args, **kwargs):
770
+ """
771
+ Computes summary statistics, such as:
772
+ VWAP, best and worst price, total size, and number of levels, for one or both sides of an order book.
773
+
774
+ See also
775
+ --------
776
+ | :func:`onetick.py.ObSummary`
777
+ | **OB_SUMMARY** OneTick event processor
778
+
779
+
780
+ Examples
781
+ --------
782
+ >>> data = otp.DataSource(db='SOME_DB', tick_type='PRL', symbols='AA') # doctest: +SKIP
783
+ >>> data = otp.agg.ob_summary(max_levels=1).apply(data) # doctest: +SKIP
784
+ >>> otp.run(data) # doctest: +SKIP
785
+ Time BID_PRICE BID_SIZE BID_VWAP BEST_BID_PRICE WORST_BID_SIZE NUM_BID_LEVELS ASK_SIZE\
786
+ ASK_VWAP BEST_ASK_PRICE WORST_ASK_PRICE NUM_ASK_LEVELS
787
+ 0 2003-12-04 NaN 7 5.0 5.0 NaN 1 6\
788
+ 2.0 2.0 2.0 1
789
+ """
790
+ return ObSummary(*args, **kwargs)
791
+
792
+
793
+ @docstring(parameters=OB_SIZE_DOC_PARAMS)
794
+ def ob_size(*args, **kwargs):
795
+ """
796
+ Returns the total size for a specified number of order book levels at the end of each bucket interval.
797
+
798
+ See also
799
+ --------
800
+ | :func:`onetick.py.ObSize`
801
+ | **OB_SIZE** OneTick event processor
802
+
803
+ Examples
804
+ --------
805
+
806
+ Basic example
807
+
808
+ >>> data = otp.DataSource(db='SOME_DB', tick_type='PRL', symbols='AA') # doctest: +SKIP
809
+ >>> data = otp.agg.ob_size(bucket_interval=otp.Second(300), max_levels=10).apply(data) # doctest: +SKIP
810
+ >>> otp.run(data) # doctest: +SKIP
811
+ Time ASK_VALUE BID_VALUE
812
+ 0 2003-12-01 00:05:00.000 194800 47200
813
+ 1 2003-12-01 00:10:00.000 194800 47200
814
+ 2 2003-12-01 00:15:00.000 313400 7700
815
+ ...
816
+
817
+ Selecting side via ``side`` parameter
818
+
819
+ >>> data = otp.DataSource(db='SOME_DB', tick_type='PRL', symbols='AA') # doctest: +SKIP
820
+ >>> data = otp.agg.ob_size(bucket_interval=otp.Second(300), max_levels=10, size='ASK').apply(data) # doctest: +SKIP
821
+ >>> otp.run(data) # doctest: +SKIP
822
+ Time VALUE
823
+ 0 2003-12-01 00:05:00.000 194800
824
+ 1 2003-12-01 00:10:00.000 194800
825
+ 2 2003-12-01 00:15:00.000 313400
826
+ ...
827
+ """
828
+ return ObSize(*args, **kwargs)
829
+
830
+
831
+ @docstring(parameters=OB_VWAP_DOC_PARAMS)
832
+ def ob_vwap(*args, **kwargs):
833
+ """
834
+ Returns the size-weighted price computed over a specified number of order book levels at the end of each interval.
835
+
836
+ See also
837
+ --------
838
+ | :func:`onetick.py.ObVwap`
839
+ | **OB_VWAP** OneTick event processor
840
+
841
+ Examples
842
+ --------
843
+
844
+ Basic example
845
+
846
+ >>> data = otp.DataSource(db='SOME_DB', tick_type='PRL', symbols='AA') # doctest: +SKIP
847
+ >>> data = otp.agg.ob_vwap(bucket_interval=otp.Second(300)).apply(data) # doctest: +SKIP
848
+ >>> otp.run(data) # doctest: +SKIP
849
+ Time ASK_VALUE BID_VALUE
850
+ 0 2003-12-01 00:05:00.000 23.93496 23.80502
851
+ 1 2003-12-01 00:10:00.000 23.93496 23.80502
852
+ 2 2003-12-01 00:15:00.000 24.35387 24.35387
853
+ ...
854
+
855
+ Selecting side via ``side`` parameter
856
+
857
+ >>> data = otp.DataSource(db='SOME_DB', tick_type='PRL', symbols='AA') # doctest: +SKIP
858
+ >>> data = otp.agg.ob_vwap(bucket_interval=otp.Second(300), size='BID').apply(data) # doctest: +SKIP
859
+ >>> otp.run(data) # doctest: +SKIP
860
+ Time VALUE
861
+ 0 2003-12-01 00:05:00.000 23.80502
862
+ 1 2003-12-01 00:10:00.000 23.80502
863
+ 2 2003-12-01 00:15:00.000 24.35387
864
+ ...
865
+ """
866
+ return ObVwap(*args, **kwargs)
867
+
868
+
869
+ @docstring(parameters=OB_NUM_LEVELS_DOC_PARAMS)
870
+ def ob_num_levels(*args, **kwargs):
871
+ """
872
+ Returns the number of levels in the order book at the end of each bucket.
873
+
874
+ Note
875
+ ----
876
+ This EP supports only seconds as ``bucket_interval``.
877
+
878
+ See also
879
+ --------
880
+ | :func:`onetick.py.ObNumLevels`
881
+ | **OB_NUM_LEVELS** OneTick event processor
882
+
883
+ Examples
884
+ --------
885
+
886
+ Basic example
887
+
888
+ >>> data = otp.DataSource(db='SOME_DB', tick_type='PRL', symbols='AA') # doctest: +SKIP
889
+ >>> data = otp.agg.ob_num_levels(bucket_interval=otp.Second(300)).apply(data) # doctest: +SKIP
890
+ >>> otp.run(data) # doctest: +SKIP
891
+ Time ASK_VALUE BID_VALUE
892
+ 0 2003-12-01 00:05:00.000 243 74
893
+ 1 2003-12-01 00:10:00.000 243 74
894
+ 2 2003-12-01 00:15:00.000 208 45
895
+ ...
896
+ """
897
+ return ObNumLevels(*args, **kwargs)
898
+
899
+
900
+ @docstring(parameters=[
901
+ _query_fun_doc,
902
+ _bucket_delimiter_doc,
903
+ _bucket_interval_doc,
904
+ _bucket_units_doc,
905
+ _bucket_time_doc,
906
+ _bucket_end_condition_doc,
907
+ _running_doc,
908
+ _group_by_doc,
909
+ _groups_to_display_doc,
910
+ _end_condition_per_group_doc,
911
+ _boundary_tick_bucket_doc,
912
+ ])
913
+ def generic(*args, **kwargs):
914
+ """
915
+ Generic aggregation.
916
+ Aggregation logic is provided in ``query_fun`` parameter
917
+ and this logic is applied for ticks in each bucket.
918
+ Currently, this aggregation can be used only with ``.apply()`` method.
919
+
920
+ Note, that ``query_fun`` should return a :py:class:`~onetick.py.Source` object,
921
+ assuming that resulted query have only one tick per bucket.
922
+
923
+ Also, ``query_fun`` could have additional parameters, which will be passed to ``query_fun``
924
+ during aggregation. Those parameters should be specified in ``.apply()`` as keyword arguments,
925
+ ex: ``.apply(src, additional_param=1)``.
926
+
927
+ Generic aggregations could be also used in :py:meth:`onetick.py.Source.agg` method.
928
+ Dict key set for an aggregation in ``aggs`` parameter will be used as prefix
929
+ for each output column of this aggregation.
930
+ Also, all tick fields not contained in the Python-level schema in a passed to generic aggregation
931
+ :class:`Source` object will be removed.
932
+
933
+ Note
934
+ ----
935
+ Some functions may be not supported in ``query_fun``.
936
+ For example, :py:func:`~onetick.py.join` and :py:meth:`~onetick.py.Source.rename`.
937
+
938
+ See also
939
+ --------
940
+ **GENERIC_AGGREGATION** OneTick event processor
941
+
942
+ Examples
943
+ --------
944
+
945
+ The simplest case, just copying some other aggregation logic:
946
+
947
+ >>> data = otp.Ticks({'A': [1, 2, 3]})
948
+ >>> def agg_fun(source):
949
+ ... return source.agg({'X': otp.agg.count()})
950
+ >>> data = otp.agg.generic(agg_fun).apply(data)
951
+ >>> otp.run(data)
952
+ Time X
953
+ 0 2003-12-04 3
954
+
955
+ Passing parameters to aggregation function:
956
+
957
+ >>> data = otp.Ticks({'A': [1, 2, 1]})
958
+ >>> def count_values(source, value):
959
+ ... values, _ = source[source['A'] == value]
960
+ ... return values.agg({'count': otp.agg.count()})
961
+ >>> data = otp.agg.generic(count_values).apply(data, value=1)
962
+ >>> otp.run(data)
963
+ Time count
964
+ 0 2003-12-04 2
965
+
966
+ Getting first 3 ticks from 5 milliseconds buckets:
967
+
968
+ >>> data = otp.Ticks({'A': list(range(10))})
969
+ >>> def agg_fun(source, n):
970
+ ... return source.first(n)
971
+ >>> data = otp.agg.generic(agg_fun, bucket_interval=0.005).apply(data, n=3)
972
+ >>> otp.run(data, start=otp.config.default_start_time, end=otp.config.default_start_time + otp.Milli(10))
973
+ Time A
974
+ 0 2003-12-01 00:00:00.005 0
975
+ 1 2003-12-01 00:00:00.005 1
976
+ 2 2003-12-01 00:00:00.005 2
977
+ 3 2003-12-01 00:00:00.010 5
978
+ 4 2003-12-01 00:00:00.010 6
979
+ 5 2003-12-01 00:00:00.010 7
980
+
981
+ Using generic aggregation inside :py:meth:`onetick.py.Source.agg` method:
982
+
983
+ >>> def agg_fun(source):
984
+ ... return source.agg({'SUM': otp.agg.sum('X'), 'AVG': otp.agg.average('X')})
985
+ ...
986
+ >>> data = otp.Ticks(X=[1, 2, 3, 4, 5])
987
+ >>> data = data.agg({'X': otp.agg.generic(agg_fun)})
988
+ >>> otp.run(data)
989
+ Time X.SUM X.AVG
990
+ 0 2003-12-04 15 3.0
991
+ """
992
+
993
+ return Generic(*args, **kwargs)
994
+
995
+
996
+ @docstring(parameters=[_running_doc, _bucket_interval_doc, _bucket_time_doc, _bucket_units_doc,
997
+ _bucket_end_condition_doc, _boundary_tick_bucket_doc])
998
+ def option_price(*args, **kwargs):
999
+ """
1000
+ This aggregation requires several parameters to compute the option price.
1001
+ Those are, OPTION_TYPE, STRIKE_PRICE, EXPIRATION_DATE or DAYS_TILL_EXPIRATION, VOLATILITY, and INTEREST_RATE.
1002
+ Each parameter can be specified, either via a symbol parameter with the same name or via a tick field,
1003
+ by specifying the name of that field as an EP parameter, as follows.
1004
+ Besides, VOLATILITY and INTEREST_RATE can also be specified as parameters. If they are also specified as fields,
1005
+ the parameters value are ignored.
1006
+ In either case, the OPTION_TYPE value must be set to either CALL or PUT (case insensitive).
1007
+ EXPIRATION_DATE is in YYYYMMDD format, a string in case of a symbol parameter and
1008
+ an integer in case of a tick attribute.
1009
+ Additionally, NUMBER_OF_STEPS should be specified in case of Cox-Ross-Rubinstein method.
1010
+
1011
+ Note
1012
+ ----
1013
+ This aggregation is used with ``.apply()``, but latest OneTick builds support also the ``.agg()`` method.
1014
+
1015
+ Parameters
1016
+ ----------
1017
+ volatility: float
1018
+ The historical volatility of the asset’s returns.
1019
+ interest_rate: float
1020
+ The risk-free interest rate.
1021
+ compute_model: str
1022
+ Allowed values are `BS` and `CRR`.
1023
+ Choose between Black–Scholes (`BS`) and Cox-Ross-Rubinstein (`CRR`) models for computing call/put option price.
1024
+ Default: `BS`
1025
+ number_of_steps: int
1026
+ Specifies the number of time steps between the valuation and expiration dates.
1027
+ This is a mandatory parameter for `CRR` model.
1028
+ compute_delta: bool
1029
+ Specifies whether Delta is to be computed or not. This parameter is used only in case of `BS` model.
1030
+ Default: False
1031
+ compute_gamma: bool
1032
+ Specifies whether Gamma is to be computed or not. This parameter is used only in case of `BS` model.
1033
+ Default: False
1034
+ compute_theta: bool
1035
+ Specifies whether Theta is to be computed or not. This parameter is used only in case of `BS` model.
1036
+ Default: False
1037
+ compute_vega: bool
1038
+ Specifies whether Vega is to be computed or not. This parameter is used only in case of `BS` model.
1039
+ Default: False
1040
+ compute_rho: bool
1041
+ Specifies whether Rho is to be computed or not. This parameter is used only in case of `BS` model.
1042
+ Default: False
1043
+ volatility_field_name: str
1044
+ Specifies name of the field, which carries the historical volatility of the asset’s returns.
1045
+ Default: empty
1046
+ interest_rate_field_name: str
1047
+ Specifies name of the field, which carries the risk-free interest rate.
1048
+ Default: empty
1049
+ option_type_field_name: str
1050
+ Specifies name of the field, which carries the option type (either CALL or PUT).
1051
+ Default: empty
1052
+ strike_price_field_name: str
1053
+ Specifies name of the field, which carries the strike price of the option.
1054
+ Default: empty
1055
+ days_in_year: int
1056
+ Specifies number of days in a year (say, 365 or 252 (business days, etc.).
1057
+ Used with DAYS_TILL_EXPIRATION parameter to compute the fractional years till expiration.
1058
+ Default: 365
1059
+ days_till_expiration_field_name: str
1060
+ Specifies name of the field, which carries number of days till expiration of the option.
1061
+ Default: empty
1062
+ expiration_date_field_name: str
1063
+ Specifies name of the field, which carries the expiration date of the option, in YYYYMMDD format.
1064
+ Default: empty
1065
+
1066
+ See also
1067
+ --------
1068
+ **OPTION_PRICE** OneTick event processor
1069
+
1070
+ Examples
1071
+ ---------
1072
+ Black–Scholes with parameters passed through symbol params and calculated delta:
1073
+
1074
+ >>> symbol = otp.Tick(SYMBOL_NAME='SYMB')
1075
+ >>> symbol['OPTION_TYPE'] = 'CALL'
1076
+ >>> symbol['STRIKE_PRICE'] = 100.0
1077
+ >>> symbol['DAYS_TILL_EXPIRATION'] = 30
1078
+ >>> symbol['VOLATILITY'] = 0.25
1079
+ >>> symbol['INTEREST_RATE'] = 0.05
1080
+ >>> data = otp.Ticks(PRICE=[100.7, 101.1, 99.5], symbol=symbol)
1081
+ >>> data = otp.agg.option_price(compute_delta=True).apply(data)
1082
+ >>> otp.run(data)['SYMB']
1083
+ Time VALUE DELTA
1084
+ 0 2003-12-04 2.800999 0.50927
1085
+ >>> data.schema
1086
+ {'VALUE': <class 'float'>, 'DELTA': <class 'float'>}
1087
+
1088
+ Cox-Ross-Rubinstein with parameters passed through fields:
1089
+
1090
+ >>> data = otp.Ticks(
1091
+ ... PRICE=[100.7, 101.1, 99.5],
1092
+ ... OPTION_TYPE=['CALL']*3,
1093
+ ... STRIKE_PRICE=[100.0]*3,
1094
+ ... DAYS_TILL_EXPIRATION=[30]*3,
1095
+ ... VOLATILITY=[0.25]*3,
1096
+ ... INTEREST_RATE=[0.05]*3,
1097
+ ... )
1098
+ >>> data = otp.agg.option_price(
1099
+ ... compute_model='CRR',
1100
+ ... number_of_steps=5,
1101
+ ... option_type_field_name='OPTION_TYPE',
1102
+ ... strike_price_field_name='STRIKE_PRICE',
1103
+ ... days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1104
+ ... volatility_field_name='VOLATILITY',
1105
+ ... interest_rate_field_name='INTEREST_RATE',
1106
+ ... ).apply(data)
1107
+ >>> otp.run(data)
1108
+ Time VALUE
1109
+ 0 2003-12-04 2.937537
1110
+
1111
+ Black–Scholes with some parameters passed through parameters:
1112
+
1113
+ >>> data = otp.Ticks(
1114
+ ... PRICE=[100.7, 101.1, 99.5],
1115
+ ... OPTION_TYPE=['CALL']*3,
1116
+ ... STRIKE_PRICE=[100.0]*3,
1117
+ ... DAYS_TILL_EXPIRATION=[30]*3,
1118
+ ... )
1119
+ >>> data = otp.agg.option_price(
1120
+ ... option_type_field_name='OPTION_TYPE',
1121
+ ... strike_price_field_name='STRIKE_PRICE',
1122
+ ... days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1123
+ ... volatility=0.25,
1124
+ ... interest_rate=0.05,
1125
+ ... ).apply(data)
1126
+ >>> otp.run(data)
1127
+ Time VALUE
1128
+ 0 2003-12-04 2.800999
1129
+
1130
+ To compute values for each tick in a series, set ``bucket_interval=1`` and ``bucket_units='ticks'``
1131
+
1132
+ >>> data = otp.Ticks(
1133
+ ... PRICE=[110.0, 101.0, 112.0],
1134
+ ... OPTION_TYPE=["CALL"]*3,
1135
+ ... STRIKE_PRICE=[110.0]*3,
1136
+ ... DAYS_TILL_EXPIRATION=[30]*3,
1137
+ ... VOLATILITY=[0.2]*3,
1138
+ ... INTEREST_RATE=[0.05]*3
1139
+ ... )
1140
+ >>> data = otp.agg.option_price(
1141
+ ... option_type_field_name='OPTION_TYPE',
1142
+ ... strike_price_field_name='STRIKE_PRICE',
1143
+ ... days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1144
+ ... volatility_field_name='VOLATILITY',
1145
+ ... interest_rate_field_name='INTEREST_RATE',
1146
+ ... bucket_interval=1,
1147
+ ... bucket_units='ticks',
1148
+ ... ).apply(data)
1149
+ >>> otp.run(data)
1150
+ Time VALUE
1151
+ 0 2003-12-01 00:00:00.000 2.742714
1152
+ 1 2003-12-01 00:00:00.001 0.212927
1153
+ 2 2003-12-01 00:00:00.002 3.945447
1154
+
1155
+ Usage with the ``.agg()`` method (on the latest OneTick builds).
1156
+
1157
+ .. testcode::
1158
+ :skipif: not otp.compatibility.is_supported_agg_option_price()
1159
+
1160
+ data = otp.Ticks(
1161
+ PRICE=[100.7, 101.1, 99.5],
1162
+ OPTION_TYPE=['CALL']*3,
1163
+ STRIKE_PRICE=[100.0]*3,
1164
+ DAYS_TILL_EXPIRATION=[30]*3,
1165
+ )
1166
+ data = data.agg({
1167
+ 'RESULT': otp.agg.option_price(
1168
+ option_type_field_name='OPTION_TYPE',
1169
+ strike_price_field_name='STRIKE_PRICE',
1170
+ days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1171
+ volatility=0.25,
1172
+ interest_rate=0.05,
1173
+ )
1174
+ })
1175
+ df = otp.run(data)
1176
+ print(df)
1177
+
1178
+ .. testoutput::
1179
+
1180
+ Time RESULT
1181
+ 0 2003-12-04 2.800999
1182
+
1183
+ The following examples show results for different cases of option price calculation.
1184
+ Results are compared with two online calculators:
1185
+ `Drexel University <https://www.math.drexel.edu/~pg/fin/VanillaCalculator.html>`_ (DU) and
1186
+ `Wolfram Alpha <https://www.wolframalpha.com/input?i=black+scholes>`_ (WA).
1187
+
1188
+ Call option, strike price 110.0, underlying price 120.0, volatility 20.0%, interest 5.0%, expiring in 15 days.
1189
+
1190
+ >>> data = {
1191
+ ... "PRICE": 120.,
1192
+ ... "OPTION_TYPE": "call",
1193
+ ... "STRIKE_PRICE": 110.,
1194
+ ... "DAYS_TILL_EXPIRATION": 15,
1195
+ ... "VOLATILITY": 0.2,
1196
+ ... "INTEREST_RATE": 0.05,
1197
+ ... }
1198
+ >>> data = otp.Tick(**data)
1199
+ >>> data = otp.agg.option_price(
1200
+ ... option_type_field_name='OPTION_TYPE',
1201
+ ... strike_price_field_name='STRIKE_PRICE',
1202
+ ... days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1203
+ ... volatility_field_name='VOLATILITY',
1204
+ ... interest_rate_field_name='INTEREST_RATE',
1205
+ ... compute_delta=True,
1206
+ ... compute_gamma=True,
1207
+ ... compute_theta=True,
1208
+ ... compute_vega=True,
1209
+ ... compute_rho=True
1210
+ ... ).apply(data)
1211
+ >>> res = otp.run(data).drop("Time", axis=1)
1212
+ >>> for key, val in res.to_dict(orient='list').items():
1213
+ ... print(f"{key}={val[0]}")
1214
+ VALUE=10.248742578738629
1215
+ DELTA=0.9866897658932824
1216
+ GAMMA=0.007022082258701294
1217
+ THETA=-7.430061156928735
1218
+ VEGA=0.8311067221257422
1219
+ RHO=4.444686136785831
1220
+
1221
+ .. csv-table:: Benchmark comparison
1222
+ :widths: 10, 25, 25, 10
1223
+ :header: Field, OneTick, DU benchmark, WA benchmark
1224
+
1225
+ VALUE, 10.248742578738629, 10.248742577611323400, 10.249
1226
+ DELTA, 0.9866897658932824, 0.986689766547165200, 0.987
1227
+ GAMMA, 0.007022082258701294, 0.007022082258701300, 0.007
1228
+ THETA, -7.430061156928735, -7.430061160908399600, -7.430
1229
+ VEGA, 0.8311067221257422, 0.831106722125743000, 0.831
1230
+ RHO, 4.444686136785831, 4.444686140056785400, 4.445
1231
+
1232
+ Put option, strike price 110.0, underlying price 120.0, volatility 20.0%, interest 5.0%, expiring in 15 days.
1233
+
1234
+ .. testcode::
1235
+ :skipif: not otp.compatibility.is_option_price_theta_value_changed()
1236
+
1237
+ data = {
1238
+ "PRICE": 120.,
1239
+ "OPTION_TYPE": "put",
1240
+ "STRIKE_PRICE": 110.,
1241
+ "DAYS_TILL_EXPIRATION": 15,
1242
+ "VOLATILITY": 0.2,
1243
+ "INTEREST_RATE": 0.05,
1244
+ }
1245
+ data = otp.Tick(**data)
1246
+ data = otp.agg.option_price(
1247
+ option_type_field_name='OPTION_TYPE',
1248
+ strike_price_field_name='STRIKE_PRICE',
1249
+ days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1250
+ volatility_field_name='VOLATILITY',
1251
+ interest_rate_field_name='INTEREST_RATE',
1252
+ compute_delta=True,
1253
+ compute_gamma=True,
1254
+ compute_theta=True,
1255
+ compute_vega=True,
1256
+ compute_rho=True
1257
+ ).apply(data)
1258
+ res = otp.run(data).drop("Time", axis=1)
1259
+ for key, val in res.to_dict(orient='list').items():
1260
+ print(f"{key}={val[0]:.14f}")
1261
+
1262
+ .. testoutput::
1263
+
1264
+ VALUE=0.02294724243400
1265
+ DELTA=-0.01331023410672
1266
+ GAMMA=0.00702208225870
1267
+ THETA=-1.94135092374397
1268
+ VEGA=0.83110672212574
1269
+ RHO=-0.06658254802357
1270
+
1271
+ .. csv-table:: Benchmark comparison
1272
+ :widths: 10, 25, 25, 10
1273
+ :header: Field, OneTick, DU benchmark, WA benchmark
1274
+
1275
+ VALUE, 0.022947242433995818, 0.022947241306682900, 0.023
1276
+ DELTA, -0.013310234106717611, -0.013310233452834800, -0.013
1277
+ GAMMA, 0.007022082258701294, 0.007022082258701300, 0.007
1278
+ THETA, -1.94135092374397, -1.941350927723632000, -1.941
1279
+ VEGA, 0.8311067221257422, 0.831106722125743000, 0.831
1280
+ RHO, -0.06658254802356636, -0.066582544752611000, -0.067
1281
+
1282
+
1283
+ Put option, strike price 90.0, underlying price 80.0, volatility 30.0%, interest 8.0%, expiring in 20 days.
1284
+
1285
+ .. testcode::
1286
+ :skipif: not otp.compatibility.is_option_price_theta_value_changed()
1287
+
1288
+ data = {
1289
+ "PRICE": 80.,
1290
+ "OPTION_TYPE": "put",
1291
+ "STRIKE_PRICE": 90.,
1292
+ "DAYS_TILL_EXPIRATION": 20,
1293
+ "VOLATILITY": 0.3,
1294
+ "INTEREST_RATE": 0.08,
1295
+ }
1296
+ data = otp.Tick(**data)
1297
+ data = otp.agg.option_price(
1298
+ option_type_field_name='OPTION_TYPE',
1299
+ strike_price_field_name='STRIKE_PRICE',
1300
+ days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1301
+ volatility_field_name='VOLATILITY',
1302
+ interest_rate_field_name='INTEREST_RATE',
1303
+ compute_delta=True,
1304
+ compute_gamma=True,
1305
+ compute_theta=True,
1306
+ compute_vega=True,
1307
+ compute_rho=True
1308
+ ).apply(data)
1309
+ res = otp.run(data).drop("Time", axis=1)
1310
+ for key, val in res.to_dict(orient='list').items():
1311
+ print(f"{key}={val[0]}")
1312
+
1313
+ .. testoutput::
1314
+
1315
+ VALUE=9.739720671039635
1316
+ DELTA=-0.9429118423759162
1317
+ GAMMA=0.020391626464263516
1318
+ THETA=0.9410250231811439
1319
+ VEGA=2.1453108389800515
1320
+ RHO=-4.666995510197969
1321
+
1322
+ .. csv-table:: Benchmark comparison
1323
+ :widths: 10, 25, 25, 10
1324
+ :header: Field, OneTick, DU benchmark, WA benchmark
1325
+
1326
+ VALUE, 9.739720671039635, 9.739720664487278600, 9.740
1327
+ DELTA, -0.9429118423759162, -0.942911845180447200, -0.943
1328
+ GAMMA, 0.020391626464263516, 0.020391626464263600, 0.020
1329
+ THETA, 0.9410250231811439, 0.941025040605956600, 0.941
1330
+ VEGA, 2.1453108389800515, 2.145310838980050700, 2.145
1331
+ RHO, -4.666995510197969, -4.666995522132770800, -4.667
1332
+
1333
+ Call option, strike price 90.0, underlying price 80.0, volatility 30.0%, interest 8.0%, expiring in 20 days.
1334
+
1335
+ >>> data = {
1336
+ ... "PRICE": 80.,
1337
+ ... "OPTION_TYPE": "call",
1338
+ ... "STRIKE_PRICE": 90.,
1339
+ ... "DAYS_TILL_EXPIRATION": 20,
1340
+ ... "VOLATILITY": 0.3,
1341
+ ... "INTEREST_RATE": 0.08,
1342
+ ... }
1343
+ >>> data = otp.Tick(**data)
1344
+ >>> data = otp.agg.option_price(
1345
+ ... option_type_field_name='OPTION_TYPE',
1346
+ ... strike_price_field_name='STRIKE_PRICE',
1347
+ ... days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1348
+ ... volatility_field_name='VOLATILITY',
1349
+ ... interest_rate_field_name='INTEREST_RATE',
1350
+ ... compute_delta=True,
1351
+ ... compute_gamma=True,
1352
+ ... compute_theta=True,
1353
+ ... compute_vega=True,
1354
+ ... compute_rho=True
1355
+ ... ).apply(data)
1356
+ >>> res = otp.run(data).drop("Time", axis=1)
1357
+ >>> for key, val in res.to_dict(orient='list').items():
1358
+ ... print(f"{key}={val[0]:.13f}")
1359
+ VALUE=0.1333777785229
1360
+ DELTA=0.0570881576241
1361
+ GAMMA=0.0203916264643
1362
+ THETA=-6.2274824082202
1363
+ VEGA=2.1453108389801
1364
+ RHO=0.2429410866523
1365
+
1366
+ .. csv-table:: Benchmark comparison
1367
+ :widths: 10, 25, 25, 10
1368
+ :header: Field, OneTick, DU benchmark, WA benchmark
1369
+
1370
+ VALUE, 0.13337777852292199, 0.133377771970562400, 0.133
1371
+ DELTA, 0.05708815762408384, 0.057088154819552600, 0.057
1372
+ GAMMA, 0.020391626464263516, 0.020391626464263600, 0.020
1373
+ THETA, -6.227482408220195, -6.227482390795381800, -6.227
1374
+ VEGA, 2.1453108389800515, 2.145310838980050700, 2.145
1375
+ RHO, 0.2429410866522622, 0.242941074717460500, 0.243
1376
+
1377
+
1378
+ Call option, strike price 140.0, underlying price 150.0, volatility 60.0%, interest 7.0%, expiring in 10 days.
1379
+
1380
+ >>> data = {
1381
+ ... "PRICE": 150.,
1382
+ ... "OPTION_TYPE": "call",
1383
+ ... "STRIKE_PRICE": 140.,
1384
+ ... "DAYS_TILL_EXPIRATION": 10,
1385
+ ... "VOLATILITY": 0.6,
1386
+ ... "INTEREST_RATE": 0.07,
1387
+ ... }
1388
+ >>> data = otp.Tick(**data)
1389
+ >>> data = otp.agg.option_price(
1390
+ ... option_type_field_name='OPTION_TYPE',
1391
+ ... strike_price_field_name='STRIKE_PRICE',
1392
+ ... days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1393
+ ... volatility_field_name='VOLATILITY',
1394
+ ... interest_rate_field_name='INTEREST_RATE',
1395
+ ... compute_delta=True,
1396
+ ... compute_gamma=True,
1397
+ ... compute_theta=True,
1398
+ ... compute_vega=True,
1399
+ ... compute_rho=True
1400
+ ... ).apply(data)
1401
+ >>> res = otp.run(data).drop("Time", axis=1)
1402
+ >>> for key, val in res.to_dict(orient='list').items():
1403
+ ... print(f"{key}={val[0]:.13f}")
1404
+ VALUE=12.2728332229748
1405
+ DELTA=0.7774682547236
1406
+ GAMMA=0.0200066930955
1407
+ THETA=-88.3314253858302
1408
+ VEGA=7.3997358024512
1409
+ RHO=2.8588330133030
1410
+
1411
+ .. csv-table:: Benchmark comparison
1412
+ :widths: 10, 25, 25, 10
1413
+ :header: Field, OneTick, DU benchmark, WA benchmark
1414
+
1415
+ VALUE, 12.272833222974782, 12.272833124496244700, 12.27
1416
+ DELTA, 0.7774682547235652, 0.777468265655730700, 0.777
1417
+ GAMMA, 0.020006693095516285, 0.020006693095516300, 0.020
1418
+ THETA, -88.33142538583016, -88.331425507511386000, -88.331
1419
+ VEGA, 7.399735802451228, 7.399735802451227600, 7.400
1420
+ RHO, 2.858833013303013, 2.858833060927763500, 2.859
1421
+
1422
+
1423
+ Put option, strike price 140.0, underlying price 150.0, volatility 60.0%, interest 7.0%, expiring in 10 days.
1424
+
1425
+ .. testcode::
1426
+ :skipif: not otp.compatibility.is_option_price_theta_value_changed()
1427
+
1428
+ data = {
1429
+ "PRICE": 150.,
1430
+ "OPTION_TYPE": "put",
1431
+ "STRIKE_PRICE": 140.,
1432
+ "DAYS_TILL_EXPIRATION": 10,
1433
+ "VOLATILITY": 0.6,
1434
+ "INTEREST_RATE": 0.07,
1435
+ }
1436
+ data = otp.Tick(**data)
1437
+ data = otp.agg.option_price(
1438
+ option_type_field_name='OPTION_TYPE',
1439
+ strike_price_field_name='STRIKE_PRICE',
1440
+ days_till_expiration_field_name='DAYS_TILL_EXPIRATION',
1441
+ volatility_field_name='VOLATILITY',
1442
+ interest_rate_field_name='INTEREST_RATE',
1443
+ compute_delta=True,
1444
+ compute_gamma=True,
1445
+ compute_theta=True,
1446
+ compute_vega=True,
1447
+ compute_rho=True).apply(data)
1448
+ res = otp.run(data).drop("Time", axis=1)
1449
+ for key, val in res.to_dict(orient='list').items():
1450
+ print(f"{key}={val[0]:.13f}")
1451
+
1452
+ .. testoutput::
1453
+
1454
+ VALUE=2.0045973669685
1455
+ DELTA=-0.2225317452764
1456
+ GAMMA=0.0200066930955
1457
+ THETA=-78.5502018957506
1458
+ VEGA=7.3997358024512
1459
+ RHO=-0.9694344974913
1460
+
1461
+ .. csv-table:: Benchmark comparison
1462
+ :widths: 10, 25, 25, 10
1463
+ :header: Field, OneTick, DU benchmark, WA benchmark
1464
+
1465
+ VALUE, 2.0045973669685395, 2.004597268490016500, 2.00
1466
+ DELTA, -0.22253174527643482, -0.222531734344269000, -0.223
1467
+ GAMMA, 0.020006693095516285, 0.020006693095516300, 0.020
1468
+ THETA, -78.5502018957506, -78.550202017431814100, -78.550
1469
+ VEGA, 7.399735802451228, 7.399735802451227600, 7.400
1470
+ RHO, -0.9694344974913363, -0.969434449866586000, -0.969
1471
+
1472
+ """
1473
+
1474
+ return OptionPrice(*args, **kwargs)
1475
+
1476
+
1477
+ @docstring(parameters=[
1478
+ _bucket_interval_doc,
1479
+ _bucket_units_doc,
1480
+ _bucket_time_doc,
1481
+ _bucket_end_condition_doc,
1482
+ _boundary_tick_bucket_doc,
1483
+ _group_by_doc,
1484
+ _groups_to_display_doc,
1485
+ _end_condition_per_group_doc,
1486
+ ])
1487
+ def ranking(*args, **kwargs):
1488
+ """
1489
+ Ranking **running** aggregation.
1490
+
1491
+ Sorts a series of ticks over a bucket interval
1492
+ using a specified set of tick fields specified in ``rank_by``
1493
+ and adds a new field ``RANKING``
1494
+ with the position of the tick in the sort order
1495
+ or the percentage of ticks with values less than (or equal) to the value of the tick.
1496
+
1497
+ Does not change the order of the ticks.
1498
+
1499
+ See also
1500
+ --------
1501
+ **RANKING** OneTick event processor
1502
+
1503
+ Parameters
1504
+ ----------
1505
+ rank_by: str or list or dict
1506
+ Set of fields to sort by.
1507
+ Can be one field specified by string, list of fields or dictionary with field names
1508
+ as keys and ``asc`` or ``desc`` string literals as values. Latter allows to specify
1509
+ sorting direction. Default direction is ``desc``.
1510
+ show_rank_as: str
1511
+
1512
+ - ``order``: calculate number that represents the position of the tick in the sort order
1513
+ - ``percent_le_values``: calculate the percentage of ticks that have higher or equal value\
1514
+ of the position in the sort order, relative to the tick
1515
+ - ``percent_lt_values``: calculate the percentage of ticks that have higher value\
1516
+ of the position in the sort order, relative to the tick
1517
+ - ``percentile_standard``: calculate Percentile Rank of the tick in the sort order.
1518
+ include_tick: bool, default=False
1519
+ Specifies whether the current tick should be included in calculations
1520
+ if ``show_rank_as`` is ``percent_lt_values`` or ``percentile_standard``.
1521
+
1522
+ Examples
1523
+ --------
1524
+ >>> t = otp.Ticks({'A': [1, 2, 3]})
1525
+ >>> t = t.ranking('A')
1526
+ >>> otp.run(t)
1527
+ Time A RANKING
1528
+ 0 2003-12-01 00:00:00.000 1 3
1529
+ 1 2003-12-01 00:00:00.001 2 2
1530
+ 2 2003-12-01 00:00:00.002 3 1
1531
+
1532
+ >>> t = otp.Ticks({'A': [1, 2, 3]})
1533
+ >>> t = t.ranking({'A': 'asc'})
1534
+ >>> otp.run(t)
1535
+ Time A RANKING
1536
+ 0 2003-12-01 00:00:00.000 1 1
1537
+ 1 2003-12-01 00:00:00.001 2 2
1538
+ 2 2003-12-01 00:00:00.002 3 3
1539
+
1540
+ >>> t = otp.Ticks({'A': [1, 2, 2, 3, 2, 1]})
1541
+ >>> otp.run(t.ranking({'A': 'asc'}, show_rank_as='percent_lt_values', include_tick=True))
1542
+ Time A RANKING
1543
+ 0 2003-12-01 00:00:00.000 1 66.666667
1544
+ 1 2003-12-01 00:00:00.001 2 16.666667
1545
+ 2 2003-12-01 00:00:00.002 2 16.666667
1546
+ 3 2003-12-01 00:00:00.003 3 0.000000
1547
+ 4 2003-12-01 00:00:00.004 2 16.666667
1548
+ 5 2003-12-01 00:00:00.005 1 66.666667
1549
+
1550
+ >>> otp.run(t.ranking({'A': 'asc'}, show_rank_as='percent_lt_values', include_tick=False))
1551
+ Time A RANKING
1552
+ 0 2003-12-01 00:00:00.000 1 80.0
1553
+ 1 2003-12-01 00:00:00.001 2 20.0
1554
+ 2 2003-12-01 00:00:00.002 2 20.0
1555
+ 3 2003-12-01 00:00:00.003 3 0.0
1556
+ 4 2003-12-01 00:00:00.004 2 20.0
1557
+ 5 2003-12-01 00:00:00.005 1 80.0
1558
+ """
1559
+ return Ranking(*args, **kwargs)
1560
+
1561
+
1562
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
1563
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
1564
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc])
1565
+ def variance(*args, **kwargs):
1566
+ """
1567
+ Implement variance aggregation
1568
+
1569
+ Parameters
1570
+ ----------
1571
+ biased: bool
1572
+ Switches between biased and unbiased variance calculation.
1573
+
1574
+ See also
1575
+ --------
1576
+ **VARIANCE** OneTick event processor
1577
+
1578
+ Examples
1579
+ --------
1580
+
1581
+ >>> data = otp.Ticks(X=[1, 2, 3, 3, 4])
1582
+ >>> data = data.agg({'RESULT': otp.agg.variance('X', biased=False)})
1583
+ >>> otp.run(data)
1584
+ Time RESULT
1585
+ 0 2003-12-04 1.3
1586
+
1587
+ >>> data = otp.Ticks(X=[1, 2, 3, 3, 4])
1588
+ >>> data = data.agg({'RESULT': otp.agg.variance('X', biased=True)})
1589
+ >>> otp.run(data)
1590
+ Time RESULT
1591
+ 0 2003-12-04 1.04
1592
+ """
1593
+ return Variance(*args, **kwargs)
1594
+
1595
+
1596
+ @docstring(parameters=[
1597
+ _running_doc,
1598
+ _bucket_interval_doc,
1599
+ _bucket_units_doc,
1600
+ _bucket_time_doc,
1601
+ _bucket_end_condition_doc,
1602
+ _boundary_tick_bucket_doc,
1603
+ _group_by_doc,
1604
+ _groups_to_display_doc,
1605
+ _end_condition_per_group_doc,
1606
+ ])
1607
+ def percentile(*args, **kwargs):
1608
+ """
1609
+ Percentile **running** aggregation.
1610
+
1611
+ For each bucket, propagates its ``n-1`` ``n-quantiles`` where a comparison between ticks is done
1612
+ using a specified set of tick fields. A new field (``QUANTILE``) with the quantile number is added.
1613
+
1614
+ See also
1615
+ --------
1616
+ **PERCENTILE** OneTick event processor
1617
+
1618
+ Parameters
1619
+ ----------
1620
+ number_of_quantiles: int
1621
+ Specifies the number ``n`` of quantiles. Setting it to 2 will propagate only one tick - the median.
1622
+
1623
+ Default: 2
1624
+ input_field_names: List[Union[Union[str, onetick.py.Column], Tuple[Union[str, onetick.py.Column], str]]]
1625
+ List of numeric field names to run aggregation on.
1626
+ You can use as list elements either string column name, either :py:class:`Columns <onetick.py.Column>`.
1627
+
1628
+ You can change default comparison order (``desc``) for the field,
1629
+ by passing a tuple of column name and comparison order (``desc`` or ``asc``) instead column name.
1630
+ output_field_names: Optional[List[str]]
1631
+ Output columns name in the same order as columns from ``input_field_names``
1632
+
1633
+ ``output_field_names`` and ``input_field_names`` must have the same number of fields.
1634
+
1635
+ If not set, ``output_field_names`` will be equal to ``input_field_names``.
1636
+
1637
+ Examples
1638
+ --------
1639
+ >>> t = otp.Ticks({'A': [1, 2, 3, 4]})
1640
+ >>> t = t.percentile(['A'])
1641
+ >>> otp.run(t)
1642
+ Time A QUANTILE
1643
+ 0 2003-12-04 2 1
1644
+
1645
+ You can also pass column:
1646
+
1647
+ >>> t = otp.Ticks({'A': [1, 2, 3, 4]})
1648
+ >>> t = t.percentile([t['A']])
1649
+ >>> otp.run(t)
1650
+ Time A QUANTILE
1651
+ 0 2003-12-04 2 1
1652
+
1653
+ Change number of quantiles:
1654
+
1655
+ >>> t = otp.Ticks({'A': [1, 2, 3, 4]})
1656
+ >>> t = t.percentile(['A'], number_of_quantiles=3)
1657
+ >>> otp.run(t)
1658
+ Time A QUANTILE
1659
+ 0 2003-12-04 3 1
1660
+ 1 2003-12-04 2 2
1661
+
1662
+ Or change default comparison order:
1663
+
1664
+ >>> t = otp.Ticks({'A': [1, 2, 3, 4]})
1665
+ >>> t = t.percentile([('A', 'asc')], number_of_quantiles=3)
1666
+ >>> otp.run(t)
1667
+ Time A QUANTILE
1668
+ 0 2003-12-04 2 1
1669
+ 1 2003-12-04 3 2
1670
+
1671
+ You can also change output column name via ``output_field_names`` parameter:
1672
+
1673
+ >>> t = otp.Ticks({'A': [1, 2, 3, 4]})
1674
+ >>> t = t.percentile(['A'], output_field_names=['B'])
1675
+ >>> otp.run(t)
1676
+ Time B QUANTILE
1677
+ 0 2003-12-04 2 1
1678
+ """
1679
+ return Percentile(*args, **kwargs)
1680
+
1681
+
1682
+ @docstring(parameters=[
1683
+ _running_doc,
1684
+ _bucket_interval_doc,
1685
+ _bucket_units_doc,
1686
+ _bucket_time_doc,
1687
+ _bucket_end_condition_doc,
1688
+ _boundary_tick_bucket_doc,
1689
+ _group_by_doc,
1690
+ _groups_to_display_doc,
1691
+ _end_condition_per_group_doc,
1692
+ ])
1693
+ def find_value_for_percentile(*args, **kwargs):
1694
+ """
1695
+ For each bucket, finds the value which has percentile rank closest to ``percentile`` parameter.
1696
+
1697
+ For more details, see `Percentile rank <https://en.wikipedia.org/wiki/Percentile_rank>`_.
1698
+
1699
+ See also
1700
+ --------
1701
+ **FIND_VALUE_FOR_PERCENTILE** OneTick event processor
1702
+
1703
+ Parameters
1704
+ ----------
1705
+ percentile: int
1706
+ Specifies the percentile number in 0-100% range
1707
+ for which find the value of input field that has percentile rank close to it.
1708
+ show_percentile_as: str
1709
+ * By default (when parameter is not set),
1710
+ the output field contains the value which has percentile rank closest to ``percentile`` parameter.
1711
+ * When set to *interpolated_value*, the output field contains the interpolated value of:
1712
+ The value above and below specified ``percentile``, or one of them if it's biggest or smallest value.
1713
+ * When set to *first_value_with_ge_percentile*, the output field contains
1714
+ the value which has greater or equal than specified ``percentile``.
1715
+
1716
+ Examples
1717
+ --------
1718
+
1719
+ Find interpolated value of 50% percentile rank:
1720
+
1721
+ .. testcode::
1722
+ :skipif: not otp.compatibility.is_find_value_for_percentile_supported()
1723
+
1724
+ t = otp.Ticks({'A': [1, 2, 3, 4]})
1725
+ data = t.find_value_for_percentile('A', 50, 'interpolated_value')
1726
+ df = otp.run(data)
1727
+ print(df)
1728
+
1729
+ .. testoutput::
1730
+
1731
+ Time A
1732
+ 0 2003-12-04 2.5
1733
+
1734
+ Find first value greater or equal to 50% percentile rank:
1735
+
1736
+ .. testcode::
1737
+ :skipif: not otp.compatibility.is_find_value_for_percentile_supported()
1738
+
1739
+ data = t.find_value_for_percentile('A', 50, 'first_value_with_ge_percentile')
1740
+ df = otp.run(data)
1741
+ print(df)
1742
+
1743
+ .. testoutput::
1744
+
1745
+ Time A
1746
+ 0 2003-12-04 3.0
1747
+
1748
+ Use :py:meth:`~onetick.py.Source.agg` method to apply several aggregations at the same time:
1749
+
1750
+ .. testcode::
1751
+ :skipif: not otp.compatibility.is_find_value_for_percentile_supported()
1752
+
1753
+ data = t.agg({
1754
+ 'X': otp.agg.find_value_for_percentile('A', 50, 'interpolated_value'),
1755
+ 'COUNT': otp.agg.count(),
1756
+ })
1757
+ df = otp.run(data)
1758
+ print(df)
1759
+
1760
+ .. testoutput::
1761
+
1762
+ Time X COUNT
1763
+ 0 2003-12-04 2.5 4
1764
+ """
1765
+ return FindValueForPercentile(*args, **kwargs)
1766
+
1767
+
1768
+ @docstring(parameters=[
1769
+ _decay_doc,
1770
+ _decay_value_type_doc,
1771
+ _running_doc,
1772
+ _bucket_interval_doc,
1773
+ _bucket_units_doc,
1774
+ _bucket_time_doc,
1775
+ _bucket_end_condition_doc,
1776
+ _boundary_tick_bucket_doc,
1777
+ _all_fields_doc,
1778
+ _group_by_doc,
1779
+ _groups_to_display_doc,
1780
+ _end_condition_per_group_doc,
1781
+ _time_series_type_w_doc,
1782
+ ])
1783
+ def exp_w_average(*args, **kwargs):
1784
+ """
1785
+ ``EXP_W_AVERAGE`` aggregation.
1786
+
1787
+ For each bucket, computes the **exponentially weighted average** value of the specified numeric attribute.
1788
+ Weights of data points in a bucket decrease exponentially in the direction from the most recent tick
1789
+ to the most aged one, being equal to ``exp(-Lambda * N)`` for a fixed weight decay value **Lambda**,
1790
+ where **N** ranges over **0, 1, 2, …** as ticks in reverse order of their arrival are treated.
1791
+ Once the weights are known, the average is found using the formula ``sum(weight*value)/sum(weight)``,
1792
+ where the sum is computed across all data points.
1793
+
1794
+ See also
1795
+ --------
1796
+ **EXP_W_AVERAGE** OneTick event processor
1797
+
1798
+ Examples
1799
+ --------
1800
+
1801
+ Basic example
1802
+
1803
+ >>> data = otp.Ticks({'A': [1.0, 2.0, 3.0, 3.0, 4.0]})
1804
+ >>> data = data.exp_w_average('A', decay=2, bucket_interval=2, bucket_units='ticks')
1805
+ >>> otp.run(data)
1806
+ Time A
1807
+ 0 2003-12-01 00:00:00.001 1.880797
1808
+ 1 2003-12-01 00:00:00.003 2.984124
1809
+ 2 2003-12-04 00:00:00.000 3.880797
1810
+
1811
+ You can switch to ``half_life_index`` as ``decay_value_type``
1812
+
1813
+ >>> data = otp.Ticks({'A': [1.0, 2.0, 3.0, 3.0, 4.0]})
1814
+ >>> data = data.exp_w_average(
1815
+ ... 'A', decay=2, decay_value_type='half_life_index', bucket_interval=2, bucket_units='ticks',
1816
+ ... )
1817
+ >>> otp.run(data)
1818
+ Time A
1819
+ 0 2003-12-01 00:00:00.001 1.585786
1820
+ 1 2003-12-01 00:00:00.003 2.773459
1821
+ 2 2003-12-04 00:00:00.000 3.585786
1822
+ """
1823
+ return ExpWAverage(*args, **kwargs)
1824
+
1825
+
1826
+ @docstring(parameters=[
1827
+ _decay_doc,
1828
+ _decay_value_type_hl_doc,
1829
+ _running_doc,
1830
+ _bucket_interval_doc,
1831
+ _bucket_units_doc,
1832
+ _bucket_time_doc,
1833
+ _bucket_end_condition_doc,
1834
+ _boundary_tick_bucket_doc,
1835
+ _all_fields_doc,
1836
+ _group_by_doc,
1837
+ _groups_to_display_doc,
1838
+ _end_condition_per_group_doc,
1839
+ ])
1840
+ def exp_tw_average(*args, **kwargs):
1841
+ """
1842
+ ``EXP_TW_AVERAGE`` aggregation.
1843
+
1844
+ For each bucket, computes the **exponentially time-weighted average** value of a specified numeric field.
1845
+ The weight of each point in the time series is computed relative to the end time of the bucket,
1846
+ so that the value which is in effect during some infinitely small time interval `delta t`
1847
+ has weight **(delta t)*exp(-Lambda*(end_time - t))**,
1848
+ where `Lambda` is a constant, `end_time` represents end time of the bucket,
1849
+ and `t` represents the timestamp of that infinitely small time interval.
1850
+
1851
+ See also
1852
+ --------
1853
+ **EXP_TW_AVERAGE** OneTick event processor
1854
+
1855
+ Examples
1856
+ --------
1857
+
1858
+ Basic example
1859
+
1860
+ >>> data = otp.Ticks({'A': [1.0, 2.0, 3.0, 3.0, 4.0]})
1861
+ >>> data = data.exp_tw_average('A', decay=2, bucket_interval=2, bucket_units='ticks')
1862
+ >>> otp.run(data)
1863
+ Time A
1864
+ 0 2003-12-01 00:00:00.001 1.000000
1865
+ 1 2003-12-01 00:00:00.003 2.500087
1866
+ 2 2003-12-04 00:00:00.000 4.000000
1867
+
1868
+ You can switch to ``lambda`` as ``decay_value_type``
1869
+
1870
+ >>> data = otp.Ticks({'A': [1.0, 2.0, 3.0, 3.0, 4.0]})
1871
+ >>> data = data.exp_tw_average(
1872
+ ... 'A', decay=2, decay_value_type='lambda', bucket_interval=2, bucket_units='ticks',
1873
+ ... )
1874
+ >>> otp.run(data)
1875
+ Time A
1876
+ 0 2003-12-01 00:00:00.001 1.0000
1877
+ 1 2003-12-01 00:00:00.003 2.5005
1878
+ 2 2003-12-04 00:00:00.000 4.0000
1879
+ """
1880
+ return ExpTwAverage(*args, **kwargs)
1881
+
1882
+
1883
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
1884
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
1885
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc, _degree_doc])
1886
+ def standardized_moment(*args, **kwargs):
1887
+ """
1888
+ ``STANDARDIZED_MOMENT`` aggregation.
1889
+
1890
+ Computes the standardized statistical moment of degree **k** of the input ``column``
1891
+ over the specified bucket interval.
1892
+ The standardized moment of degree **k** is defined
1893
+ as the expected value of the expression ``((X - mean) / stddev)^k``.
1894
+
1895
+ See also
1896
+ --------
1897
+ **STANDARDIZED_MOMENT** OneTick event processor
1898
+
1899
+ Examples
1900
+ --------
1901
+
1902
+ Basic example
1903
+
1904
+ .. testcode::
1905
+ :skipif: not otp.compatibility.is_standardized_moment_supported()
1906
+
1907
+ data = otp.Ticks({'A': [1, 2, 4, 4, 4, 6]})
1908
+ data = data.standardized_moment('A', degree=3, bucket_interval=3, bucket_units='ticks')
1909
+ df = otp.run(data)
1910
+ print(df)
1911
+
1912
+ .. testoutput::
1913
+ Time A
1914
+ 0 2003-12-01 00:00:00.002 0.381802
1915
+ 1 2003-12-01 00:00:00.005 0.707107
1916
+ """
1917
+ return StandardizedMoment(*args, **kwargs)
1918
+
1919
+
1920
+ @docstring(parameters=[_column_doc, _running_doc, _bucket_interval_doc, _bucket_time_doc,
1921
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
1922
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
1923
+ _weight_field_name_doc, _portfolio_side_doc,
1924
+ _weight_type_doc, _symbols_doc])
1925
+ def portfolio_price(*args, **kwargs):
1926
+ """
1927
+ ``PORTFOLIO_PRICE`` aggregation.
1928
+
1929
+ For each bucket, computes weighted portfolio price.
1930
+
1931
+ See also
1932
+ --------
1933
+ **PORTFOLIO_PRICE** OneTick event processor
1934
+
1935
+ Examples
1936
+ --------
1937
+
1938
+ Basic example, by default this EP takes ``PRICE`` column as input
1939
+
1940
+ >>> data = otp.DataSource(
1941
+ ... 'US_COMP', symbol='AAPL', tick_type='TRD',
1942
+ ... start=otp.dt(2022, 3, 1), end=otp.dt(2022, 3, 2),
1943
+ ... )
1944
+ >>> data = data.portfolio_price()
1945
+ >>> otp.run(data)
1946
+ Time VALUE NUM_SYMBOLS
1947
+ 0 2022-03-02 1.4 1
1948
+
1949
+ Getting portfolio price for multiple symbols:
1950
+
1951
+ >>> data = otp.DataSource('US_COMP', tick_type='TRD', start=otp.dt(2022, 3, 1), end=otp.dt(2022, 3, 2))
1952
+ >>> data = data.portfolio_price(symbols=['AAPL', 'AAP'])
1953
+ >>> otp.run(data)
1954
+ Time VALUE NUM_SYMBOLS
1955
+ 0 2022-03-02 46.81 2
1956
+
1957
+ Applying **PORTFOLIO_PRICE** on custom column
1958
+
1959
+ >>> data = otp.Ticks(X=[10.0, 12.5, 11.0, 10.2, 15])
1960
+ >>> data = data.portfolio_price('X')
1961
+ >>> otp.run(data)
1962
+ Time VALUE NUM_SYMBOLS
1963
+ 0 2003-12-04 15.0 1
1964
+
1965
+ Specifying weights via column 'WEIGHS'
1966
+
1967
+ >>> data = otp.Ticks(PRICE=[10.0, 12.5, 11.0, 10.2, 15], WEIGHTS=[1, 2, -1, 2, 2])
1968
+ >>> data = data.portfolio_price(weight_field_name=data['WEIGHTS'])
1969
+ >>> otp.run(data)
1970
+ Time VALUE NUM_SYMBOLS
1971
+ 0 2003-12-04 30.0 1
1972
+ """
1973
+ return PortfolioPrice(*args, **kwargs)
1974
+
1975
+
1976
+ @docstring(parameters=[_portfolios_query_doc, _columns_portfolio_doc, _running_doc, _bucket_interval_doc,
1977
+ _bucket_time_doc, _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
1978
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
1979
+ _weight_field_name_doc,
1980
+ _weight_multiplier_field_name_doc, _portfolio_side_doc, _weight_type_doc,
1981
+ _portfolios_query_params_doc, _portfolio_value_field_name_doc, _symbols_doc])
1982
+ def multi_portfolio_price(*args, **kwargs):
1983
+ """
1984
+ ``MULTI_PORTFOLIO_PRICE`` aggregation.
1985
+
1986
+ For each bucket, computes weighted portfolio price for multiple portfolios.
1987
+
1988
+ See also
1989
+ --------
1990
+ **MULTI_PORTFOLIO_PRICE** OneTick event processor
1991
+
1992
+ Examples
1993
+ --------
1994
+
1995
+ Basic example, by default this EP takes ``PRICE`` column as input
1996
+
1997
+ >>> data = otp.DataSource(
1998
+ ... 'US_COMP', tick_type='TRD', date=otp.dt(2022, 3, 1)
1999
+ ... )
2000
+ >>> data = data.multi_portfolio_price(
2001
+ ... portfolios_query='some_query.otq::portfolios_query',
2002
+ ... symbols=['US_COMP::AAPL', 'US_COMP::MSFT', 'US_COMP::ORCL'],
2003
+ ... )
2004
+ >>> otp.run(data) # doctest: +SKIP
2005
+ Time VALUE NUM_SYMBOLS PORTFOLIO_NAME
2006
+ 0 2003-12-01 95.0 3 PORTFOLIO_1
2007
+ 1 2003-12-01 47.5 1 PORTFOLIO_2
2008
+ 2 2003-12-01 32.5 2 PORTFOLIO_3
2009
+
2010
+ Override ``weight`` returned by ``portfolios_query`` with ``weight_field_name``
2011
+
2012
+ >>> data = otp.DataSource(
2013
+ ... 'US_COMP', tick_type='TRD', date=otp.dt(2022, 3, 1)
2014
+ ... )
2015
+ >>> data['WEIGHT'] = 2
2016
+ >>> data = data.multi_portfolio_price(
2017
+ ... portfolios_query='some_query.otq::portfolios_query',
2018
+ ... weight_field_name='WEIGHT',
2019
+ ... symbols=['US_COMP::AAPL', 'US_COMP::MSFT', 'US_COMP::ORCL'],
2020
+ ... )
2021
+ >>> otp.run(data) # doctest: +SKIP
2022
+ Time VALUE NUM_SYMBOLS PORTFOLIO_NAME
2023
+ 0 2003-12-01 38.0 3 PORTFOLIO_1
2024
+ 1 2003-12-01 19.0 1 PORTFOLIO_2
2025
+ 2 2003-12-01 13.0 2 PORTFOLIO_3
2026
+
2027
+ Pass parameters to the query from ``portfolios_query`` via ``portfolios_query_params``
2028
+
2029
+ >>> data = otp.DataSource(
2030
+ ... 'US_COMP', tick_type='TRD', date=otp.dt(2022, 3, 1)
2031
+ ... )
2032
+ >>> data = data.multi_portfolio_price(
2033
+ ... portfolios_query='some_query.otq::portfolios_query_with_param',
2034
+ ... symbols=['US_COMP::AAPL', 'US_COMP::MSFT', 'US_COMP::ORCL'],
2035
+ ... portfolios_query_params={'PORTFOLIO_1_NAME': 'CUSTOM_NAME'}
2036
+ ... )
2037
+ >>> otp.run(data) # doctest: +SKIP
2038
+ Time VALUE NUM_SYMBOLS PORTFOLIO_NAME
2039
+ 0 2003-12-01 95.0 3 CUSTOM_NAME
2040
+ 1 2003-12-01 47.5 1 PORTFOLIO_2
2041
+ 2 2003-12-01 32.5 2 PORTFOLIO_3
2042
+
2043
+ Use ``otp.Source`` object as ``portfolios_query`` (only for local queries)
2044
+
2045
+ >>> portfolios = otp.Ticks(
2046
+ ... SYMBOL_NAME=['US_COMP::AAPL', 'US_COMP::MSFT', 'US_COMP::AAPL'],
2047
+ ... PORTFOLIO_NAME=['PORTFOLIO_1', 'PORTFOLIO_1', 'PORTFOLIO_2'],
2048
+ ... WEIGHT=[1, 1, 2],
2049
+ ... )
2050
+ >>> data = otp.DataSource(
2051
+ ... 'US_COMP', tick_type='TRD', date=otp.dt(2022, 3, 1)
2052
+ ... )
2053
+ >>> data = data.multi_portfolio_price(
2054
+ ... portfolios_query=portfolios,
2055
+ ... symbols=['US_COMP::AAPL', 'US_COMP::MSFT'],
2056
+ ... )
2057
+ >>> otp.run(data) # doctest: +SKIP
2058
+ Time VALUE NUM_SYMBOLS PORTFOLIO_NAME
2059
+ 0 2003-12-01 47.5 2 PORTFOLIO_1
2060
+ 1 2003-12-01 46.0 1 PORTFOLIO_2
2061
+ """
2062
+ return MultiPortfolioPrice(*args, **kwargs)
2063
+
2064
+
2065
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
2066
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
2067
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc])
2068
+ def return_ep(*args, **kwargs):
2069
+ """
2070
+ ``RETURN`` aggregation.
2071
+
2072
+ Computes the ratio between the value of the input field at the end of a bucket interval and the value
2073
+ of this field at the start of a bucket interval.
2074
+ If ``running`` is set to ``True``, then ``RETURN`` is calculated as the ratio between latest tick
2075
+ and the first tick from the start time. Below, the input field is referred to as 'price'.
2076
+
2077
+ ``Return for an interval = ending price for the interval / starting price for the interval``
2078
+
2079
+ where
2080
+
2081
+ * ``ending price for the interval`` is taken from the last tick observed in the stream
2082
+ up to the end of the interval.
2083
+ * ``starting price for the interval`` is taken from the first tick in the interval for the first bucket interval
2084
+ that has any ticks. For all other intervals, it is the price of the first tick with timestamp of the start
2085
+ of interval or, if no such tick is present, the ending price of the previous interval. The ending price
2086
+ for the interval is taken from the last tick observed in the stream up to the end of the interval.
2087
+
2088
+ See also
2089
+ --------
2090
+ **RETURN** OneTick event processor
2091
+
2092
+ Examples
2093
+ --------
2094
+
2095
+ Basic example as :py:class:`~onetick.py.Source` method
2096
+
2097
+ >>> data = otp.DataSource('US_COMP', symbol='AAPL', tick_type='TRD')
2098
+ >>> data = data.return_ep(data['PRICE'], bucket_interval=otp.Minute(10))
2099
+ >>> otp.run(data, date=otp.dt(2022, 3, 1)) # doctest: +SKIP
2100
+ Time PRICE
2101
+ 0 2022-03-01 00:00:00.000 0.99953
2102
+ 1 2022-03-01 00:10:00.000 1.0043
2103
+ 2 2022-03-01 00:20:00.000 0.9986
2104
+ 3 2022-03-01 00:30:00.000 0.99643
2105
+ 4 2022-03-01 00:40:00.000 1.042
2106
+ ...
2107
+
2108
+ Basic example as aggregation
2109
+
2110
+ >>> data = otp.DataSource('US_COMP', symbol='AAPL', tick_type='TRD')
2111
+ >>> data = otp.agg.return_ep(data['PRICE'], bucket_interval=otp.Minute(10)).apply(data)
2112
+ >>> otp.run(data, date=otp.dt(2022, 3, 1)) # doctest: +SKIP
2113
+ Time PRICE
2114
+ 0 2022-03-01 00:00:00.000 0.99953
2115
+ 1 2022-03-01 00:10:00.000 1.0043
2116
+ 2 2022-03-01 00:20:00.000 0.9986
2117
+ 3 2022-03-01 00:30:00.000 0.99643
2118
+ 4 2022-03-01 00:40:00.000 1.042
2119
+ ...
2120
+ """
2121
+ return Return(*args, **kwargs)
2122
+
2123
+
2124
+ @docstring(parameters=[_column_doc, _running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
2125
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
2126
+ _boundary_tick_bucket_doc, _group_by_doc, _groups_to_display_doc,
2127
+ _interest_rate_doc, _price_field_doc, _option_price_field_doc,
2128
+ _method_doc, _precision_doc, _value_for_non_converge_doc, _option_type_field_doc,
2129
+ _strike_price_field_doc, _days_in_year_doc, _days_till_expiration_field_doc,
2130
+ _expiration_date_field_doc,
2131
+ ])
2132
+ def implied_vol(*args, **kwargs):
2133
+ """
2134
+ ``IMPLIED_VOL`` aggregation.
2135
+
2136
+ For each bucket, computes implied volatility value for the last tick in the bucket,
2137
+ based on the Black-Scholes option pricing model.
2138
+
2139
+ This EP requires a time series of ticks, having the ``PRICE`` and ``OPTION_PRICE`` attributes.
2140
+
2141
+ It also requires several parameters to compute the implied volatility.
2142
+ Those are, ``OPTION_TYPE``, ``STRIKE_PRICE``, ``EXPIRATION_DATE`` or ``DAYS_TILL_EXPIRATION`` and ``INTEREST_RATE``.
2143
+ Each parameter can be specified either via a symbol parameter with the same name, or via a tick field,
2144
+ by specifying name of that field as an EP parameter.
2145
+ Besides, ``interest_rate`` can also be specified as aggregation parameter.
2146
+ In either case ``OPTION_TYPE`` must have either ``CALL`` value, or ``PUT``.
2147
+ ``EXPIRATION_DATE`` is in ``YYYYMMDD`` format, a string in case of a symbol parameter and an integer
2148
+ in case of a tick attribute.
2149
+
2150
+ See also
2151
+ --------
2152
+ **IMPLIED_VOL** OneTick event processor
2153
+
2154
+ Examples
2155
+ --------
2156
+
2157
+ Basic example:
2158
+
2159
+ >>> data = otp.DataSource('SOME_DB', symbol='AAA', tick_type='TT') # doctest: +SKIP
2160
+ >>> data = data.implied_vol(
2161
+ ... interest_rate=0.05, option_type_field=data['OPTION_TYPE'],
2162
+ ... strike_price_field=data['STRIKE_PRICE'], days_till_expiration_field=data['DAYS_TILL_EXPIRATION'],
2163
+ ... ) # doctest: +SKIP
2164
+ >>> otp.run(data) # doctest: +SKIP
2165
+ Time VALUE
2166
+ 0 2003-12-04 0.889491
2167
+
2168
+ Specifying ``interest_rate`` and ``strike_price`` as symbol parameters:
2169
+
2170
+ >>> sym = otp.Ticks({
2171
+ ... 'SYMBOL_NAME': ['TEST'],
2172
+ ... 'INTEREST_RATE': [0.05],
2173
+ ... 'STRIKE_PRICE': [100.0],
2174
+ ... }) # doctest: +SKIP
2175
+ >>> data = otp.DataSource('SOME_DB', symbol='AAA', tick_type='TT') # doctest: +SKIP
2176
+ >>> data = data.implied_vol(
2177
+ ... option_type_field=data['OPTION_TYPE'], days_till_expiration_field=data['DAYS_TILL_EXPIRATION'],
2178
+ ... ) # doctest: +SKIP
2179
+ >>> otp.run(data) # doctest: +SKIP
2180
+ Time VALUE
2181
+ 0 2003-12-04 0.889491
2182
+ """
2183
+ return ImpliedVol(*args, **kwargs)
2184
+
2185
+
2186
+ @docstring(parameters=[_running_doc, _all_fields_doc, _bucket_interval_doc, _bucket_time_doc,
2187
+ _bucket_units_doc, _bucket_end_condition_doc, _end_condition_per_group_doc,
2188
+ _boundary_tick_bucket_doc,
2189
+ ])
2190
+ def linear_regression(*args, **kwargs):
2191
+ """
2192
+ ``LINEAR_REGRESSION`` aggregation.
2193
+
2194
+ For each bucket, computes the linear regression parameters slope and intercept of specified input fields
2195
+ ``dependent_variable_field_name`` and ``independent_variable_field_name``.
2196
+ Adds computed parameters as `SLOPE` and `INTERCEPT` fields in output time series.
2197
+ The relationship between the dependent variable (``Y``) and the independent variable (``X``) is defined
2198
+ by the formula: Y = SLOPE * X + INTERCEPT, where `SLOPE` and `INTERCEPT` are the calculated output parameters.
2199
+
2200
+ See also
2201
+ --------
2202
+ **LINEAR_REGRESSION** OneTick event processor
2203
+
2204
+ Examples
2205
+ --------
2206
+
2207
+ >>> data = otp.Ticks({'X': [10.0, 9.5, 8.0, 8.5], 'Y': [3.0, 5.0, 4.5, 3.5]})
2208
+ >>> data = data.linear_regression(
2209
+ ... dependent_variable_field_name=data['Y'],
2210
+ ... independent_variable_field_name=data['X'],
2211
+ ... ) # doctest: +SKIP
2212
+ >>> otp.run(data) # doctest: +SKIP
2213
+ Time SLOPE INTERCEPT
2214
+ 0 2003-12-04 -0.3 6.7
2215
+ """
2216
+ return LinearRegression(*args, **kwargs)