dycw-utilities 0.109.17__tar.gz → 0.109.19__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/PKG-INFO +1 -1
  2. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/pyproject.toml +2 -2
  3. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_numpy.py +30 -16
  4. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_polars.py +69 -0
  5. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/__init__.py +1 -1
  6. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/numpy.py +44 -27
  7. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/polars.py +106 -0
  8. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/polars_ols.py +3 -1
  9. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/.gitignore +0 -0
  10. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/LICENSE +0 -0
  11. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/README.md +0 -0
  12. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/__init__.py +0 -0
  13. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/conftest.py +0 -0
  14. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/__init__.py +0 -0
  15. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_missing/__init__.py +0 -0
  16. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_missing/module.py +0 -0
  17. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_with/__init__.py +0 -0
  18. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_with/outer_1.py +0 -0
  19. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_with/outer_2.py +0 -0
  20. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_with/subpackage/__init__.py +0 -0
  21. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_with/subpackage/inner_1.py +0 -0
  22. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_with/subpackage/inner_2.py +0 -0
  23. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_with/subpackage/inner_3.py +0 -0
  24. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_without/__init__.py +0 -0
  25. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_without/module_1.py +0 -0
  26. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/package_without/module_2.py +0 -0
  27. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/standalone.py +0 -0
  28. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/modules/with_imports.py +0 -0
  29. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__obj.json +0 -0
  30. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/regressions/test_pytest_regressions/TestMultipleRegressionFixtures__test_main__series.json +0 -0
  31. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_int.json +0 -0
  32. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__false.json +0 -0
  33. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_literal__true.json +0 -0
  34. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/regressions/test_pytest_regressions/TestOrjsonRegressionFixture__test_dataclass_nested.json +0 -0
  35. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_dataframe.json +0 -0
  36. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/regressions/test_pytest_regressions/TestPolarsRegressionFixture__test_series.json +0 -0
  37. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/scripts/__init__.py +0 -0
  38. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/scripts/test_async_service/__init__.py +0 -0
  39. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/scripts/test_async_service/__main__.py +0 -0
  40. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/scripts/test_async_service/run.sh +0 -0
  41. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/scripts/test_queue_processor/__init__.py +0 -0
  42. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/scripts/test_queue_processor/__main__.py +0 -0
  43. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/scripts/test_queue_processor/run.sh +0 -0
  44. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_altair.py +0 -0
  45. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_astor.py +0 -0
  46. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_asyncio.py +0 -0
  47. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_atomicwrites.py +0 -0
  48. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_atools.py +0 -0
  49. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_cachetools.py +0 -0
  50. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_click.py +0 -0
  51. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_concurrent.py +0 -0
  52. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_contextlib.py +0 -0
  53. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_contextvars.py +0 -0
  54. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_cryptography.py +0 -0
  55. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_cvxpy.py +0 -0
  56. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_dataclasses.py +0 -0
  57. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_datetime.py +0 -0
  58. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_enum.py +0 -0
  59. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_errors.py +0 -0
  60. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_eventkit.py +0 -0
  61. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_fastapi.py +0 -0
  62. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_fpdf2.py +0 -0
  63. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_functions.py +0 -0
  64. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_functools.py +0 -0
  65. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_getpass.py +0 -0
  66. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_git.py +0 -0
  67. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_hashlib.py +0 -0
  68. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_http.py +0 -0
  69. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_hypothesis.py +0 -0
  70. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_ipython.py +0 -0
  71. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_iterables.py +0 -0
  72. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_jupyter.py +0 -0
  73. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_lightweight_charts.py +0 -0
  74. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_logging.py +0 -0
  75. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_loguru.py +0 -0
  76. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_luigi.py +0 -0
  77. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_math.py +0 -0
  78. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_memory_profiler.py +0 -0
  79. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_modules.py +0 -0
  80. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_more_itertools.py +0 -0
  81. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_operator.py +0 -0
  82. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_optuna.py +0 -0
  83. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_orjson.py +0 -0
  84. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_os.py +0 -0
  85. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_parse.py +0 -0
  86. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_pathlib.py +0 -0
  87. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_period.py +0 -0
  88. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_pickle.py +0 -0
  89. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_platform.py +0 -0
  90. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_polars_ols.py +0 -0
  91. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_pqdm.py +0 -0
  92. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_pydantic.py +0 -0
  93. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_pyinstrument.py +0 -0
  94. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_pyrsistent.py +0 -0
  95. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_pytest.py +0 -0
  96. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_pytest_regressions.py +0 -0
  97. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_python_dotenv.py +0 -0
  98. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_random.py +0 -0
  99. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_re.py +0 -0
  100. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_redis.py +0 -0
  101. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_reprlib.py +0 -0
  102. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_rich.py +0 -0
  103. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_scipy.py +0 -0
  104. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_sentinel.py +0 -0
  105. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_shelve.py +0 -0
  106. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_slack_sdk.py +0 -0
  107. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_socket.py +0 -0
  108. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_sqlalchemy.py +0 -0
  109. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_sqlalchemy_polars.py +0 -0
  110. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_streamlit.py +0 -0
  111. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_sys.py +0 -0
  112. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_tempfile.py +0 -0
  113. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_tenacity.py +0 -0
  114. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_text.py +0 -0
  115. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_threading.py +0 -0
  116. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_timer.py +0 -0
  117. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback.py +0 -0
  118. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/__init__.py +0 -0
  119. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/chain.py +0 -0
  120. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/decorated_async.py +0 -0
  121. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/decorated_sync.py +0 -0
  122. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/error_bind.py +0 -0
  123. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/many.py +0 -0
  124. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/one.py +0 -0
  125. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/recursive.py +0 -0
  126. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/task_group_one.py +0 -0
  127. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/task_group_two.py +0 -0
  128. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/two.py +0 -0
  129. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_traceback_funcs/untraced.py +0 -0
  130. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_types.py +0 -0
  131. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_typing.py +0 -0
  132. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_typing_funcs/__init__.py +0 -0
  133. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_typing_funcs/no_future.py +0 -0
  134. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_typing_funcs/with_future.py +0 -0
  135. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_tzdata.py +0 -0
  136. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_tzlocal.py +0 -0
  137. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_uuid.py +0 -0
  138. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_version.py +0 -0
  139. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_warnings.py +0 -0
  140. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_whenever.py +0 -0
  141. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_zipfile.py +0 -0
  142. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/tests/test_zoneinfo.py +0 -0
  143. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/altair.py +0 -0
  144. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/astor.py +0 -0
  145. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/asyncio.py +0 -0
  146. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/atomicwrites.py +0 -0
  147. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/atools.py +0 -0
  148. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/cachetools.py +0 -0
  149. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/click.py +0 -0
  150. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/concurrent.py +0 -0
  151. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/contextlib.py +0 -0
  152. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/contextvars.py +0 -0
  153. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/cryptography.py +0 -0
  154. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/cvxpy.py +0 -0
  155. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/dataclasses.py +0 -0
  156. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/datetime.py +0 -0
  157. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/enum.py +0 -0
  158. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/errors.py +0 -0
  159. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/eventkit.py +0 -0
  160. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/fastapi.py +0 -0
  161. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/fpdf2.py +0 -0
  162. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/functions.py +0 -0
  163. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/functools.py +0 -0
  164. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/getpass.py +0 -0
  165. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/git.py +0 -0
  166. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/hashlib.py +0 -0
  167. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/http.py +0 -0
  168. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/hypothesis.py +0 -0
  169. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/ipython.py +0 -0
  170. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/iterables.py +0 -0
  171. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/jupyter.py +0 -0
  172. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/lightweight_charts.py +0 -0
  173. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/logging.py +0 -0
  174. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/loguru.py +0 -0
  175. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/luigi.py +0 -0
  176. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/math.py +0 -0
  177. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/memory_profiler.py +0 -0
  178. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/modules.py +0 -0
  179. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/more_itertools.py +0 -0
  180. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/operator.py +0 -0
  181. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/optuna.py +0 -0
  182. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/orjson.py +0 -0
  183. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/os.py +0 -0
  184. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/parse.py +0 -0
  185. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/pathlib.py +0 -0
  186. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/period.py +0 -0
  187. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/pickle.py +0 -0
  188. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/platform.py +0 -0
  189. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/pqdm.py +0 -0
  190. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/py.typed +0 -0
  191. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/pydantic.py +0 -0
  192. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/pyinstrument.py +0 -0
  193. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/pyrsistent.py +0 -0
  194. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/pytest.py +0 -0
  195. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/pytest_regressions.py +0 -0
  196. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/python_dotenv.py +0 -0
  197. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/random.py +0 -0
  198. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/re.py +0 -0
  199. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/redis.py +0 -0
  200. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/reprlib.py +0 -0
  201. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/rich.py +0 -0
  202. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/scipy.py +0 -0
  203. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/sentinel.py +0 -0
  204. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/shelve.py +0 -0
  205. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/slack_sdk.py +0 -0
  206. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/socket.py +0 -0
  207. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/sqlalchemy.py +0 -0
  208. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/sqlalchemy_polars.py +0 -0
  209. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/streamlit.py +0 -0
  210. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/sys.py +0 -0
  211. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/tempfile.py +0 -0
  212. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/tenacity.py +0 -0
  213. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/text.py +0 -0
  214. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/threading.py +0 -0
  215. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/timer.py +0 -0
  216. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/traceback.py +0 -0
  217. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/types.py +0 -0
  218. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/typing.py +0 -0
  219. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/tzdata.py +0 -0
  220. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/tzlocal.py +0 -0
  221. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/uuid.py +0 -0
  222. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/version.py +0 -0
  223. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/warnings.py +0 -0
  224. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/whenever.py +0 -0
  225. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/zipfile.py +0 -0
  226. {dycw_utilities-0.109.17 → dycw_utilities-0.109.19}/src/utilities/zoneinfo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.109.17
3
+ Version: 0.109.19
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -92,7 +92,7 @@ dependencies = [
92
92
  name = "dycw-utilities"
93
93
  readme = "README.md"
94
94
  requires-python = ">= 3.12"
95
- version = "0.109.17"
95
+ version = "0.109.19"
96
96
 
97
97
  [project.optional-dependencies]
98
98
  test = [
@@ -335,7 +335,7 @@ zzz-test-zoneinfo = [
335
335
  # bump-my-version
336
336
  [tool.bumpversion]
337
337
  allow_dirty = true
338
- current_version = "0.109.17"
338
+ current_version = "0.109.19"
339
339
 
340
340
  [[tool.bumpversion.files]]
341
341
  filename = "src/utilities/__init__.py"
@@ -19,6 +19,7 @@ from numpy import (
19
19
  ndarray,
20
20
  ones,
21
21
  pi,
22
+ where,
22
23
  zeros,
23
24
  zeros_like,
24
25
  )
@@ -40,12 +41,12 @@ from utilities.numpy import (
40
41
  _BoxCarLocationsError,
41
42
  _BoxCarLowerBoundSlopeError,
42
43
  _BoxCarUpperBoundSlopeError,
44
+ adjust_frequencies,
43
45
  array_indexer,
44
46
  as_int,
45
47
  boxcar,
46
48
  discretize,
47
49
  fillna,
48
- filter_frequencies,
49
50
  flatn0,
50
51
  get_frequency_spectrum,
51
52
  has_dtype,
@@ -106,6 +107,32 @@ if TYPE_CHECKING:
106
107
  from collections.abc import Sequence
107
108
 
108
109
 
110
+ class TestAdjustFrequencies:
111
+ def test_filter(self) -> None:
112
+ n = 1000
113
+ x = linspace(0, 2 * pi, n)
114
+ noise = DEFAULT_RNG.normal(scale=0.25, size=n)
115
+ y = x + noise
116
+ result = adjust_frequencies(y, filters=lambda f: np.abs(f) <= 0.02)
117
+ assert result.shape == (n,)
118
+ amplitudes = fft(result)
119
+ freqs = fftfreq(n)
120
+ assert np.allclose(amplitudes[np.abs(freqs) > 0.02], 0.0)
121
+
122
+ def test_weight(self) -> None:
123
+ n = 1000
124
+ x = linspace(0, 2 * pi, n)
125
+ noise = DEFAULT_RNG.normal(scale=0.25, size=n)
126
+ y = x + noise
127
+ result = adjust_frequencies(
128
+ y, weights=lambda f: where(np.abs(f) <= 0.02, 1.0, 0.0)
129
+ )
130
+ assert result.shape == (n,)
131
+ amplitudes = fft(result)
132
+ freqs = fftfreq(n)
133
+ assert np.allclose(amplitudes[np.abs(freqs) > 0.02], 0.0)
134
+
135
+
109
136
  class TestArrayIndexer:
110
137
  @mark.parametrize(
111
138
  ("i", "ndim", "expected"),
@@ -330,19 +357,6 @@ class TestFillNa:
330
357
  assert_equal(result, expected)
331
358
 
332
359
 
333
- class TestFilterFrequencies:
334
- def test_main(self) -> None:
335
- n = 1000
336
- x = linspace(0, 2 * pi, n)
337
- noise = DEFAULT_RNG.normal(scale=0.25, size=n)
338
- y = x + noise
339
- result = filter_frequencies(y, lambda f: np.abs(f) <= 0.02)
340
- assert result.shape == (n,)
341
- fft_vals = fft(result)
342
- freqs = fftfreq(n)
343
- assert np.allclose(fft_vals[np.abs(freqs) > 0.02], 0.0)
344
-
345
-
346
360
  class TestFlatN0:
347
361
  @given(data=data(), n=integers(1, 10))
348
362
  def test_main(self, *, data: DataObject, n: int) -> None:
@@ -369,10 +383,10 @@ class TestGetFrequencySpectrum:
369
383
  x = linspace(0, 2 * pi, n)
370
384
  noise = DEFAULT_RNG.normal(scale=0.25, size=n)
371
385
  y = x + noise
372
- y2 = filter_frequencies(y, lambda f: np.abs(f) <= 0.02)
386
+ y2 = adjust_frequencies(y, filters=lambda f: np.abs(f) <= 0.02)
373
387
  result = get_frequency_spectrum(y2)
374
388
  assert result.shape == (n, 2)
375
- assert np.allclose(result[result[:, 0] > 0.02, 1], 0.0)
389
+ assert np.allclose(result[np.abs(result[:, 0]) > 0.02, 1], 0.0)
376
390
 
377
391
 
378
392
  class TestHasDtype:
@@ -12,6 +12,7 @@ from typing import TYPE_CHECKING, Any, ClassVar, Literal, cast
12
12
  from uuid import UUID, uuid4
13
13
 
14
14
  import hypothesis.strategies
15
+ import numpy as np
15
16
  import polars as pl
16
17
  from hypothesis import given
17
18
  from hypothesis.strategies import (
@@ -26,6 +27,7 @@ from hypothesis.strategies import (
26
27
  sampled_from,
27
28
  timezones,
28
29
  )
30
+ from numpy import allclose, linspace, pi
29
31
  from polars import (
30
32
  Boolean,
31
33
  DataFrame,
@@ -60,6 +62,7 @@ from utilities.hypothesis import (
60
62
  zoned_datetimes,
61
63
  )
62
64
  from utilities.math import number_of_decimals
65
+ from utilities.numpy import DEFAULT_RNG
63
66
  from utilities.pathlib import PWD
64
67
  from utilities.polars import (
65
68
  AppendDataClassError,
@@ -104,6 +107,7 @@ from utilities.polars import (
104
107
  _InsertBetweenMissingColumnsError,
105
108
  _InsertBetweenNonConsecutiveError,
106
109
  _yield_struct_series_element_remove_nulls,
110
+ adjust_frequencies,
107
111
  append_dataclass,
108
112
  are_frames_equal,
109
113
  ceil_datetime,
@@ -113,6 +117,7 @@ from utilities.polars import (
113
117
  concat_series,
114
118
  convert_time_zone,
115
119
  cross,
120
+ cross_rolling_quantile,
116
121
  dataclass_to_dataframe,
117
122
  dataclass_to_schema,
118
123
  drop_null_struct_series,
@@ -121,6 +126,7 @@ from utilities.polars import (
121
126
  finite_ewm_mean,
122
127
  floor_datetime,
123
128
  get_data_type_or_series_time_zone,
129
+ get_frequency_spectrum,
124
130
  get_series_number_of_decimals,
125
131
  insert_after,
126
132
  insert_before,
@@ -162,6 +168,16 @@ if TYPE_CHECKING:
162
168
  from utilities.types import MaybeType, StrMapping, WeekDay
163
169
 
164
170
 
171
+ class TestAdjustFrequencies:
172
+ def test_main(self) -> None:
173
+ n = 1000
174
+ x = linspace(0, 2 * pi, n)
175
+ noise = DEFAULT_RNG.normal(scale=0.25, size=n)
176
+ y = Series(values=x + noise)
177
+ result = adjust_frequencies(y, filters=lambda f: np.abs(f) <= 0.02)
178
+ assert isinstance(result, Series)
179
+
180
+
165
181
  class TestAppendDataClass:
166
182
  @given(
167
183
  data=fixed_dictionaries({
@@ -661,6 +677,45 @@ class TestCrossOrTouch:
661
677
  assert_series_equal(result, expected)
662
678
 
663
679
 
680
+ class TestCrossRollingQuantile:
681
+ def test_main(self) -> None:
682
+ df = DataFrame(
683
+ data=[
684
+ (4, None, None),
685
+ (5, None, None),
686
+ (7, None, None),
687
+ (9, None, None),
688
+ (0, 5.0, False),
689
+ (1, 5.0, False),
690
+ (8, 7.0, True),
691
+ (9, 8.0, False),
692
+ (2, 2.0, False),
693
+ (3, 3.0, False),
694
+ ],
695
+ schema={"x": Int64, "median": Float64, "cross": Boolean},
696
+ orient="row",
697
+ )
698
+ assert_series_equal(
699
+ df["x"].rolling_quantile(0.5, window_size=5),
700
+ df["median"],
701
+ check_names=False,
702
+ )
703
+ assert_series_equal(
704
+ cross_rolling_quantile(df["x"], "up", 0.5, window_size=5),
705
+ df["cross"],
706
+ check_names=False,
707
+ )
708
+
709
+ def test_example(self) -> None:
710
+ close = Series(name="close", values=[8, 7, 8, 5, 0], dtype=Int64)
711
+ mid = Series(name="mid", values=[1, 2, 3, 4, 6], dtype=Int64)
712
+ result = cross(close, "down", mid).alias("result")
713
+ expected = Series(
714
+ name="result", values=[None, False, False, False, True], dtype=Boolean
715
+ )
716
+ assert_series_equal(result, expected)
717
+
718
+
664
719
  class TestDataClassToDataFrame:
665
720
  @given(data=data())
666
721
  def test_basic_type(self, *, data: DataObject) -> None:
@@ -1213,6 +1268,20 @@ class TestGetDataTypeOrSeriesTimeZone:
1213
1268
  _ = get_data_type_or_series_time_zone(Datetime)
1214
1269
 
1215
1270
 
1271
+ class TestGetFrequencySpectrum:
1272
+ def test_main(self) -> None:
1273
+ n = 1000
1274
+ x = linspace(0, 2 * pi, n)
1275
+ noise = DEFAULT_RNG.normal(scale=0.25, size=n)
1276
+ y = Series(x + noise)
1277
+ y2 = adjust_frequencies(y, filters=lambda f: np.abs(f) <= 0.02)
1278
+ result = get_frequency_spectrum(y2)
1279
+ check_polars_dataframe(
1280
+ result, height=n, schema_list={"frequency": Float64, "amplitude": Float64}
1281
+ )
1282
+ assert allclose(result.filter(col("frequency").abs() > 0.02)["amplitude"], 0.0)
1283
+
1284
+
1216
1285
  class TestGetSeriesNumberOfDecimals:
1217
1286
  @given(data=data(), n=hypothesis.strategies.integers(1, 10), nullable=booleans())
1218
1287
  def test_main(self, *, data: DataObject, n: int, nullable: bool) -> None:
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.109.17"
3
+ __version__ = "0.109.19"
@@ -16,11 +16,10 @@ from numpy import (
16
16
  errstate,
17
17
  exp,
18
18
  flatnonzero,
19
- float64,
20
19
  floating,
21
20
  full_like,
22
21
  inf,
23
- int64,
22
+ integer,
24
23
  isclose,
25
24
  isfinite,
26
25
  isinf,
@@ -39,11 +38,13 @@ from numpy.linalg import det, eig
39
38
  from numpy.random import default_rng
40
39
  from numpy.typing import NDArray
41
40
 
42
- from utilities.iterables import is_iterable_not_str
41
+ from utilities.iterables import always_iterable, is_iterable_not_str
43
42
 
44
43
  if TYPE_CHECKING:
45
44
  from collections.abc import Callable, Iterable
46
45
 
46
+ from utilities.types import MaybeIterable
47
+
47
48
 
48
49
  ##
49
50
 
@@ -89,8 +90,9 @@ timedelta64as = dtype("timedelta64[as]")
89
90
 
90
91
  NDArrayA = NDArray[Any]
91
92
  NDArrayB = NDArray[bool_]
92
- NDArrayF = NDArray[float64]
93
- NDArrayI = NDArray[int64]
93
+ NDArrayC128 = NDArray[complex128]
94
+ NDArrayF = NDArray[floating[Any]]
95
+ NDArrayI = NDArray[integer[Any]]
94
96
  NDArrayO = NDArray[object_]
95
97
 
96
98
 
@@ -135,7 +137,7 @@ class AsIntError(Exception): ...
135
137
 
136
138
 
137
139
  def boxcar(
138
- array: NDArray[floating[Any]],
140
+ array: NDArrayF,
139
141
  /,
140
142
  *,
141
143
  loc_low: float = -1.0,
@@ -144,7 +146,7 @@ def boxcar(
144
146
  slope_high: float = 1.0,
145
147
  rtol: float | None = None,
146
148
  atol: float | None = None,
147
- ) -> NDArray[floating[Any]]:
149
+ ) -> NDArrayF:
148
150
  """Construct a boxcar function."""
149
151
  if not is_at_most(loc_low, loc_high, rtol=rtol, atol=atol):
150
152
  raise _BoxCarLocationsError(low=loc_low, high=loc_high)
@@ -224,28 +226,43 @@ def fillna(array: NDArrayF, /, *, value: float = 0.0) -> NDArrayF:
224
226
  ##
225
227
 
226
228
 
227
- def filter_frequencies(
229
+ def adjust_frequencies(
228
230
  array: NDArrayF,
229
231
  /,
230
- *filters: Callable[[NDArray[floating[Any]]], NDArrayB],
232
+ *,
233
+ filters: MaybeIterable[Callable[[NDArrayF], NDArrayB]] | None = None,
234
+ weights: MaybeIterable[Callable[[NDArrayF], NDArrayF]] | None = None,
231
235
  d: int = 1,
232
236
  ) -> NDArrayF:
233
- """Filter an array by the frequencies of its FFT."""
237
+ """Adjust an array via its FFT frequencies."""
234
238
  (n,) = array.shape
235
- fft_vals = fft(array)
239
+ amplitudes = fft(array)
236
240
  freqs = fftfreq(n, d=d)
237
- reduced = reduce(partial(_filter_frequencies_one, freqs=freqs), filters, fft_vals)
238
- return ifft(reduced).real
241
+ if filters is not None:
242
+ amplitudes = reduce(
243
+ partial(_adjust_frequencies_filter_one, freqs=freqs),
244
+ always_iterable(filters),
245
+ amplitudes,
246
+ )
247
+ if weights is not None:
248
+ amplitudes = reduce(
249
+ partial(_adjust_frequencies_weight_one, freqs=freqs),
250
+ always_iterable(weights),
251
+ amplitudes,
252
+ )
253
+ return ifft(amplitudes).real
254
+
255
+
256
+ def _adjust_frequencies_filter_one(
257
+ acc: NDArrayC128, el: Callable[[NDArrayF], NDArrayB], /, *, freqs: NDArrayF
258
+ ) -> NDArrayC128:
259
+ return where(el(freqs), acc, 0.0)
239
260
 
240
261
 
241
- def _filter_frequencies_one(
242
- acc: NDArray[complex128],
243
- el: Callable[[NDArray[floating[Any]]], NDArrayB],
244
- /,
245
- *,
246
- freqs: NDArray[floating[Any]],
247
- ) -> NDArray[complex128]:
248
- return where(el(freqs), acc, 0.0)
262
+ def _adjust_frequencies_weight_one(
263
+ acc: NDArrayC128, el: Callable[[NDArrayF], NDArrayF], /, *, freqs: NDArrayF
264
+ ) -> NDArrayC128:
265
+ return acc * el(freqs)
249
266
 
250
267
 
251
268
  ##
@@ -284,12 +301,12 @@ class FlatN0MultipleError(FlatN0Error):
284
301
  ##
285
302
 
286
303
 
287
- def get_frequency_spectrum(array: NDArrayF, /, *, d: int = 1) -> NDArray[floating[Any]]:
304
+ def get_frequency_spectrum(array: NDArrayF, /, *, d: int = 1) -> NDArrayF:
288
305
  """Get the frequency spectrum."""
289
306
  (n,) = array.shape
290
- fft_vals = fft(array)
307
+ amplitudes = fft(array)
291
308
  freqs = fftfreq(n, d=d)
292
- amplitudes = np.abs(fft_vals)
309
+ amplitudes = np.abs(amplitudes)
293
310
  data = np.hstack([freqs.reshape(-1, 1), amplitudes.reshape(-1, 1)])
294
311
  return data[argsort(data[:, 0])]
295
312
 
@@ -908,14 +925,14 @@ def shift_bool(
908
925
 
909
926
 
910
927
  def sigmoid(
911
- array: NDArray[floating[Any]],
928
+ array: NDArrayF,
912
929
  /,
913
930
  *,
914
931
  loc: float = 0.0,
915
932
  slope: float = 1.0,
916
933
  rtol: float | None = None,
917
934
  atol: float | None = None,
918
- ) -> NDArray[floating[Any]]:
935
+ ) -> NDArrayF:
919
936
  """Construct a sigmoid function."""
920
937
  if is_zero(slope, rtol=rtol, atol=atol):
921
938
  raise SigmoidError
@@ -965,6 +982,7 @@ __all__ = [
965
982
  "NDArrayO",
966
983
  "ShiftError",
967
984
  "SigmoidError",
985
+ "adjust_frequencies",
968
986
  "array_indexer",
969
987
  "as_int",
970
988
  "boxcar",
@@ -983,7 +1001,6 @@ __all__ = [
983
1001
  "datetime64us",
984
1002
  "discretize",
985
1003
  "fillna",
986
- "filter_frequencies",
987
1004
  "flatn0",
988
1005
  "get_frequency_spectrum",
989
1006
  "has_dtype",
@@ -115,10 +115,12 @@ if TYPE_CHECKING:
115
115
  JoinStrategy, # pyright: ignore[reportPrivateImportUsage]
116
116
  JoinValidation, # pyright: ignore[reportPrivateImportUsage]
117
117
  PolarsDataType, # pyright: ignore[reportPrivateImportUsage]
118
+ RollingInterpolationMethod, # pyright: ignore[reportPrivateImportUsage]
118
119
  SchemaDict, # pyright: ignore[reportPrivateImportUsage]
119
120
  TimeUnit, # pyright: ignore[reportPrivateImportUsage]
120
121
  )
121
122
 
123
+ from utilities.numpy import NDArrayB, NDArrayF
122
124
  from utilities.types import (
123
125
  Dataclass,
124
126
  MaybeIterable,
@@ -141,6 +143,27 @@ _FINITE_EWM_MIN_WEIGHT = 0.9999
141
143
  ##
142
144
 
143
145
 
146
+ def adjust_frequencies(
147
+ series: Series,
148
+ /,
149
+ *,
150
+ filters: MaybeIterable[Callable[[NDArrayF], NDArrayB]] | None = None,
151
+ weights: MaybeIterable[Callable[[NDArrayF], NDArrayF]] | None = None,
152
+ d: int = 1,
153
+ ) -> Series:
154
+ """Adjust a Series via its FFT frequencies."""
155
+ import utilities.numpy
156
+
157
+ array = series.to_numpy()
158
+ adjusted = utilities.numpy.adjust_frequencies(
159
+ array, filters=filters, weights=weights, d=d
160
+ )
161
+ return Series(name=series.name, values=adjusted, dtype=Float64)
162
+
163
+
164
+ ##
165
+
166
+
144
167
  def append_dataclass(df: DataFrame, obj: Dataclass, /) -> DataFrame:
145
168
  """Append a dataclass object to a DataFrame."""
146
169
  non_null_fields = {k: v for k, v in asdict(obj).items() if v is not None}
@@ -658,6 +681,73 @@ def _cross_or_touch(
658
681
  ##
659
682
 
660
683
 
684
+ @overload
685
+ def cross_rolling_quantile(
686
+ expr: ExprLike,
687
+ up_or_down: Literal["up", "down"],
688
+ quantile: float,
689
+ /,
690
+ *,
691
+ interpolation: RollingInterpolationMethod = "nearest",
692
+ window_size: int = 2,
693
+ weights: list[float] | None = None,
694
+ min_samples: int | None = None,
695
+ center: bool = False,
696
+ ) -> Expr: ...
697
+ @overload
698
+ def cross_rolling_quantile(
699
+ expr: Series,
700
+ up_or_down: Literal["up", "down"],
701
+ quantile: float,
702
+ /,
703
+ *,
704
+ interpolation: RollingInterpolationMethod = "nearest",
705
+ window_size: int = 2,
706
+ weights: list[float] | None = None,
707
+ min_samples: int | None = None,
708
+ center: bool = False,
709
+ ) -> Series: ...
710
+ @overload
711
+ def cross_rolling_quantile(
712
+ expr: IntoExprColumn,
713
+ up_or_down: Literal["up", "down"],
714
+ quantile: float,
715
+ /,
716
+ *,
717
+ interpolation: RollingInterpolationMethod = "nearest",
718
+ window_size: int = 2,
719
+ weights: list[float] | None = None,
720
+ min_samples: int | None = None,
721
+ center: bool = False,
722
+ ) -> Expr | Series: ...
723
+ def cross_rolling_quantile(
724
+ expr: IntoExprColumn,
725
+ up_or_down: Literal["up", "down"],
726
+ quantile: float,
727
+ /,
728
+ *,
729
+ interpolation: RollingInterpolationMethod = "nearest",
730
+ window_size: int = 2,
731
+ weights: list[float] | None = None,
732
+ min_samples: int | None = None,
733
+ center: bool = False,
734
+ ) -> Expr | Series:
735
+ """Compute when a column crosses its rolling quantile."""
736
+ expr = ensure_expr_or_series(expr)
737
+ rolling = expr.rolling_quantile(
738
+ quantile,
739
+ interpolation=interpolation,
740
+ window_size=window_size,
741
+ weights=weights,
742
+ min_samples=min_samples,
743
+ center=center,
744
+ )
745
+ return cross(expr, up_or_down, rolling)
746
+
747
+
748
+ ##
749
+
750
+
661
751
  def dataclass_to_dataframe(
662
752
  objs: MaybeIterable[Dataclass],
663
753
  /,
@@ -1027,6 +1117,20 @@ class _GetDataTypeOrSeriesTimeZoneNotZonedError(GetDataTypeOrSeriesTimeZoneError
1027
1117
  ##
1028
1118
 
1029
1119
 
1120
+ def get_frequency_spectrum(series: Series, /, *, d: int = 1) -> DataFrame:
1121
+ """Get the frequency spectrum."""
1122
+ import utilities.numpy
1123
+
1124
+ array = series.to_numpy()
1125
+ spectrum = utilities.numpy.get_frequency_spectrum(array, d=d)
1126
+ return DataFrame(
1127
+ data=spectrum, schema={"frequency": Float64, "amplitude": Float64}, orient="row"
1128
+ )
1129
+
1130
+
1131
+ ##
1132
+
1133
+
1030
1134
  @overload
1031
1135
  def get_series_number_of_decimals(
1032
1136
  series: Series, /, *, nullable: Literal[True]
@@ -1736,6 +1840,7 @@ __all__ = [
1736
1840
  "SetFirstRowAsColumnsError",
1737
1841
  "StructFromDataClassError",
1738
1842
  "YieldStructSeriesElementsError",
1843
+ "adjust_frequencies",
1739
1844
  "append_dataclass",
1740
1845
  "are_frames_equal",
1741
1846
  "ceil_datetime",
@@ -1753,6 +1858,7 @@ __all__ = [
1753
1858
  "finite_ewm_mean",
1754
1859
  "floor_datetime",
1755
1860
  "get_data_type_or_series_time_zone",
1861
+ "get_frequency_spectrum",
1756
1862
  "get_series_number_of_decimals",
1757
1863
  "insert_after",
1758
1864
  "insert_before",
@@ -10,7 +10,9 @@ from utilities.functions import is_sequence_of
10
10
  from utilities.polars import concat_series, ensure_expr_or_series
11
11
 
12
12
  if TYPE_CHECKING:
13
- from polars._typing import IntoExprColumn
13
+ from polars._typing import (
14
+ IntoExprColumn, # pyright: ignore[reportPrivateImportUsage]
15
+ )
14
16
  from polars_ols import NullPolicy
15
17
 
16
18
  from utilities.polars import ExprLike