├── .benchmarks └── Darwin-CPython-3.12-64bit │ └── 0001_f2137eaf44442f4bc1c79ab517528d6e70ce22fc_20240920_165136_uncommited-changes.json ├── .github └── workflows │ ├── ci.yml │ ├── codecov.yml │ └── codspeed.yml ├── .gitignore ├── .pre-commit-config.yaml ├── Cargo.lock ├── Cargo.toml ├── Makefile ├── README.md ├── polars_trading ├── __init__.py ├── _internal.pyi ├── _testing │ ├── __init__.py │ ├── data.py │ ├── features.py │ └── labels.py ├── _utils.py ├── bars.py ├── features │ ├── __init__.py │ └── frac_diff.py ├── labels │ ├── __init__.py │ ├── dynamic_labels.py │ └── labels.py ├── py.typed └── typing.py ├── pyproject.toml ├── requirements.txt ├── rustfmt.toml ├── src ├── bars.rs ├── frac_diff.rs ├── labels.rs └── lib.rs ├── tests ├── conftest.py ├── features │ └── test_frac_diff.py ├── labels │ ├── test_dynamic_labels.py │ └── test_labels.py ├── test__utils.py └── test_bars.py └── uv.lock /.benchmarks/Darwin-CPython-3.12-64bit/0001_f2137eaf44442f4bc1c79ab517528d6e70ce22fc_20240920_165136_uncommited-changes.json: -------------------------------------------------------------------------------- 1 | { 2 | "machine_info": { 3 | "node": "MacBook-Pro-4.local", 4 | "processor": "arm", 5 | "machine": "arm64", 6 | "python_compiler": "Clang 15.0.0 (clang-1500.3.9.4)", 7 | "python_implementation": "CPython", 8 | "python_implementation_version": "3.12.5", 9 | "python_version": "3.12.5", 10 | "python_build": [ 11 | "main", 12 | "Aug 6 2024 19:08:49" 13 | ], 14 | "release": "23.2.0", 15 | "system": "Darwin", 16 | "cpu": { 17 | "python_version": "3.12.5.final.0 (64 bit)", 18 | "cpuinfo_version": [ 19 | 9, 20 | 0, 21 | 0 22 | ], 23 | "cpuinfo_version_string": "9.0.0", 24 | "arch": "ARM_8", 25 | "bits": 64, 26 | "count": 12, 27 | "arch_string_raw": "arm64", 28 | "brand_raw": "Apple M3 Pro" 29 | } 30 | }, 31 | "commit_info": { 32 | "id": "f2137eaf44442f4bc1c79ab517528d6e70ce22fc", 33 | "time": "2024-09-20T05:50:37-06:00", 34 | "author_time": "2024-09-20T05:50:37-06:00", 35 | "dirty": true, 36 | "project": "polars-finance", 37 | "branch": "feat/pandas-triple-barrier" 38 | }, 39 | "benchmarks": [ 40 | { 41 | "group": "daily_vol", 42 | "name": "test__daily_vol__polars_benchmark[trade_data0]", 43 | "fullname": "tests/labels/test_dynamic_labels.py::test__daily_vol__polars_benchmark[trade_data0]", 44 | "params": { 45 | "trade_data": { 46 | "n_rows": 10000, 47 | "n_companies": 3 48 | } 49 | }, 50 | "param": "trade_data0", 51 | "extra_info": {}, 52 | "options": { 53 | "disable_gc": false, 54 | "timer": "perf_counter", 55 | "min_rounds": 5, 56 | "max_time": 1.0, 57 | "min_time": 5e-06, 58 | "warmup": false 59 | }, 60 | "stats": { 61 | "min": 0.0008518749382346869, 62 | "max": 0.0015520418528467417, 63 | "mean": 0.0011004127622504837, 64 | "stddev": 9.694317081710826e-05, 65 | "rounds": 362, 66 | "median": 0.0010951249860227108, 67 | "iqr": 0.00013275002129375935, 68 | "q1": 0.001035457942634821, 69 | "q3": 0.0011682079639285803, 70 | "iqr_outliers": 1, 71 | "stddev_outliers": 106, 72 | "outliers": "106;1", 73 | "ld15iqr": 0.0008518749382346869, 74 | "hd15iqr": 0.0015520418528467417, 75 | "ops": 908.7499112195619, 76 | "total": 0.3983494199346751, 77 | "iterations": 1 78 | } 79 | }, 80 | { 81 | "group": "daily_vol", 82 | "name": "test__daily_vol__polars_benchmark[trade_data1]", 83 | "fullname": "tests/labels/test_dynamic_labels.py::test__daily_vol__polars_benchmark[trade_data1]", 84 | "params": { 85 | "trade_data": { 86 | "n_rows": 100000, 87 | "n_companies": 5 88 | } 89 | }, 90 | "param": "trade_data1", 91 | "extra_info": {}, 92 | "options": { 93 | "disable_gc": false, 94 | "timer": "perf_counter", 95 | "min_rounds": 5, 96 | "max_time": 1.0, 97 | "min_time": 5e-06, 98 | "warmup": false 99 | }, 100 | "stats": { 101 | "min": 0.004835666157305241, 102 | "max": 0.006815832806751132, 103 | "mean": 0.0054197329263300145, 104 | "stddev": 0.00026706212076531386, 105 | "rounds": 134, 106 | "median": 0.005401999922469258, 107 | "iqr": 0.00025116605684161186, 108 | "q1": 0.0052685418631881475, 109 | "q3": 0.005519707920029759, 110 | "iqr_outliers": 8, 111 | "stddev_outliers": 33, 112 | "outliers": "33;8", 113 | "ld15iqr": 0.004964167019352317, 114 | "hd15iqr": 0.005952165927737951, 115 | "ops": 184.51093690278063, 116 | "total": 0.726244212128222, 117 | "iterations": 1 118 | } 119 | }, 120 | { 121 | "group": "daily_vol", 122 | "name": "test__daily_vol__polars_benchmark[trade_data2]", 123 | "fullname": "tests/labels/test_dynamic_labels.py::test__daily_vol__polars_benchmark[trade_data2]", 124 | "params": { 125 | "trade_data": { 126 | "n_rows": 1000000, 127 | "n_companies": 10 128 | } 129 | }, 130 | "param": "trade_data2", 131 | "extra_info": {}, 132 | "options": { 133 | "disable_gc": false, 134 | "timer": "perf_counter", 135 | "min_rounds": 5, 136 | "max_time": 1.0, 137 | "min_time": 5e-06, 138 | "warmup": false 139 | }, 140 | "stats": { 141 | "min": 0.06569054210558534, 142 | "max": 0.07898629107512534, 143 | "mean": 0.07163801177271775, 144 | "stddev": 0.004717184630955575, 145 | "rounds": 7, 146 | "median": 0.07001666608266532, 147 | "iqr": 0.0071938763139769435, 148 | "q1": 0.06812085350975394, 149 | "q3": 0.07531472982373089, 150 | "iqr_outliers": 0, 151 | "stddev_outliers": 2, 152 | "outliers": "2;0", 153 | "ld15iqr": 0.06569054210558534, 154 | "hd15iqr": 0.07898629107512534, 155 | "ops": 13.959069706912704, 156 | "total": 0.5014660824090242, 157 | "iterations": 1 158 | } 159 | }, 160 | { 161 | "group": "time_bars", 162 | "name": "test__time_bars__polars_benchmark[trade_data0]", 163 | "fullname": "tests/test_bars.py::test__time_bars__polars_benchmark[trade_data0]", 164 | "params": { 165 | "trade_data": { 166 | "n_rows": 1000, 167 | "n_companies": 3 168 | } 169 | }, 170 | "param": "trade_data0", 171 | "extra_info": {}, 172 | "options": { 173 | "disable_gc": false, 174 | "timer": "perf_counter", 175 | "min_rounds": 5, 176 | "max_time": 1.0, 177 | "min_time": 5e-06, 178 | "warmup": false 179 | }, 180 | "stats": { 181 | "min": 0.0003788750618696213, 182 | "max": 0.0010135411284863949, 183 | "mean": 0.0005729989761879363, 184 | "stddev": 0.00010006917725372432, 185 | "rounds": 849, 186 | "median": 0.0005550829228013754, 187 | "iqr": 0.00014642783207818866, 188 | "q1": 0.0004942601080983877, 189 | "q3": 0.0006406879401765764, 190 | "iqr_outliers": 5, 191 | "stddev_outliers": 263, 192 | "outliers": "263;5", 193 | "ld15iqr": 0.0003788750618696213, 194 | "hd15iqr": 0.0008626659400761127, 195 | "ops": 1745.2038163363366, 196 | "total": 0.4864761307835579, 197 | "iterations": 1 198 | } 199 | }, 200 | { 201 | "group": "time_bars", 202 | "name": "test__time_bars__polars_benchmark[trade_data1]", 203 | "fullname": "tests/test_bars.py::test__time_bars__polars_benchmark[trade_data1]", 204 | "params": { 205 | "trade_data": { 206 | "n_rows": 10000, 207 | "n_companies": 3 208 | } 209 | }, 210 | "param": "trade_data1", 211 | "extra_info": {}, 212 | "options": { 213 | "disable_gc": false, 214 | "timer": "perf_counter", 215 | "min_rounds": 5, 216 | "max_time": 1.0, 217 | "min_time": 5e-06, 218 | "warmup": false 219 | }, 220 | "stats": { 221 | "min": 0.0006168750114738941, 222 | "max": 0.0010418749880045652, 223 | "mean": 0.0007620256526985419, 224 | "stddev": 5.687672825014427e-05, 225 | "rounds": 1276, 226 | "median": 0.0007594794733449817, 227 | "iqr": 7.489509880542755e-05, 228 | "q1": 0.000722396420314908, 229 | "q3": 0.0007972915191203356, 230 | "iqr_outliers": 17, 231 | "stddev_outliers": 384, 232 | "outliers": "384;17", 233 | "ld15iqr": 0.0006168750114738941, 234 | "hd15iqr": 0.000910458154976368, 235 | "ops": 1312.29177975666, 236 | "total": 0.9723447328433394, 237 | "iterations": 1 238 | } 239 | }, 240 | { 241 | "group": "time_bars", 242 | "name": "test__time_bars__polars_benchmark[trade_data2]", 243 | "fullname": "tests/test_bars.py::test__time_bars__polars_benchmark[trade_data2]", 244 | "params": { 245 | "trade_data": { 246 | "n_rows": 1000000, 247 | "n_companies": 20 248 | } 249 | }, 250 | "param": "trade_data2", 251 | "extra_info": {}, 252 | "options": { 253 | "disable_gc": false, 254 | "timer": "perf_counter", 255 | "min_rounds": 5, 256 | "max_time": 1.0, 257 | "min_time": 5e-06, 258 | "warmup": false 259 | }, 260 | "stats": { 261 | "min": 0.019815375097095966, 262 | "max": 0.02876037498936057, 263 | "mean": 0.021518070207859733, 264 | "stddev": 0.0014444191549200683, 265 | "rounds": 38, 266 | "median": 0.021403937600553036, 267 | "iqr": 0.001104332972317934, 268 | "q1": 0.020702874986454844, 269 | "q3": 0.02180720795877278, 270 | "iqr_outliers": 2, 271 | "stddev_outliers": 4, 272 | "outliers": "4;2", 273 | "ld15iqr": 0.019815375097095966, 274 | "hd15iqr": 0.023794875014573336, 275 | "ops": 46.47256888467341, 276 | "total": 0.8176866678986698, 277 | "iterations": 1 278 | } 279 | }, 280 | { 281 | "group": "tick_bars", 282 | "name": "test__tick_bars__polars_benchmark[trade_data0]", 283 | "fullname": "tests/test_bars.py::test__tick_bars__polars_benchmark[trade_data0]", 284 | "params": { 285 | "trade_data": { 286 | "n_rows": 1000, 287 | "n_companies": 3 288 | } 289 | }, 290 | "param": "trade_data0", 291 | "extra_info": {}, 292 | "options": { 293 | "disable_gc": false, 294 | "timer": "perf_counter", 295 | "min_rounds": 5, 296 | "max_time": 1.0, 297 | "min_time": 5e-06, 298 | "warmup": false 299 | }, 300 | "stats": { 301 | "min": 0.0007745828479528427, 302 | "max": 0.001545500010251999, 303 | "mean": 0.0010984447373344113, 304 | "stddev": 0.000113852042941398, 305 | "rounds": 712, 306 | "median": 0.0010957710910588503, 307 | "iqr": 0.00014785502571612597, 308 | "q1": 0.0010244580917060375, 309 | "q3": 0.0011723131174221635, 310 | "iqr_outliers": 5, 311 | "stddev_outliers": 219, 312 | "outliers": "219;5", 313 | "ld15iqr": 0.0008159170392900705, 314 | "hd15iqr": 0.0014616248663514853, 315 | "ops": 910.378070021705, 316 | "total": 0.7820926529821008, 317 | "iterations": 1 318 | } 319 | }, 320 | { 321 | "group": "tick_bars", 322 | "name": "test__tick_bars__polars_benchmark[trade_data1]", 323 | "fullname": "tests/test_bars.py::test__tick_bars__polars_benchmark[trade_data1]", 324 | "params": { 325 | "trade_data": { 326 | "n_rows": 10000, 327 | "n_companies": 3 328 | } 329 | }, 330 | "param": "trade_data1", 331 | "extra_info": {}, 332 | "options": { 333 | "disable_gc": false, 334 | "timer": "perf_counter", 335 | "min_rounds": 5, 336 | "max_time": 1.0, 337 | "min_time": 5e-06, 338 | "warmup": false 339 | }, 340 | "stats": { 341 | "min": 0.0013206249568611383, 342 | "max": 0.002115708077326417, 343 | "mean": 0.0017051144155799155, 344 | "stddev": 0.00012526637504000065, 345 | "rounds": 527, 346 | "median": 0.001703500049188733, 347 | "iqr": 0.00015246961265802383, 348 | "q1": 0.0016227704472839832, 349 | "q3": 0.001775240059942007, 350 | "iqr_outliers": 13, 351 | "stddev_outliers": 159, 352 | "outliers": "159;13", 353 | "ld15iqr": 0.001407291041687131, 354 | "hd15iqr": 0.002016040962189436, 355 | "ops": 586.4709082644736, 356 | "total": 0.8985952970106155, 357 | "iterations": 1 358 | } 359 | }, 360 | { 361 | "group": "tick_bars", 362 | "name": "test__tick_bars__polars_benchmark[trade_data2]", 363 | "fullname": "tests/test_bars.py::test__tick_bars__polars_benchmark[trade_data2]", 364 | "params": { 365 | "trade_data": { 366 | "n_rows": 1000000, 367 | "n_companies": 10 368 | } 369 | }, 370 | "param": "trade_data2", 371 | "extra_info": {}, 372 | "options": { 373 | "disable_gc": false, 374 | "timer": "perf_counter", 375 | "min_rounds": 5, 376 | "max_time": 1.0, 377 | "min_time": 5e-06, 378 | "warmup": false 379 | }, 380 | "stats": { 381 | "min": 0.033509374829009175, 382 | "max": 0.03557691699825227, 383 | "mean": 0.034498987133325686, 384 | "stddev": 0.0005490550532409403, 385 | "rounds": 29, 386 | "median": 0.034530041040852666, 387 | "iqr": 0.0006634583696722984, 388 | "q1": 0.03415980190038681, 389 | "q3": 0.03482326027005911, 390 | "iqr_outliers": 0, 391 | "stddev_outliers": 10, 392 | "outliers": "10;0", 393 | "ld15iqr": 0.033509374829009175, 394 | "hd15iqr": 0.03557691699825227, 395 | "ops": 28.986358241051363, 396 | "total": 1.000470626866445, 397 | "iterations": 1 398 | } 399 | }, 400 | { 401 | "group": "volume_bars", 402 | "name": "test__volume_bars__polars_benchmark[trade_data0]", 403 | "fullname": "tests/test_bars.py::test__volume_bars__polars_benchmark[trade_data0]", 404 | "params": { 405 | "trade_data": { 406 | "n_rows": 1000, 407 | "n_companies": 3 408 | } 409 | }, 410 | "param": "trade_data0", 411 | "extra_info": {}, 412 | "options": { 413 | "disable_gc": false, 414 | "timer": "perf_counter", 415 | "min_rounds": 5, 416 | "max_time": 1.0, 417 | "min_time": 5e-06, 418 | "warmup": false 419 | }, 420 | "stats": { 421 | "min": 0.001798124983906746, 422 | "max": 0.0026017078198492527, 423 | "mean": 0.002103642488957053, 424 | "stddev": 0.00013445729744066096, 425 | "rounds": 322, 426 | "median": 0.002093917108140886, 427 | "iqr": 0.00017579179257154465, 428 | "q1": 0.002007625065743923, 429 | "q3": 0.002183416858315468, 430 | "iqr_outliers": 6, 431 | "stddev_outliers": 96, 432 | "outliers": "96;6", 433 | "ld15iqr": 0.001798124983906746, 434 | "hd15iqr": 0.0024874170776456594, 435 | "ops": 475.3659451401276, 436 | "total": 0.6773728814441711, 437 | "iterations": 1 438 | } 439 | }, 440 | { 441 | "group": "volume_bars", 442 | "name": "test__volume_bars__polars_benchmark[trade_data1]", 443 | "fullname": "tests/test_bars.py::test__volume_bars__polars_benchmark[trade_data1]", 444 | "params": { 445 | "trade_data": { 446 | "n_rows": 10000, 447 | "n_companies": 3 448 | } 449 | }, 450 | "param": "trade_data1", 451 | "extra_info": {}, 452 | "options": { 453 | "disable_gc": false, 454 | "timer": "perf_counter", 455 | "min_rounds": 5, 456 | "max_time": 1.0, 457 | "min_time": 5e-06, 458 | "warmup": false 459 | }, 460 | "stats": { 461 | "min": 0.003117708023637533, 462 | "max": 0.0040478750597685575, 463 | "mean": 0.003661660312855538, 464 | "stddev": 0.00016513581523498156, 465 | "rounds": 263, 466 | "median": 0.003661041846498847, 467 | "iqr": 0.00023841665824875236, 468 | "q1": 0.003544145729392767, 469 | "q3": 0.0037825623876415193, 470 | "iqr_outliers": 1, 471 | "stddev_outliers": 92, 472 | "outliers": "92;1", 473 | "ld15iqr": 0.0032709159422665834, 474 | "hd15iqr": 0.0040478750597685575, 475 | "ops": 273.1001552735928, 476 | "total": 0.9630166622810066, 477 | "iterations": 1 478 | } 479 | }, 480 | { 481 | "group": "volume_bars", 482 | "name": "test__volume_bars__polars_benchmark[trade_data2]", 483 | "fullname": "tests/test_bars.py::test__volume_bars__polars_benchmark[trade_data2]", 484 | "params": { 485 | "trade_data": { 486 | "n_rows": 1000000, 487 | "n_companies": 10 488 | } 489 | }, 490 | "param": "trade_data2", 491 | "extra_info": {}, 492 | "options": { 493 | "disable_gc": false, 494 | "timer": "perf_counter", 495 | "min_rounds": 5, 496 | "max_time": 1.0, 497 | "min_time": 5e-06, 498 | "warmup": false 499 | }, 500 | "stats": { 501 | "min": 0.1190591671038419, 502 | "max": 0.1266824589110911, 503 | "mean": 0.12282050534849986, 504 | "stddev": 0.0021960235564076037, 505 | "rounds": 8, 506 | "median": 0.12317345850169659, 507 | "iqr": 0.0018020010320469737, 508 | "q1": 0.1217178744263947, 509 | "q3": 0.12351987545844167, 510 | "iqr_outliers": 1, 511 | "stddev_outliers": 2, 512 | "outliers": "2;1", 513 | "ld15iqr": 0.1190591671038419, 514 | "hd15iqr": 0.1266824589110911, 515 | "ops": 8.141962917043266, 516 | "total": 0.9825640427879989, 517 | "iterations": 1 518 | } 519 | }, 520 | { 521 | "group": "dollar_bars", 522 | "name": "test__dollar_bars__polars_benchmark[trade_data0]", 523 | "fullname": "tests/test_bars.py::test__dollar_bars__polars_benchmark[trade_data0]", 524 | "params": { 525 | "trade_data": { 526 | "n_rows": 1000, 527 | "n_companies": 3 528 | } 529 | }, 530 | "param": "trade_data0", 531 | "extra_info": {}, 532 | "options": { 533 | "disable_gc": false, 534 | "timer": "perf_counter", 535 | "min_rounds": 5, 536 | "max_time": 1.0, 537 | "min_time": 5e-06, 538 | "warmup": false 539 | }, 540 | "stats": { 541 | "min": 0.001833832822740078, 542 | "max": 0.002633583964779973, 543 | "mean": 0.0021860578263961997, 544 | "stddev": 0.00013788928468163358, 545 | "rounds": 397, 546 | "median": 0.0021704998798668385, 547 | "iqr": 0.0001777080469764769, 548 | "q1": 0.0020923858392052352, 549 | "q3": 0.002270093886181712, 550 | "iqr_outliers": 3, 551 | "stddev_outliers": 130, 552 | "outliers": "130;3", 553 | "ld15iqr": 0.001833832822740078, 554 | "hd15iqr": 0.002547207986935973, 555 | "ops": 457.4444408218324, 556 | "total": 0.8678649570792913, 557 | "iterations": 1 558 | } 559 | }, 560 | { 561 | "group": "dollar_bars", 562 | "name": "test__dollar_bars__polars_benchmark[trade_data1]", 563 | "fullname": "tests/test_bars.py::test__dollar_bars__polars_benchmark[trade_data1]", 564 | "params": { 565 | "trade_data": { 566 | "n_rows": 10000, 567 | "n_companies": 3 568 | } 569 | }, 570 | "param": "trade_data1", 571 | "extra_info": {}, 572 | "options": { 573 | "disable_gc": false, 574 | "timer": "perf_counter", 575 | "min_rounds": 5, 576 | "max_time": 1.0, 577 | "min_time": 5e-06, 578 | "warmup": false 579 | }, 580 | "stats": { 581 | "min": 0.003399582812562585, 582 | "max": 0.004201542120426893, 583 | "mean": 0.0037548097376914127, 584 | "stddev": 0.00016368041006722573, 585 | "rounds": 230, 586 | "median": 0.0037463546032086015, 587 | "iqr": 0.00020579202100634575, 588 | "q1": 0.003648167010396719, 589 | "q3": 0.0038539590314030647, 590 | "iqr_outliers": 4, 591 | "stddev_outliers": 73, 592 | "outliers": "73;4", 593 | "ld15iqr": 0.003399582812562585, 594 | "hd15iqr": 0.004166333936154842, 595 | "ops": 266.32507899450445, 596 | "total": 0.8636062396690249, 597 | "iterations": 1 598 | } 599 | }, 600 | { 601 | "group": "dollar_bars", 602 | "name": "test__dollar_bars__polars_benchmark[trade_data2]", 603 | "fullname": "tests/test_bars.py::test__dollar_bars__polars_benchmark[trade_data2]", 604 | "params": { 605 | "trade_data": { 606 | "n_rows": 1000000, 607 | "n_companies": 10 608 | } 609 | }, 610 | "param": "trade_data2", 611 | "extra_info": {}, 612 | "options": { 613 | "disable_gc": false, 614 | "timer": "perf_counter", 615 | "min_rounds": 5, 616 | "max_time": 1.0, 617 | "min_time": 5e-06, 618 | "warmup": false 619 | }, 620 | "stats": { 621 | "min": 0.1228118329308927, 622 | "max": 0.1324748748447746, 623 | "mean": 0.12721897393930703, 624 | "stddev": 0.002710620732647333, 625 | "rounds": 8, 626 | "median": 0.12719714548438787, 627 | "iqr": 0.0018838954856619239, 628 | "q1": 0.12607575044967234, 629 | "q3": 0.12795964593533427, 630 | "iqr_outliers": 2, 631 | "stddev_outliers": 2, 632 | "outliers": "2;2", 633 | "ld15iqr": 0.1255003339610994, 634 | "hd15iqr": 0.1324748748447746, 635 | "ops": 7.860462704856233, 636 | "total": 1.0177517915144563, 637 | "iterations": 1 638 | } 639 | } 640 | ], 641 | "datetime": "2024-09-20T16:52:06.642417", 642 | "version": "4.0.0" 643 | } -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: 3 | push: 4 | branches: 5 | - "**" 6 | tags-ignore: 7 | - "**" 8 | jobs: 9 | lint: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Install uv 16 | uses: astral-sh/setup-uv@v2 17 | 18 | - name: Set up Python 19 | run: uv python install 20 | 21 | - name: Install the project 22 | run: uv sync --only-dev 23 | 24 | - name: Run Ruff 25 | run: uv run ruff check --output-format=github . 26 | -------------------------------------------------------------------------------- /.github/workflows/codecov.yml: -------------------------------------------------------------------------------- 1 | name: Test & Code Coverage 2 | 3 | on: push 4 | 5 | jobs: 6 | test: 7 | name: Run tests and collect coverage 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | 12 | - name: Install uv 13 | uses: astral-sh/setup-uv@v2 14 | 15 | - name: Set up Python 16 | run: uv python install 17 | 18 | - name: Install the project 19 | run: uv sync --all-extras --dev 20 | 21 | - name: Run tests 22 | run: uv run pytest --cov-report=xml 23 | 24 | - name: Upload results to Codecov 25 | uses: codecov/codecov-action@v4 26 | with: 27 | token: ${{ secrets.CODECOV_TOKEN }} 28 | -------------------------------------------------------------------------------- /.github/workflows/codspeed.yml: -------------------------------------------------------------------------------- 1 | name: codspeed-benchmarks 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" # or "master" 7 | pull_request: 8 | # `workflow_dispatch` allows CodSpeed to trigger backtest 9 | # performance analysis in order to generate initial data. 10 | workflow_dispatch: 11 | 12 | env: 13 | UV_SYSTEM_PYTHON: 1 14 | 15 | jobs: 16 | benchmarks: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | 21 | - name: Install uv 22 | uses: astral-sh/setup-uv@v2 23 | 24 | - name: "Set up Python" 25 | uses: actions/setup-python@v5 26 | with: 27 | python-version-file: "pyproject.toml" 28 | 29 | - name: Install the project 30 | run: uv sync --all-extras --dev 31 | 32 | - name: Run benchmarks 33 | uses: CodSpeedHQ/action@v3 34 | with: 35 | token: ${{ secrets.CODSPEED_TOKEN }} 36 | run: uv run pytest --codspeed 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.so 2 | *.pyc 3 | target 4 | venv 5 | .venv 6 | *.so 7 | *.dll 8 | *.pyd 9 | .hypothesis/ 10 | .pytest_cache/ 11 | .ruff_cache/ 12 | __pycache__/ 13 | data/ 14 | .DS_Store 15 | scratchpad.py 16 | .coverage* 17 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.6.0 4 | hooks: 5 | - id: check-ast 6 | - id: check-toml 7 | - id: trailing-whitespace 8 | - repo: https://github.com/charliermarsh/ruff-pre-commit 9 | rev: v0.6.4 10 | hooks: 11 | - id: ruff 12 | exclude: ^tests/ 13 | args: [--fix, --exit-non-zero-on-fix] 14 | - id: ruff-format 15 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "ahash" 22 | version = "0.8.11" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 25 | dependencies = [ 26 | "cfg-if", 27 | "getrandom", 28 | "once_cell", 29 | "version_check", 30 | "zerocopy", 31 | ] 32 | 33 | [[package]] 34 | name = "aho-corasick" 35 | version = "1.1.3" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 38 | dependencies = [ 39 | "memchr", 40 | ] 41 | 42 | [[package]] 43 | name = "alloc-no-stdlib" 44 | version = "2.0.4" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 47 | 48 | [[package]] 49 | name = "alloc-stdlib" 50 | version = "0.2.2" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 53 | dependencies = [ 54 | "alloc-no-stdlib", 55 | ] 56 | 57 | [[package]] 58 | name = "allocator-api2" 59 | version = "0.2.18" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" 62 | 63 | [[package]] 64 | name = "android-tzdata" 65 | version = "0.1.1" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 68 | 69 | [[package]] 70 | name = "android_system_properties" 71 | version = "0.1.5" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 74 | dependencies = [ 75 | "libc", 76 | ] 77 | 78 | [[package]] 79 | name = "argminmax" 80 | version = "0.6.2" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "52424b59d69d69d5056d508b260553afd91c57e21849579cd1f50ee8b8b88eaa" 83 | dependencies = [ 84 | "num-traits", 85 | ] 86 | 87 | [[package]] 88 | name = "array-init-cursor" 89 | version = "0.2.0" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "bf7d0a018de4f6aa429b9d33d69edf69072b1c5b1cb8d3e4a5f7ef898fc3eb76" 92 | 93 | [[package]] 94 | name = "arrayref" 95 | version = "0.3.9" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" 98 | 99 | [[package]] 100 | name = "arrayvec" 101 | version = "0.7.6" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 104 | 105 | [[package]] 106 | name = "async-stream" 107 | version = "0.3.6" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" 110 | dependencies = [ 111 | "async-stream-impl", 112 | "futures-core", 113 | "pin-project-lite", 114 | ] 115 | 116 | [[package]] 117 | name = "async-stream-impl" 118 | version = "0.3.6" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" 121 | dependencies = [ 122 | "proc-macro2", 123 | "quote", 124 | "syn 2.0.87", 125 | ] 126 | 127 | [[package]] 128 | name = "async-trait" 129 | version = "0.1.83" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" 132 | dependencies = [ 133 | "proc-macro2", 134 | "quote", 135 | "syn 2.0.87", 136 | ] 137 | 138 | [[package]] 139 | name = "atoi" 140 | version = "2.0.0" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" 143 | dependencies = [ 144 | "num-traits", 145 | ] 146 | 147 | [[package]] 148 | name = "atoi_simd" 149 | version = "0.15.6" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "9ae037714f313c1353189ead58ef9eec30a8e8dc101b2622d461418fd59e28a9" 152 | 153 | [[package]] 154 | name = "atomic-waker" 155 | version = "1.1.2" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 158 | 159 | [[package]] 160 | name = "autocfg" 161 | version = "1.4.0" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 164 | 165 | [[package]] 166 | name = "backtrace" 167 | version = "0.3.74" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 170 | dependencies = [ 171 | "addr2line", 172 | "cfg-if", 173 | "libc", 174 | "miniz_oxide", 175 | "object", 176 | "rustc-demangle", 177 | "windows-targets", 178 | ] 179 | 180 | [[package]] 181 | name = "base64" 182 | version = "0.22.1" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 185 | 186 | [[package]] 187 | name = "bitflags" 188 | version = "2.6.0" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 191 | dependencies = [ 192 | "serde", 193 | ] 194 | 195 | [[package]] 196 | name = "blake3" 197 | version = "1.5.4" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" 200 | dependencies = [ 201 | "arrayref", 202 | "arrayvec", 203 | "cc", 204 | "cfg-if", 205 | "constant_time_eq", 206 | ] 207 | 208 | [[package]] 209 | name = "block-buffer" 210 | version = "0.10.4" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 213 | dependencies = [ 214 | "generic-array", 215 | ] 216 | 217 | [[package]] 218 | name = "brotli" 219 | version = "6.0.0" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" 222 | dependencies = [ 223 | "alloc-no-stdlib", 224 | "alloc-stdlib", 225 | "brotli-decompressor", 226 | ] 227 | 228 | [[package]] 229 | name = "brotli-decompressor" 230 | version = "4.0.1" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" 233 | dependencies = [ 234 | "alloc-no-stdlib", 235 | "alloc-stdlib", 236 | ] 237 | 238 | [[package]] 239 | name = "bumpalo" 240 | version = "3.16.0" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 243 | 244 | [[package]] 245 | name = "bytemuck" 246 | version = "1.19.0" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" 249 | dependencies = [ 250 | "bytemuck_derive", 251 | ] 252 | 253 | [[package]] 254 | name = "bytemuck_derive" 255 | version = "1.8.0" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" 258 | dependencies = [ 259 | "proc-macro2", 260 | "quote", 261 | "syn 2.0.87", 262 | ] 263 | 264 | [[package]] 265 | name = "byteorder" 266 | version = "1.5.0" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 269 | 270 | [[package]] 271 | name = "bytes" 272 | version = "1.8.0" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" 275 | 276 | [[package]] 277 | name = "castaway" 278 | version = "0.2.3" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" 281 | dependencies = [ 282 | "rustversion", 283 | ] 284 | 285 | [[package]] 286 | name = "cc" 287 | version = "1.1.35" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "0f57c4b4da2a9d619dd035f27316d7a426305b75be93d09e92f2b9229c34feaf" 290 | dependencies = [ 291 | "jobserver", 292 | "libc", 293 | "shlex", 294 | ] 295 | 296 | [[package]] 297 | name = "cfg-if" 298 | version = "1.0.0" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 301 | 302 | [[package]] 303 | name = "cfg_aliases" 304 | version = "0.2.1" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 307 | 308 | [[package]] 309 | name = "chrono" 310 | version = "0.4.38" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" 313 | dependencies = [ 314 | "android-tzdata", 315 | "iana-time-zone", 316 | "num-traits", 317 | "serde", 318 | "windows-targets", 319 | ] 320 | 321 | [[package]] 322 | name = "chrono-tz" 323 | version = "0.8.6" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e" 326 | dependencies = [ 327 | "chrono", 328 | "chrono-tz-build", 329 | "phf", 330 | ] 331 | 332 | [[package]] 333 | name = "chrono-tz-build" 334 | version = "0.2.1" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" 337 | dependencies = [ 338 | "parse-zoneinfo", 339 | "phf", 340 | "phf_codegen", 341 | ] 342 | 343 | [[package]] 344 | name = "ciborium" 345 | version = "0.2.2" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" 348 | dependencies = [ 349 | "ciborium-io", 350 | "ciborium-ll", 351 | "serde", 352 | ] 353 | 354 | [[package]] 355 | name = "ciborium-io" 356 | version = "0.2.2" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" 359 | 360 | [[package]] 361 | name = "ciborium-ll" 362 | version = "0.2.2" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 365 | dependencies = [ 366 | "ciborium-io", 367 | "half", 368 | ] 369 | 370 | [[package]] 371 | name = "comfy-table" 372 | version = "7.1.1" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" 375 | dependencies = [ 376 | "crossterm", 377 | "strum", 378 | "strum_macros", 379 | "unicode-width", 380 | ] 381 | 382 | [[package]] 383 | name = "compact_str" 384 | version = "0.8.0" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" 387 | dependencies = [ 388 | "castaway", 389 | "cfg-if", 390 | "itoa", 391 | "rustversion", 392 | "ryu", 393 | "serde", 394 | "static_assertions", 395 | ] 396 | 397 | [[package]] 398 | name = "constant_time_eq" 399 | version = "0.3.1" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" 402 | 403 | [[package]] 404 | name = "core-foundation" 405 | version = "0.9.4" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 408 | dependencies = [ 409 | "core-foundation-sys", 410 | "libc", 411 | ] 412 | 413 | [[package]] 414 | name = "core-foundation-sys" 415 | version = "0.8.7" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 418 | 419 | [[package]] 420 | name = "crc32fast" 421 | version = "1.4.2" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 424 | dependencies = [ 425 | "cfg-if", 426 | ] 427 | 428 | [[package]] 429 | name = "crossbeam-channel" 430 | version = "0.5.13" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" 433 | dependencies = [ 434 | "crossbeam-utils", 435 | ] 436 | 437 | [[package]] 438 | name = "crossbeam-deque" 439 | version = "0.8.5" 440 | source = "registry+https://github.com/rust-lang/crates.io-index" 441 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" 442 | dependencies = [ 443 | "crossbeam-epoch", 444 | "crossbeam-utils", 445 | ] 446 | 447 | [[package]] 448 | name = "crossbeam-epoch" 449 | version = "0.9.18" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 452 | dependencies = [ 453 | "crossbeam-utils", 454 | ] 455 | 456 | [[package]] 457 | name = "crossbeam-queue" 458 | version = "0.3.11" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" 461 | dependencies = [ 462 | "crossbeam-utils", 463 | ] 464 | 465 | [[package]] 466 | name = "crossbeam-utils" 467 | version = "0.8.20" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 470 | 471 | [[package]] 472 | name = "crossterm" 473 | version = "0.27.0" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" 476 | dependencies = [ 477 | "bitflags", 478 | "crossterm_winapi", 479 | "libc", 480 | "parking_lot", 481 | "winapi", 482 | ] 483 | 484 | [[package]] 485 | name = "crossterm_winapi" 486 | version = "0.9.1" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" 489 | dependencies = [ 490 | "winapi", 491 | ] 492 | 493 | [[package]] 494 | name = "crunchy" 495 | version = "0.2.2" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 498 | 499 | [[package]] 500 | name = "crypto-common" 501 | version = "0.1.6" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 504 | dependencies = [ 505 | "generic-array", 506 | "typenum", 507 | ] 508 | 509 | [[package]] 510 | name = "digest" 511 | version = "0.10.7" 512 | source = "registry+https://github.com/rust-lang/crates.io-index" 513 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 514 | dependencies = [ 515 | "block-buffer", 516 | "crypto-common", 517 | ] 518 | 519 | [[package]] 520 | name = "displaydoc" 521 | version = "0.2.5" 522 | source = "registry+https://github.com/rust-lang/crates.io-index" 523 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 524 | dependencies = [ 525 | "proc-macro2", 526 | "quote", 527 | "syn 2.0.87", 528 | ] 529 | 530 | [[package]] 531 | name = "doc-comment" 532 | version = "0.3.3" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" 535 | 536 | [[package]] 537 | name = "dyn-clone" 538 | version = "1.0.17" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" 541 | 542 | [[package]] 543 | name = "either" 544 | version = "1.13.0" 545 | source = "registry+https://github.com/rust-lang/crates.io-index" 546 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 547 | dependencies = [ 548 | "serde", 549 | ] 550 | 551 | [[package]] 552 | name = "enum_dispatch" 553 | version = "0.3.13" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" 556 | dependencies = [ 557 | "once_cell", 558 | "proc-macro2", 559 | "quote", 560 | "syn 2.0.87", 561 | ] 562 | 563 | [[package]] 564 | name = "equivalent" 565 | version = "1.0.1" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 568 | 569 | [[package]] 570 | name = "errno" 571 | version = "0.3.9" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 574 | dependencies = [ 575 | "libc", 576 | "windows-sys 0.52.0", 577 | ] 578 | 579 | [[package]] 580 | name = "ethnum" 581 | version = "1.5.0" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" 584 | 585 | [[package]] 586 | name = "fallible-streaming-iterator" 587 | version = "0.1.9" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" 590 | 591 | [[package]] 592 | name = "fast-float" 593 | version = "0.2.0" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" 596 | 597 | [[package]] 598 | name = "flate2" 599 | version = "1.0.34" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" 602 | dependencies = [ 603 | "crc32fast", 604 | "miniz_oxide", 605 | ] 606 | 607 | [[package]] 608 | name = "float-cmp" 609 | version = "0.10.0" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" 612 | dependencies = [ 613 | "num-traits", 614 | ] 615 | 616 | [[package]] 617 | name = "fnv" 618 | version = "1.0.7" 619 | source = "registry+https://github.com/rust-lang/crates.io-index" 620 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 621 | 622 | [[package]] 623 | name = "foldhash" 624 | version = "0.1.3" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" 627 | 628 | [[package]] 629 | name = "form_urlencoded" 630 | version = "1.2.1" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 633 | dependencies = [ 634 | "percent-encoding", 635 | ] 636 | 637 | [[package]] 638 | name = "fs4" 639 | version = "0.9.1" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "e8c6b3bd49c37d2aa3f3f2220233b29a7cd23f79d1fe70e5337d25fb390793de" 642 | dependencies = [ 643 | "rustix", 644 | "windows-sys 0.52.0", 645 | ] 646 | 647 | [[package]] 648 | name = "futures" 649 | version = "0.3.31" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 652 | dependencies = [ 653 | "futures-channel", 654 | "futures-core", 655 | "futures-executor", 656 | "futures-io", 657 | "futures-sink", 658 | "futures-task", 659 | "futures-util", 660 | ] 661 | 662 | [[package]] 663 | name = "futures-channel" 664 | version = "0.3.31" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 667 | dependencies = [ 668 | "futures-core", 669 | "futures-sink", 670 | ] 671 | 672 | [[package]] 673 | name = "futures-core" 674 | version = "0.3.31" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 677 | 678 | [[package]] 679 | name = "futures-executor" 680 | version = "0.3.31" 681 | source = "registry+https://github.com/rust-lang/crates.io-index" 682 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 683 | dependencies = [ 684 | "futures-core", 685 | "futures-task", 686 | "futures-util", 687 | ] 688 | 689 | [[package]] 690 | name = "futures-io" 691 | version = "0.3.31" 692 | source = "registry+https://github.com/rust-lang/crates.io-index" 693 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 694 | 695 | [[package]] 696 | name = "futures-macro" 697 | version = "0.3.31" 698 | source = "registry+https://github.com/rust-lang/crates.io-index" 699 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 700 | dependencies = [ 701 | "proc-macro2", 702 | "quote", 703 | "syn 2.0.87", 704 | ] 705 | 706 | [[package]] 707 | name = "futures-sink" 708 | version = "0.3.31" 709 | source = "registry+https://github.com/rust-lang/crates.io-index" 710 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 711 | 712 | [[package]] 713 | name = "futures-task" 714 | version = "0.3.31" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 717 | 718 | [[package]] 719 | name = "futures-util" 720 | version = "0.3.31" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 723 | dependencies = [ 724 | "futures-channel", 725 | "futures-core", 726 | "futures-io", 727 | "futures-macro", 728 | "futures-sink", 729 | "futures-task", 730 | "memchr", 731 | "pin-project-lite", 732 | "pin-utils", 733 | "slab", 734 | ] 735 | 736 | [[package]] 737 | name = "generic-array" 738 | version = "0.14.7" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 741 | dependencies = [ 742 | "typenum", 743 | "version_check", 744 | ] 745 | 746 | [[package]] 747 | name = "getrandom" 748 | version = "0.2.15" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 751 | dependencies = [ 752 | "cfg-if", 753 | "js-sys", 754 | "libc", 755 | "wasi", 756 | "wasm-bindgen", 757 | ] 758 | 759 | [[package]] 760 | name = "gimli" 761 | version = "0.31.1" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 764 | 765 | [[package]] 766 | name = "glob" 767 | version = "0.3.1" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 770 | 771 | [[package]] 772 | name = "h2" 773 | version = "0.4.6" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" 776 | dependencies = [ 777 | "atomic-waker", 778 | "bytes", 779 | "fnv", 780 | "futures-core", 781 | "futures-sink", 782 | "http", 783 | "indexmap", 784 | "slab", 785 | "tokio", 786 | "tokio-util", 787 | "tracing", 788 | ] 789 | 790 | [[package]] 791 | name = "half" 792 | version = "2.4.1" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" 795 | dependencies = [ 796 | "cfg-if", 797 | "crunchy", 798 | ] 799 | 800 | [[package]] 801 | name = "halfbrown" 802 | version = "0.2.5" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f" 805 | dependencies = [ 806 | "hashbrown 0.14.5", 807 | "serde", 808 | ] 809 | 810 | [[package]] 811 | name = "hashbrown" 812 | version = "0.14.5" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 815 | dependencies = [ 816 | "ahash", 817 | "allocator-api2", 818 | "rayon", 819 | "serde", 820 | ] 821 | 822 | [[package]] 823 | name = "hashbrown" 824 | version = "0.15.1" 825 | source = "registry+https://github.com/rust-lang/crates.io-index" 826 | checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" 827 | dependencies = [ 828 | "allocator-api2", 829 | "equivalent", 830 | "foldhash", 831 | "rayon", 832 | "serde", 833 | ] 834 | 835 | [[package]] 836 | name = "heck" 837 | version = "0.4.1" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 840 | 841 | [[package]] 842 | name = "heck" 843 | version = "0.5.0" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 846 | 847 | [[package]] 848 | name = "hermit-abi" 849 | version = "0.3.9" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 852 | 853 | [[package]] 854 | name = "hex" 855 | version = "0.4.3" 856 | source = "registry+https://github.com/rust-lang/crates.io-index" 857 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 858 | 859 | [[package]] 860 | name = "home" 861 | version = "0.5.9" 862 | source = "registry+https://github.com/rust-lang/crates.io-index" 863 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 864 | dependencies = [ 865 | "windows-sys 0.52.0", 866 | ] 867 | 868 | [[package]] 869 | name = "http" 870 | version = "1.1.0" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" 873 | dependencies = [ 874 | "bytes", 875 | "fnv", 876 | "itoa", 877 | ] 878 | 879 | [[package]] 880 | name = "http-body" 881 | version = "1.0.1" 882 | source = "registry+https://github.com/rust-lang/crates.io-index" 883 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 884 | dependencies = [ 885 | "bytes", 886 | "http", 887 | ] 888 | 889 | [[package]] 890 | name = "http-body-util" 891 | version = "0.1.2" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 894 | dependencies = [ 895 | "bytes", 896 | "futures-util", 897 | "http", 898 | "http-body", 899 | "pin-project-lite", 900 | ] 901 | 902 | [[package]] 903 | name = "httparse" 904 | version = "1.9.5" 905 | source = "registry+https://github.com/rust-lang/crates.io-index" 906 | checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" 907 | 908 | [[package]] 909 | name = "humantime" 910 | version = "2.1.0" 911 | source = "registry+https://github.com/rust-lang/crates.io-index" 912 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 913 | 914 | [[package]] 915 | name = "hyper" 916 | version = "1.5.0" 917 | source = "registry+https://github.com/rust-lang/crates.io-index" 918 | checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" 919 | dependencies = [ 920 | "bytes", 921 | "futures-channel", 922 | "futures-util", 923 | "h2", 924 | "http", 925 | "http-body", 926 | "httparse", 927 | "itoa", 928 | "pin-project-lite", 929 | "smallvec", 930 | "tokio", 931 | "want", 932 | ] 933 | 934 | [[package]] 935 | name = "hyper-rustls" 936 | version = "0.27.3" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" 939 | dependencies = [ 940 | "futures-util", 941 | "http", 942 | "hyper", 943 | "hyper-util", 944 | "rustls", 945 | "rustls-native-certs", 946 | "rustls-pki-types", 947 | "tokio", 948 | "tokio-rustls", 949 | "tower-service", 950 | ] 951 | 952 | [[package]] 953 | name = "hyper-util" 954 | version = "0.1.10" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" 957 | dependencies = [ 958 | "bytes", 959 | "futures-channel", 960 | "futures-util", 961 | "http", 962 | "http-body", 963 | "hyper", 964 | "pin-project-lite", 965 | "socket2", 966 | "tokio", 967 | "tower-service", 968 | "tracing", 969 | ] 970 | 971 | [[package]] 972 | name = "iana-time-zone" 973 | version = "0.1.61" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 976 | dependencies = [ 977 | "android_system_properties", 978 | "core-foundation-sys", 979 | "iana-time-zone-haiku", 980 | "js-sys", 981 | "wasm-bindgen", 982 | "windows-core 0.52.0", 983 | ] 984 | 985 | [[package]] 986 | name = "iana-time-zone-haiku" 987 | version = "0.1.2" 988 | source = "registry+https://github.com/rust-lang/crates.io-index" 989 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 990 | dependencies = [ 991 | "cc", 992 | ] 993 | 994 | [[package]] 995 | name = "icu_collections" 996 | version = "1.5.0" 997 | source = "registry+https://github.com/rust-lang/crates.io-index" 998 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 999 | dependencies = [ 1000 | "displaydoc", 1001 | "yoke", 1002 | "zerofrom", 1003 | "zerovec", 1004 | ] 1005 | 1006 | [[package]] 1007 | name = "icu_locid" 1008 | version = "1.5.0" 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" 1010 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 1011 | dependencies = [ 1012 | "displaydoc", 1013 | "litemap", 1014 | "tinystr", 1015 | "writeable", 1016 | "zerovec", 1017 | ] 1018 | 1019 | [[package]] 1020 | name = "icu_locid_transform" 1021 | version = "1.5.0" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 1024 | dependencies = [ 1025 | "displaydoc", 1026 | "icu_locid", 1027 | "icu_locid_transform_data", 1028 | "icu_provider", 1029 | "tinystr", 1030 | "zerovec", 1031 | ] 1032 | 1033 | [[package]] 1034 | name = "icu_locid_transform_data" 1035 | version = "1.5.0" 1036 | source = "registry+https://github.com/rust-lang/crates.io-index" 1037 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 1038 | 1039 | [[package]] 1040 | name = "icu_normalizer" 1041 | version = "1.5.0" 1042 | source = "registry+https://github.com/rust-lang/crates.io-index" 1043 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 1044 | dependencies = [ 1045 | "displaydoc", 1046 | "icu_collections", 1047 | "icu_normalizer_data", 1048 | "icu_properties", 1049 | "icu_provider", 1050 | "smallvec", 1051 | "utf16_iter", 1052 | "utf8_iter", 1053 | "write16", 1054 | "zerovec", 1055 | ] 1056 | 1057 | [[package]] 1058 | name = "icu_normalizer_data" 1059 | version = "1.5.0" 1060 | source = "registry+https://github.com/rust-lang/crates.io-index" 1061 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 1062 | 1063 | [[package]] 1064 | name = "icu_properties" 1065 | version = "1.5.1" 1066 | source = "registry+https://github.com/rust-lang/crates.io-index" 1067 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 1068 | dependencies = [ 1069 | "displaydoc", 1070 | "icu_collections", 1071 | "icu_locid_transform", 1072 | "icu_properties_data", 1073 | "icu_provider", 1074 | "tinystr", 1075 | "zerovec", 1076 | ] 1077 | 1078 | [[package]] 1079 | name = "icu_properties_data" 1080 | version = "1.5.0" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 1083 | 1084 | [[package]] 1085 | name = "icu_provider" 1086 | version = "1.5.0" 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" 1088 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 1089 | dependencies = [ 1090 | "displaydoc", 1091 | "icu_locid", 1092 | "icu_provider_macros", 1093 | "stable_deref_trait", 1094 | "tinystr", 1095 | "writeable", 1096 | "yoke", 1097 | "zerofrom", 1098 | "zerovec", 1099 | ] 1100 | 1101 | [[package]] 1102 | name = "icu_provider_macros" 1103 | version = "1.5.0" 1104 | source = "registry+https://github.com/rust-lang/crates.io-index" 1105 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 1106 | dependencies = [ 1107 | "proc-macro2", 1108 | "quote", 1109 | "syn 2.0.87", 1110 | ] 1111 | 1112 | [[package]] 1113 | name = "idna" 1114 | version = "1.0.3" 1115 | source = "registry+https://github.com/rust-lang/crates.io-index" 1116 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 1117 | dependencies = [ 1118 | "idna_adapter", 1119 | "smallvec", 1120 | "utf8_iter", 1121 | ] 1122 | 1123 | [[package]] 1124 | name = "idna_adapter" 1125 | version = "1.2.0" 1126 | source = "registry+https://github.com/rust-lang/crates.io-index" 1127 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 1128 | dependencies = [ 1129 | "icu_normalizer", 1130 | "icu_properties", 1131 | ] 1132 | 1133 | [[package]] 1134 | name = "indexmap" 1135 | version = "2.6.0" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" 1138 | dependencies = [ 1139 | "equivalent", 1140 | "hashbrown 0.15.1", 1141 | "serde", 1142 | ] 1143 | 1144 | [[package]] 1145 | name = "indoc" 1146 | version = "2.0.5" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" 1149 | 1150 | [[package]] 1151 | name = "ipnet" 1152 | version = "2.10.1" 1153 | source = "registry+https://github.com/rust-lang/crates.io-index" 1154 | checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" 1155 | 1156 | [[package]] 1157 | name = "iter-read" 1158 | version = "0.3.1" 1159 | source = "registry+https://github.com/rust-lang/crates.io-index" 1160 | checksum = "c397ca3ea05ad509c4ec451fea28b4771236a376ca1c69fd5143aae0cf8f93c4" 1161 | 1162 | [[package]] 1163 | name = "itertools" 1164 | version = "0.13.0" 1165 | source = "registry+https://github.com/rust-lang/crates.io-index" 1166 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 1167 | dependencies = [ 1168 | "either", 1169 | ] 1170 | 1171 | [[package]] 1172 | name = "itoa" 1173 | version = "1.0.11" 1174 | source = "registry+https://github.com/rust-lang/crates.io-index" 1175 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 1176 | 1177 | [[package]] 1178 | name = "itoap" 1179 | version = "1.0.1" 1180 | source = "registry+https://github.com/rust-lang/crates.io-index" 1181 | checksum = "9028f49264629065d057f340a86acb84867925865f73bbf8d47b4d149a7e88b8" 1182 | 1183 | [[package]] 1184 | name = "jobserver" 1185 | version = "0.1.32" 1186 | source = "registry+https://github.com/rust-lang/crates.io-index" 1187 | checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" 1188 | dependencies = [ 1189 | "libc", 1190 | ] 1191 | 1192 | [[package]] 1193 | name = "js-sys" 1194 | version = "0.3.72" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" 1197 | dependencies = [ 1198 | "wasm-bindgen", 1199 | ] 1200 | 1201 | [[package]] 1202 | name = "libc" 1203 | version = "0.2.161" 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" 1205 | checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" 1206 | 1207 | [[package]] 1208 | name = "libm" 1209 | version = "0.2.11" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" 1212 | 1213 | [[package]] 1214 | name = "linux-raw-sys" 1215 | version = "0.4.14" 1216 | source = "registry+https://github.com/rust-lang/crates.io-index" 1217 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 1218 | 1219 | [[package]] 1220 | name = "litemap" 1221 | version = "0.7.3" 1222 | source = "registry+https://github.com/rust-lang/crates.io-index" 1223 | checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" 1224 | 1225 | [[package]] 1226 | name = "lock_api" 1227 | version = "0.4.12" 1228 | source = "registry+https://github.com/rust-lang/crates.io-index" 1229 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 1230 | dependencies = [ 1231 | "autocfg", 1232 | "scopeguard", 1233 | ] 1234 | 1235 | [[package]] 1236 | name = "log" 1237 | version = "0.4.22" 1238 | source = "registry+https://github.com/rust-lang/crates.io-index" 1239 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 1240 | 1241 | [[package]] 1242 | name = "lz4" 1243 | version = "1.28.0" 1244 | source = "registry+https://github.com/rust-lang/crates.io-index" 1245 | checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" 1246 | dependencies = [ 1247 | "lz4-sys", 1248 | ] 1249 | 1250 | [[package]] 1251 | name = "lz4-sys" 1252 | version = "1.11.1+lz4-1.10.0" 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" 1254 | checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" 1255 | dependencies = [ 1256 | "cc", 1257 | "libc", 1258 | ] 1259 | 1260 | [[package]] 1261 | name = "md-5" 1262 | version = "0.10.6" 1263 | source = "registry+https://github.com/rust-lang/crates.io-index" 1264 | checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" 1265 | dependencies = [ 1266 | "cfg-if", 1267 | "digest", 1268 | ] 1269 | 1270 | [[package]] 1271 | name = "memchr" 1272 | version = "2.7.4" 1273 | source = "registry+https://github.com/rust-lang/crates.io-index" 1274 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1275 | 1276 | [[package]] 1277 | name = "memmap2" 1278 | version = "0.7.1" 1279 | source = "registry+https://github.com/rust-lang/crates.io-index" 1280 | checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6" 1281 | dependencies = [ 1282 | "libc", 1283 | ] 1284 | 1285 | [[package]] 1286 | name = "memoffset" 1287 | version = "0.9.1" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" 1290 | dependencies = [ 1291 | "autocfg", 1292 | ] 1293 | 1294 | [[package]] 1295 | name = "mime" 1296 | version = "0.3.17" 1297 | source = "registry+https://github.com/rust-lang/crates.io-index" 1298 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1299 | 1300 | [[package]] 1301 | name = "miniz_oxide" 1302 | version = "0.8.0" 1303 | source = "registry+https://github.com/rust-lang/crates.io-index" 1304 | checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" 1305 | dependencies = [ 1306 | "adler2", 1307 | ] 1308 | 1309 | [[package]] 1310 | name = "mio" 1311 | version = "1.0.2" 1312 | source = "registry+https://github.com/rust-lang/crates.io-index" 1313 | checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" 1314 | dependencies = [ 1315 | "hermit-abi", 1316 | "libc", 1317 | "wasi", 1318 | "windows-sys 0.52.0", 1319 | ] 1320 | 1321 | [[package]] 1322 | name = "multiversion" 1323 | version = "0.7.4" 1324 | source = "registry+https://github.com/rust-lang/crates.io-index" 1325 | checksum = "c4851161a11d3ad0bf9402d90ffc3967bf231768bfd7aeb61755ad06dbf1a142" 1326 | dependencies = [ 1327 | "multiversion-macros", 1328 | "target-features", 1329 | ] 1330 | 1331 | [[package]] 1332 | name = "multiversion-macros" 1333 | version = "0.7.4" 1334 | source = "registry+https://github.com/rust-lang/crates.io-index" 1335 | checksum = "79a74ddee9e0c27d2578323c13905793e91622148f138ba29738f9dddb835e90" 1336 | dependencies = [ 1337 | "proc-macro2", 1338 | "quote", 1339 | "syn 1.0.109", 1340 | "target-features", 1341 | ] 1342 | 1343 | [[package]] 1344 | name = "now" 1345 | version = "0.1.3" 1346 | source = "registry+https://github.com/rust-lang/crates.io-index" 1347 | checksum = "6d89e9874397a1f0a52fc1f197a8effd9735223cb2390e9dcc83ac6cd02923d0" 1348 | dependencies = [ 1349 | "chrono", 1350 | ] 1351 | 1352 | [[package]] 1353 | name = "ntapi" 1354 | version = "0.4.1" 1355 | source = "registry+https://github.com/rust-lang/crates.io-index" 1356 | checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" 1357 | dependencies = [ 1358 | "winapi", 1359 | ] 1360 | 1361 | [[package]] 1362 | name = "num" 1363 | version = "0.4.3" 1364 | source = "registry+https://github.com/rust-lang/crates.io-index" 1365 | checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" 1366 | dependencies = [ 1367 | "num-bigint", 1368 | "num-complex", 1369 | "num-integer", 1370 | "num-iter", 1371 | "num-rational", 1372 | "num-traits", 1373 | ] 1374 | 1375 | [[package]] 1376 | name = "num-bigint" 1377 | version = "0.4.6" 1378 | source = "registry+https://github.com/rust-lang/crates.io-index" 1379 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 1380 | dependencies = [ 1381 | "num-integer", 1382 | "num-traits", 1383 | ] 1384 | 1385 | [[package]] 1386 | name = "num-complex" 1387 | version = "0.4.6" 1388 | source = "registry+https://github.com/rust-lang/crates.io-index" 1389 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" 1390 | dependencies = [ 1391 | "num-traits", 1392 | ] 1393 | 1394 | [[package]] 1395 | name = "num-integer" 1396 | version = "0.1.46" 1397 | source = "registry+https://github.com/rust-lang/crates.io-index" 1398 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 1399 | dependencies = [ 1400 | "num-traits", 1401 | ] 1402 | 1403 | [[package]] 1404 | name = "num-iter" 1405 | version = "0.1.45" 1406 | source = "registry+https://github.com/rust-lang/crates.io-index" 1407 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 1408 | dependencies = [ 1409 | "autocfg", 1410 | "num-integer", 1411 | "num-traits", 1412 | ] 1413 | 1414 | [[package]] 1415 | name = "num-rational" 1416 | version = "0.4.2" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" 1419 | dependencies = [ 1420 | "num-bigint", 1421 | "num-integer", 1422 | "num-traits", 1423 | ] 1424 | 1425 | [[package]] 1426 | name = "num-traits" 1427 | version = "0.2.19" 1428 | source = "registry+https://github.com/rust-lang/crates.io-index" 1429 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1430 | dependencies = [ 1431 | "autocfg", 1432 | "libm", 1433 | ] 1434 | 1435 | [[package]] 1436 | name = "object" 1437 | version = "0.36.5" 1438 | source = "registry+https://github.com/rust-lang/crates.io-index" 1439 | checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" 1440 | dependencies = [ 1441 | "memchr", 1442 | ] 1443 | 1444 | [[package]] 1445 | name = "object_store" 1446 | version = "0.10.2" 1447 | source = "registry+https://github.com/rust-lang/crates.io-index" 1448 | checksum = "e6da452820c715ce78221e8202ccc599b4a52f3e1eb3eedb487b680c81a8e3f3" 1449 | dependencies = [ 1450 | "async-trait", 1451 | "base64", 1452 | "bytes", 1453 | "chrono", 1454 | "futures", 1455 | "humantime", 1456 | "hyper", 1457 | "itertools", 1458 | "md-5", 1459 | "parking_lot", 1460 | "percent-encoding", 1461 | "quick-xml", 1462 | "rand", 1463 | "reqwest", 1464 | "ring", 1465 | "serde", 1466 | "serde_json", 1467 | "snafu", 1468 | "tokio", 1469 | "tracing", 1470 | "url", 1471 | "walkdir", 1472 | ] 1473 | 1474 | [[package]] 1475 | name = "once_cell" 1476 | version = "1.20.2" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 1479 | 1480 | [[package]] 1481 | name = "openssl-probe" 1482 | version = "0.1.5" 1483 | source = "registry+https://github.com/rust-lang/crates.io-index" 1484 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 1485 | 1486 | [[package]] 1487 | name = "parking_lot" 1488 | version = "0.12.3" 1489 | source = "registry+https://github.com/rust-lang/crates.io-index" 1490 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 1491 | dependencies = [ 1492 | "lock_api", 1493 | "parking_lot_core", 1494 | ] 1495 | 1496 | [[package]] 1497 | name = "parking_lot_core" 1498 | version = "0.9.10" 1499 | source = "registry+https://github.com/rust-lang/crates.io-index" 1500 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 1501 | dependencies = [ 1502 | "cfg-if", 1503 | "libc", 1504 | "redox_syscall", 1505 | "smallvec", 1506 | "windows-targets", 1507 | ] 1508 | 1509 | [[package]] 1510 | name = "parse-zoneinfo" 1511 | version = "0.3.1" 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" 1513 | checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" 1514 | dependencies = [ 1515 | "regex", 1516 | ] 1517 | 1518 | [[package]] 1519 | name = "percent-encoding" 1520 | version = "2.3.1" 1521 | source = "registry+https://github.com/rust-lang/crates.io-index" 1522 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1523 | 1524 | [[package]] 1525 | name = "phf" 1526 | version = "0.11.2" 1527 | source = "registry+https://github.com/rust-lang/crates.io-index" 1528 | checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" 1529 | dependencies = [ 1530 | "phf_shared", 1531 | ] 1532 | 1533 | [[package]] 1534 | name = "phf_codegen" 1535 | version = "0.11.2" 1536 | source = "registry+https://github.com/rust-lang/crates.io-index" 1537 | checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" 1538 | dependencies = [ 1539 | "phf_generator", 1540 | "phf_shared", 1541 | ] 1542 | 1543 | [[package]] 1544 | name = "phf_generator" 1545 | version = "0.11.2" 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" 1547 | checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" 1548 | dependencies = [ 1549 | "phf_shared", 1550 | "rand", 1551 | ] 1552 | 1553 | [[package]] 1554 | name = "phf_shared" 1555 | version = "0.11.2" 1556 | source = "registry+https://github.com/rust-lang/crates.io-index" 1557 | checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" 1558 | dependencies = [ 1559 | "siphasher", 1560 | ] 1561 | 1562 | [[package]] 1563 | name = "pin-project-lite" 1564 | version = "0.2.15" 1565 | source = "registry+https://github.com/rust-lang/crates.io-index" 1566 | checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" 1567 | 1568 | [[package]] 1569 | name = "pin-utils" 1570 | version = "0.1.0" 1571 | source = "registry+https://github.com/rust-lang/crates.io-index" 1572 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1573 | 1574 | [[package]] 1575 | name = "pkg-config" 1576 | version = "0.3.31" 1577 | source = "registry+https://github.com/rust-lang/crates.io-index" 1578 | checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" 1579 | 1580 | [[package]] 1581 | name = "planus" 1582 | version = "0.3.1" 1583 | source = "registry+https://github.com/rust-lang/crates.io-index" 1584 | checksum = "fc1691dd09e82f428ce8d6310bd6d5da2557c82ff17694d2a32cad7242aea89f" 1585 | dependencies = [ 1586 | "array-init-cursor", 1587 | ] 1588 | 1589 | [[package]] 1590 | name = "polars" 1591 | version = "0.44.2" 1592 | source = "registry+https://github.com/rust-lang/crates.io-index" 1593 | checksum = "f65c6aa86d991a64c95416a61202f7952da2f8cccefa448f9a23c1b8f2301ecc" 1594 | dependencies = [ 1595 | "getrandom", 1596 | "polars-arrow", 1597 | "polars-core", 1598 | "polars-error", 1599 | "polars-io", 1600 | "polars-lazy", 1601 | "polars-ops", 1602 | "polars-parquet", 1603 | "polars-sql", 1604 | "polars-time", 1605 | "polars-utils", 1606 | "version_check", 1607 | ] 1608 | 1609 | [[package]] 1610 | name = "polars-arrow" 1611 | version = "0.44.2" 1612 | source = "registry+https://github.com/rust-lang/crates.io-index" 1613 | checksum = "87dbb24d29ddea5abb73d7954df8b8d3d4bb7f02a3e5c96d1519cdad9e816a3d" 1614 | dependencies = [ 1615 | "ahash", 1616 | "atoi", 1617 | "atoi_simd", 1618 | "bytemuck", 1619 | "chrono", 1620 | "chrono-tz", 1621 | "dyn-clone", 1622 | "either", 1623 | "ethnum", 1624 | "fast-float", 1625 | "getrandom", 1626 | "hashbrown 0.15.1", 1627 | "itoa", 1628 | "itoap", 1629 | "lz4", 1630 | "multiversion", 1631 | "num-traits", 1632 | "parking_lot", 1633 | "polars-arrow-format", 1634 | "polars-error", 1635 | "polars-schema", 1636 | "polars-utils", 1637 | "ryu", 1638 | "serde", 1639 | "simdutf8", 1640 | "streaming-iterator", 1641 | "strength_reduce", 1642 | "strum_macros", 1643 | "version_check", 1644 | "zstd", 1645 | ] 1646 | 1647 | [[package]] 1648 | name = "polars-arrow-format" 1649 | version = "0.1.0" 1650 | source = "registry+https://github.com/rust-lang/crates.io-index" 1651 | checksum = "19b0ef2474af9396b19025b189d96e992311e6a47f90c53cd998b36c4c64b84c" 1652 | dependencies = [ 1653 | "planus", 1654 | "serde", 1655 | ] 1656 | 1657 | [[package]] 1658 | name = "polars-compute" 1659 | version = "0.44.2" 1660 | source = "registry+https://github.com/rust-lang/crates.io-index" 1661 | checksum = "cbdb1071147452a4c4b25560f23d2fbaffef255b04757291131b22fc2c0d35b2" 1662 | dependencies = [ 1663 | "bytemuck", 1664 | "either", 1665 | "num-traits", 1666 | "polars-arrow", 1667 | "polars-error", 1668 | "polars-utils", 1669 | "strength_reduce", 1670 | "version_check", 1671 | ] 1672 | 1673 | [[package]] 1674 | name = "polars-core" 1675 | version = "0.44.2" 1676 | source = "registry+https://github.com/rust-lang/crates.io-index" 1677 | checksum = "dd5df9b55e614088a3270b06f8649dce76537c268d6b1ca4d9c37008b2be5949" 1678 | dependencies = [ 1679 | "ahash", 1680 | "bitflags", 1681 | "bytemuck", 1682 | "chrono", 1683 | "chrono-tz", 1684 | "comfy-table", 1685 | "either", 1686 | "hashbrown 0.14.5", 1687 | "hashbrown 0.15.1", 1688 | "indexmap", 1689 | "num-traits", 1690 | "once_cell", 1691 | "polars-arrow", 1692 | "polars-compute", 1693 | "polars-error", 1694 | "polars-row", 1695 | "polars-schema", 1696 | "polars-utils", 1697 | "rand", 1698 | "rand_distr", 1699 | "rayon", 1700 | "regex", 1701 | "serde", 1702 | "serde_json", 1703 | "strum_macros", 1704 | "thiserror", 1705 | "version_check", 1706 | "xxhash-rust", 1707 | ] 1708 | 1709 | [[package]] 1710 | name = "polars-error" 1711 | version = "0.44.2" 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" 1713 | checksum = "4643898a644f30c83737db85f942f8c8956b0c11190b39afec745218eae1746b" 1714 | dependencies = [ 1715 | "object_store", 1716 | "polars-arrow-format", 1717 | "regex", 1718 | "simdutf8", 1719 | "thiserror", 1720 | ] 1721 | 1722 | [[package]] 1723 | name = "polars-expr" 1724 | version = "0.44.2" 1725 | source = "registry+https://github.com/rust-lang/crates.io-index" 1726 | checksum = "ea1b431ed816cba1120cff200f06b962748001bbb2e615ce53cfbbdf701cc136" 1727 | dependencies = [ 1728 | "ahash", 1729 | "bitflags", 1730 | "hashbrown 0.15.1", 1731 | "num-traits", 1732 | "once_cell", 1733 | "polars-arrow", 1734 | "polars-compute", 1735 | "polars-core", 1736 | "polars-io", 1737 | "polars-ops", 1738 | "polars-plan", 1739 | "polars-row", 1740 | "polars-time", 1741 | "polars-utils", 1742 | "rand", 1743 | "rayon", 1744 | ] 1745 | 1746 | [[package]] 1747 | name = "polars-ffi" 1748 | version = "0.44.2" 1749 | source = "registry+https://github.com/rust-lang/crates.io-index" 1750 | checksum = "11f38ddf675f605d8b5228c3e282b630112d7431c884120be10d606c705c4989" 1751 | dependencies = [ 1752 | "polars-arrow", 1753 | "polars-core", 1754 | ] 1755 | 1756 | [[package]] 1757 | name = "polars-io" 1758 | version = "0.44.2" 1759 | source = "registry+https://github.com/rust-lang/crates.io-index" 1760 | checksum = "b2fab2c016635cb416b49461fd6419b0208c6c13a4fd065bd65e4a87dbb66314" 1761 | dependencies = [ 1762 | "ahash", 1763 | "async-trait", 1764 | "atoi_simd", 1765 | "blake3", 1766 | "bytes", 1767 | "chrono", 1768 | "fast-float", 1769 | "fs4", 1770 | "futures", 1771 | "glob", 1772 | "hashbrown 0.15.1", 1773 | "home", 1774 | "itoa", 1775 | "memchr", 1776 | "memmap2", 1777 | "num-traits", 1778 | "object_store", 1779 | "once_cell", 1780 | "percent-encoding", 1781 | "polars-arrow", 1782 | "polars-core", 1783 | "polars-error", 1784 | "polars-json", 1785 | "polars-parquet", 1786 | "polars-schema", 1787 | "polars-time", 1788 | "polars-utils", 1789 | "pyo3", 1790 | "rayon", 1791 | "regex", 1792 | "reqwest", 1793 | "ryu", 1794 | "serde", 1795 | "serde_json", 1796 | "simd-json", 1797 | "simdutf8", 1798 | "tokio", 1799 | "tokio-util", 1800 | "url", 1801 | ] 1802 | 1803 | [[package]] 1804 | name = "polars-json" 1805 | version = "0.44.2" 1806 | source = "registry+https://github.com/rust-lang/crates.io-index" 1807 | checksum = "d5c8c057ef04feaf34b6ce52096bdea3a766fa4725f50442078c8a4ee86397bf" 1808 | dependencies = [ 1809 | "ahash", 1810 | "chrono", 1811 | "fallible-streaming-iterator", 1812 | "hashbrown 0.15.1", 1813 | "indexmap", 1814 | "itoa", 1815 | "num-traits", 1816 | "polars-arrow", 1817 | "polars-error", 1818 | "polars-utils", 1819 | "ryu", 1820 | "simd-json", 1821 | "streaming-iterator", 1822 | ] 1823 | 1824 | [[package]] 1825 | name = "polars-lazy" 1826 | version = "0.44.2" 1827 | source = "registry+https://github.com/rust-lang/crates.io-index" 1828 | checksum = "4a8ca74f42e7b47cad241b36b98d991cc7fbb51b8d0695a055eb937588d1f310" 1829 | dependencies = [ 1830 | "ahash", 1831 | "bitflags", 1832 | "memchr", 1833 | "once_cell", 1834 | "polars-arrow", 1835 | "polars-core", 1836 | "polars-expr", 1837 | "polars-io", 1838 | "polars-mem-engine", 1839 | "polars-ops", 1840 | "polars-pipe", 1841 | "polars-plan", 1842 | "polars-stream", 1843 | "polars-time", 1844 | "polars-utils", 1845 | "rayon", 1846 | "version_check", 1847 | ] 1848 | 1849 | [[package]] 1850 | name = "polars-mem-engine" 1851 | version = "0.44.2" 1852 | source = "registry+https://github.com/rust-lang/crates.io-index" 1853 | checksum = "7a32614e5b52c9b83856d80c7e2880b79d83055bfd59969bd1d0b148f9cfdc7a" 1854 | dependencies = [ 1855 | "futures", 1856 | "memmap2", 1857 | "polars-arrow", 1858 | "polars-core", 1859 | "polars-error", 1860 | "polars-expr", 1861 | "polars-io", 1862 | "polars-json", 1863 | "polars-ops", 1864 | "polars-plan", 1865 | "polars-time", 1866 | "polars-utils", 1867 | "pyo3", 1868 | "rayon", 1869 | "tokio", 1870 | ] 1871 | 1872 | [[package]] 1873 | name = "polars-ops" 1874 | version = "0.44.2" 1875 | source = "registry+https://github.com/rust-lang/crates.io-index" 1876 | checksum = "035c800fbe5bbd820afeb8313713ed345853bb014e0f821a4025d40cf0d60e1a" 1877 | dependencies = [ 1878 | "ahash", 1879 | "argminmax", 1880 | "base64", 1881 | "bytemuck", 1882 | "chrono", 1883 | "chrono-tz", 1884 | "either", 1885 | "hashbrown 0.15.1", 1886 | "hex", 1887 | "indexmap", 1888 | "memchr", 1889 | "num-traits", 1890 | "polars-arrow", 1891 | "polars-compute", 1892 | "polars-core", 1893 | "polars-error", 1894 | "polars-schema", 1895 | "polars-utils", 1896 | "rayon", 1897 | "regex", 1898 | "regex-syntax", 1899 | "serde", 1900 | "strum_macros", 1901 | "unicode-reverse", 1902 | "version_check", 1903 | ] 1904 | 1905 | [[package]] 1906 | name = "polars-parquet" 1907 | version = "0.44.2" 1908 | source = "registry+https://github.com/rust-lang/crates.io-index" 1909 | checksum = "91dcf1d9f048079376949eaf2e24e240b313ff4a102fb83b57c9a5f807cdca52" 1910 | dependencies = [ 1911 | "ahash", 1912 | "async-stream", 1913 | "base64", 1914 | "brotli", 1915 | "bytemuck", 1916 | "ethnum", 1917 | "flate2", 1918 | "futures", 1919 | "hashbrown 0.15.1", 1920 | "lz4", 1921 | "num-traits", 1922 | "polars-arrow", 1923 | "polars-compute", 1924 | "polars-error", 1925 | "polars-parquet-format", 1926 | "polars-utils", 1927 | "serde", 1928 | "simdutf8", 1929 | "snap", 1930 | "streaming-decompression", 1931 | "zstd", 1932 | ] 1933 | 1934 | [[package]] 1935 | name = "polars-parquet-format" 1936 | version = "0.1.0" 1937 | source = "registry+https://github.com/rust-lang/crates.io-index" 1938 | checksum = "c025243dcfe8dbc57e94d9f82eb3bef10b565ab180d5b99bed87fd8aea319ce1" 1939 | dependencies = [ 1940 | "async-trait", 1941 | "futures", 1942 | ] 1943 | 1944 | [[package]] 1945 | name = "polars-pipe" 1946 | version = "0.44.2" 1947 | source = "registry+https://github.com/rust-lang/crates.io-index" 1948 | checksum = "05936f2b3981eecb2fe74d8ef092bb75a93d2a056b3e4f339f4ac20c71c9e331" 1949 | dependencies = [ 1950 | "crossbeam-channel", 1951 | "crossbeam-queue", 1952 | "enum_dispatch", 1953 | "hashbrown 0.15.1", 1954 | "num-traits", 1955 | "polars-arrow", 1956 | "polars-compute", 1957 | "polars-core", 1958 | "polars-expr", 1959 | "polars-io", 1960 | "polars-ops", 1961 | "polars-plan", 1962 | "polars-row", 1963 | "polars-utils", 1964 | "rayon", 1965 | "uuid", 1966 | "version_check", 1967 | ] 1968 | 1969 | [[package]] 1970 | name = "polars-plan" 1971 | version = "0.44.2" 1972 | source = "registry+https://github.com/rust-lang/crates.io-index" 1973 | checksum = "23de436f33f4d1134c58f24e7059a221b957ec20730807e0ef0c80c8e4b3d06a" 1974 | dependencies = [ 1975 | "ahash", 1976 | "bitflags", 1977 | "bytemuck", 1978 | "bytes", 1979 | "chrono", 1980 | "chrono-tz", 1981 | "ciborium", 1982 | "either", 1983 | "futures", 1984 | "hashbrown 0.15.1", 1985 | "memmap2", 1986 | "num-traits", 1987 | "once_cell", 1988 | "percent-encoding", 1989 | "polars-arrow", 1990 | "polars-core", 1991 | "polars-io", 1992 | "polars-json", 1993 | "polars-ops", 1994 | "polars-parquet", 1995 | "polars-time", 1996 | "polars-utils", 1997 | "pyo3", 1998 | "rayon", 1999 | "recursive", 2000 | "regex", 2001 | "serde", 2002 | "strum_macros", 2003 | "version_check", 2004 | ] 2005 | 2006 | [[package]] 2007 | name = "polars-row" 2008 | version = "0.44.2" 2009 | source = "registry+https://github.com/rust-lang/crates.io-index" 2010 | checksum = "3823d3de3e614509bba6929798f1f3d5ae05c1cdfc4eb7029d2ec6ad77201da2" 2011 | dependencies = [ 2012 | "bytemuck", 2013 | "polars-arrow", 2014 | "polars-error", 2015 | "polars-utils", 2016 | ] 2017 | 2018 | [[package]] 2019 | name = "polars-schema" 2020 | version = "0.44.2" 2021 | source = "registry+https://github.com/rust-lang/crates.io-index" 2022 | checksum = "d88667f770291cefa2e8cd366a54f29dc6fe362e9a263914c903db411a58ac1d" 2023 | dependencies = [ 2024 | "indexmap", 2025 | "polars-error", 2026 | "polars-utils", 2027 | "serde", 2028 | "version_check", 2029 | ] 2030 | 2031 | [[package]] 2032 | name = "polars-sql" 2033 | version = "0.44.2" 2034 | source = "registry+https://github.com/rust-lang/crates.io-index" 2035 | checksum = "69451f08363bb497407f6ebebe00bc01972a51716d20d115b75f9b5326f1f3c8" 2036 | dependencies = [ 2037 | "hex", 2038 | "once_cell", 2039 | "polars-arrow", 2040 | "polars-core", 2041 | "polars-error", 2042 | "polars-lazy", 2043 | "polars-ops", 2044 | "polars-plan", 2045 | "polars-time", 2046 | "polars-utils", 2047 | "rand", 2048 | "serde", 2049 | "serde_json", 2050 | "sqlparser", 2051 | ] 2052 | 2053 | [[package]] 2054 | name = "polars-stream" 2055 | version = "0.44.2" 2056 | source = "registry+https://github.com/rust-lang/crates.io-index" 2057 | checksum = "188622b0a4bc4530cf91a288134254ffa065d18932e261075377914225e757c2" 2058 | dependencies = [ 2059 | "atomic-waker", 2060 | "crossbeam-deque", 2061 | "crossbeam-utils", 2062 | "futures", 2063 | "memmap2", 2064 | "parking_lot", 2065 | "pin-project-lite", 2066 | "polars-core", 2067 | "polars-error", 2068 | "polars-expr", 2069 | "polars-io", 2070 | "polars-mem-engine", 2071 | "polars-parquet", 2072 | "polars-plan", 2073 | "polars-utils", 2074 | "rand", 2075 | "rayon", 2076 | "recursive", 2077 | "slotmap", 2078 | "tokio", 2079 | "version_check", 2080 | ] 2081 | 2082 | [[package]] 2083 | name = "polars-time" 2084 | version = "0.44.2" 2085 | source = "registry+https://github.com/rust-lang/crates.io-index" 2086 | checksum = "90f36e4d6b19f2c406faea585b9a1814f422fc5b310f65ccf8a55216df0754ef" 2087 | dependencies = [ 2088 | "atoi", 2089 | "bytemuck", 2090 | "chrono", 2091 | "chrono-tz", 2092 | "now", 2093 | "once_cell", 2094 | "polars-arrow", 2095 | "polars-core", 2096 | "polars-error", 2097 | "polars-ops", 2098 | "polars-utils", 2099 | "regex", 2100 | "serde", 2101 | "strum_macros", 2102 | ] 2103 | 2104 | [[package]] 2105 | name = "polars-trading" 2106 | version = "0.1.0" 2107 | dependencies = [ 2108 | "num", 2109 | "polars", 2110 | "polars-arrow", 2111 | "pyo3", 2112 | "pyo3-polars", 2113 | "serde", 2114 | ] 2115 | 2116 | [[package]] 2117 | name = "polars-utils" 2118 | version = "0.44.2" 2119 | source = "registry+https://github.com/rust-lang/crates.io-index" 2120 | checksum = "96186b70bda00c90b5027bf2f69193c5c40571e80d3e8ec505c22cdc8e3e39aa" 2121 | dependencies = [ 2122 | "ahash", 2123 | "bytemuck", 2124 | "bytes", 2125 | "compact_str", 2126 | "hashbrown 0.15.1", 2127 | "indexmap", 2128 | "libc", 2129 | "memmap2", 2130 | "num-traits", 2131 | "once_cell", 2132 | "polars-error", 2133 | "pyo3", 2134 | "raw-cpuid", 2135 | "rayon", 2136 | "serde", 2137 | "stacker", 2138 | "sysinfo", 2139 | "version_check", 2140 | ] 2141 | 2142 | [[package]] 2143 | name = "portable-atomic" 2144 | version = "1.9.0" 2145 | source = "registry+https://github.com/rust-lang/crates.io-index" 2146 | checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" 2147 | 2148 | [[package]] 2149 | name = "ppv-lite86" 2150 | version = "0.2.20" 2151 | source = "registry+https://github.com/rust-lang/crates.io-index" 2152 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 2153 | dependencies = [ 2154 | "zerocopy", 2155 | ] 2156 | 2157 | [[package]] 2158 | name = "proc-macro2" 2159 | version = "1.0.89" 2160 | source = "registry+https://github.com/rust-lang/crates.io-index" 2161 | checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" 2162 | dependencies = [ 2163 | "unicode-ident", 2164 | ] 2165 | 2166 | [[package]] 2167 | name = "psm" 2168 | version = "0.1.23" 2169 | source = "registry+https://github.com/rust-lang/crates.io-index" 2170 | checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" 2171 | dependencies = [ 2172 | "cc", 2173 | ] 2174 | 2175 | [[package]] 2176 | name = "pyo3" 2177 | version = "0.21.2" 2178 | source = "registry+https://github.com/rust-lang/crates.io-index" 2179 | checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8" 2180 | dependencies = [ 2181 | "cfg-if", 2182 | "indoc", 2183 | "libc", 2184 | "memoffset", 2185 | "parking_lot", 2186 | "portable-atomic", 2187 | "pyo3-build-config", 2188 | "pyo3-ffi", 2189 | "pyo3-macros", 2190 | "unindent", 2191 | ] 2192 | 2193 | [[package]] 2194 | name = "pyo3-build-config" 2195 | version = "0.21.2" 2196 | source = "registry+https://github.com/rust-lang/crates.io-index" 2197 | checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50" 2198 | dependencies = [ 2199 | "once_cell", 2200 | "target-lexicon", 2201 | ] 2202 | 2203 | [[package]] 2204 | name = "pyo3-ffi" 2205 | version = "0.21.2" 2206 | source = "registry+https://github.com/rust-lang/crates.io-index" 2207 | checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403" 2208 | dependencies = [ 2209 | "libc", 2210 | "pyo3-build-config", 2211 | ] 2212 | 2213 | [[package]] 2214 | name = "pyo3-macros" 2215 | version = "0.21.2" 2216 | source = "registry+https://github.com/rust-lang/crates.io-index" 2217 | checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c" 2218 | dependencies = [ 2219 | "proc-macro2", 2220 | "pyo3-macros-backend", 2221 | "quote", 2222 | "syn 2.0.87", 2223 | ] 2224 | 2225 | [[package]] 2226 | name = "pyo3-macros-backend" 2227 | version = "0.21.2" 2228 | source = "registry+https://github.com/rust-lang/crates.io-index" 2229 | checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c" 2230 | dependencies = [ 2231 | "heck 0.4.1", 2232 | "proc-macro2", 2233 | "pyo3-build-config", 2234 | "quote", 2235 | "syn 2.0.87", 2236 | ] 2237 | 2238 | [[package]] 2239 | name = "pyo3-polars" 2240 | version = "0.18.0" 2241 | source = "registry+https://github.com/rust-lang/crates.io-index" 2242 | checksum = "08d315add0412858cb21d45f0a48d68974d32f5f93f92fd9cedc95102ea011d1" 2243 | dependencies = [ 2244 | "libc", 2245 | "once_cell", 2246 | "polars", 2247 | "polars-core", 2248 | "polars-ffi", 2249 | "polars-plan", 2250 | "pyo3", 2251 | "pyo3-polars-derive", 2252 | "serde", 2253 | "serde-pickle", 2254 | "thiserror", 2255 | ] 2256 | 2257 | [[package]] 2258 | name = "pyo3-polars-derive" 2259 | version = "0.12.0" 2260 | source = "registry+https://github.com/rust-lang/crates.io-index" 2261 | checksum = "ecaf05e8162950078d88e1ab4ffaf865723389c252a8c4f0c3f405ca1d88439f" 2262 | dependencies = [ 2263 | "polars-core", 2264 | "polars-ffi", 2265 | "polars-plan", 2266 | "proc-macro2", 2267 | "quote", 2268 | "syn 2.0.87", 2269 | ] 2270 | 2271 | [[package]] 2272 | name = "quick-xml" 2273 | version = "0.36.2" 2274 | source = "registry+https://github.com/rust-lang/crates.io-index" 2275 | checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" 2276 | dependencies = [ 2277 | "memchr", 2278 | "serde", 2279 | ] 2280 | 2281 | [[package]] 2282 | name = "quinn" 2283 | version = "0.11.5" 2284 | source = "registry+https://github.com/rust-lang/crates.io-index" 2285 | checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" 2286 | dependencies = [ 2287 | "bytes", 2288 | "pin-project-lite", 2289 | "quinn-proto", 2290 | "quinn-udp", 2291 | "rustc-hash", 2292 | "rustls", 2293 | "socket2", 2294 | "thiserror", 2295 | "tokio", 2296 | "tracing", 2297 | ] 2298 | 2299 | [[package]] 2300 | name = "quinn-proto" 2301 | version = "0.11.8" 2302 | source = "registry+https://github.com/rust-lang/crates.io-index" 2303 | checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" 2304 | dependencies = [ 2305 | "bytes", 2306 | "rand", 2307 | "ring", 2308 | "rustc-hash", 2309 | "rustls", 2310 | "slab", 2311 | "thiserror", 2312 | "tinyvec", 2313 | "tracing", 2314 | ] 2315 | 2316 | [[package]] 2317 | name = "quinn-udp" 2318 | version = "0.5.7" 2319 | source = "registry+https://github.com/rust-lang/crates.io-index" 2320 | checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" 2321 | dependencies = [ 2322 | "cfg_aliases", 2323 | "libc", 2324 | "once_cell", 2325 | "socket2", 2326 | "tracing", 2327 | "windows-sys 0.59.0", 2328 | ] 2329 | 2330 | [[package]] 2331 | name = "quote" 2332 | version = "1.0.37" 2333 | source = "registry+https://github.com/rust-lang/crates.io-index" 2334 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 2335 | dependencies = [ 2336 | "proc-macro2", 2337 | ] 2338 | 2339 | [[package]] 2340 | name = "rand" 2341 | version = "0.8.5" 2342 | source = "registry+https://github.com/rust-lang/crates.io-index" 2343 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 2344 | dependencies = [ 2345 | "libc", 2346 | "rand_chacha", 2347 | "rand_core", 2348 | ] 2349 | 2350 | [[package]] 2351 | name = "rand_chacha" 2352 | version = "0.3.1" 2353 | source = "registry+https://github.com/rust-lang/crates.io-index" 2354 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 2355 | dependencies = [ 2356 | "ppv-lite86", 2357 | "rand_core", 2358 | ] 2359 | 2360 | [[package]] 2361 | name = "rand_core" 2362 | version = "0.6.4" 2363 | source = "registry+https://github.com/rust-lang/crates.io-index" 2364 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 2365 | dependencies = [ 2366 | "getrandom", 2367 | ] 2368 | 2369 | [[package]] 2370 | name = "rand_distr" 2371 | version = "0.4.3" 2372 | source = "registry+https://github.com/rust-lang/crates.io-index" 2373 | checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" 2374 | dependencies = [ 2375 | "num-traits", 2376 | "rand", 2377 | ] 2378 | 2379 | [[package]] 2380 | name = "raw-cpuid" 2381 | version = "11.2.0" 2382 | source = "registry+https://github.com/rust-lang/crates.io-index" 2383 | checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" 2384 | dependencies = [ 2385 | "bitflags", 2386 | ] 2387 | 2388 | [[package]] 2389 | name = "rayon" 2390 | version = "1.10.0" 2391 | source = "registry+https://github.com/rust-lang/crates.io-index" 2392 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 2393 | dependencies = [ 2394 | "either", 2395 | "rayon-core", 2396 | ] 2397 | 2398 | [[package]] 2399 | name = "rayon-core" 2400 | version = "1.12.1" 2401 | source = "registry+https://github.com/rust-lang/crates.io-index" 2402 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 2403 | dependencies = [ 2404 | "crossbeam-deque", 2405 | "crossbeam-utils", 2406 | ] 2407 | 2408 | [[package]] 2409 | name = "recursive" 2410 | version = "0.1.1" 2411 | source = "registry+https://github.com/rust-lang/crates.io-index" 2412 | checksum = "0786a43debb760f491b1bc0269fe5e84155353c67482b9e60d0cfb596054b43e" 2413 | dependencies = [ 2414 | "recursive-proc-macro-impl", 2415 | "stacker", 2416 | ] 2417 | 2418 | [[package]] 2419 | name = "recursive-proc-macro-impl" 2420 | version = "0.1.1" 2421 | source = "registry+https://github.com/rust-lang/crates.io-index" 2422 | checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b" 2423 | dependencies = [ 2424 | "quote", 2425 | "syn 2.0.87", 2426 | ] 2427 | 2428 | [[package]] 2429 | name = "redox_syscall" 2430 | version = "0.5.7" 2431 | source = "registry+https://github.com/rust-lang/crates.io-index" 2432 | checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" 2433 | dependencies = [ 2434 | "bitflags", 2435 | ] 2436 | 2437 | [[package]] 2438 | name = "ref-cast" 2439 | version = "1.0.23" 2440 | source = "registry+https://github.com/rust-lang/crates.io-index" 2441 | checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" 2442 | dependencies = [ 2443 | "ref-cast-impl", 2444 | ] 2445 | 2446 | [[package]] 2447 | name = "ref-cast-impl" 2448 | version = "1.0.23" 2449 | source = "registry+https://github.com/rust-lang/crates.io-index" 2450 | checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" 2451 | dependencies = [ 2452 | "proc-macro2", 2453 | "quote", 2454 | "syn 2.0.87", 2455 | ] 2456 | 2457 | [[package]] 2458 | name = "regex" 2459 | version = "1.11.1" 2460 | source = "registry+https://github.com/rust-lang/crates.io-index" 2461 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 2462 | dependencies = [ 2463 | "aho-corasick", 2464 | "memchr", 2465 | "regex-automata", 2466 | "regex-syntax", 2467 | ] 2468 | 2469 | [[package]] 2470 | name = "regex-automata" 2471 | version = "0.4.8" 2472 | source = "registry+https://github.com/rust-lang/crates.io-index" 2473 | checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" 2474 | dependencies = [ 2475 | "aho-corasick", 2476 | "memchr", 2477 | "regex-syntax", 2478 | ] 2479 | 2480 | [[package]] 2481 | name = "regex-syntax" 2482 | version = "0.8.5" 2483 | source = "registry+https://github.com/rust-lang/crates.io-index" 2484 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 2485 | 2486 | [[package]] 2487 | name = "reqwest" 2488 | version = "0.12.9" 2489 | source = "registry+https://github.com/rust-lang/crates.io-index" 2490 | checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" 2491 | dependencies = [ 2492 | "base64", 2493 | "bytes", 2494 | "futures-core", 2495 | "futures-util", 2496 | "h2", 2497 | "http", 2498 | "http-body", 2499 | "http-body-util", 2500 | "hyper", 2501 | "hyper-rustls", 2502 | "hyper-util", 2503 | "ipnet", 2504 | "js-sys", 2505 | "log", 2506 | "mime", 2507 | "once_cell", 2508 | "percent-encoding", 2509 | "pin-project-lite", 2510 | "quinn", 2511 | "rustls", 2512 | "rustls-native-certs", 2513 | "rustls-pemfile", 2514 | "rustls-pki-types", 2515 | "serde", 2516 | "serde_json", 2517 | "serde_urlencoded", 2518 | "sync_wrapper", 2519 | "tokio", 2520 | "tokio-rustls", 2521 | "tokio-util", 2522 | "tower-service", 2523 | "url", 2524 | "wasm-bindgen", 2525 | "wasm-bindgen-futures", 2526 | "wasm-streams", 2527 | "web-sys", 2528 | "windows-registry", 2529 | ] 2530 | 2531 | [[package]] 2532 | name = "ring" 2533 | version = "0.17.8" 2534 | source = "registry+https://github.com/rust-lang/crates.io-index" 2535 | checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 2536 | dependencies = [ 2537 | "cc", 2538 | "cfg-if", 2539 | "getrandom", 2540 | "libc", 2541 | "spin", 2542 | "untrusted", 2543 | "windows-sys 0.52.0", 2544 | ] 2545 | 2546 | [[package]] 2547 | name = "rustc-demangle" 2548 | version = "0.1.24" 2549 | source = "registry+https://github.com/rust-lang/crates.io-index" 2550 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 2551 | 2552 | [[package]] 2553 | name = "rustc-hash" 2554 | version = "2.0.0" 2555 | source = "registry+https://github.com/rust-lang/crates.io-index" 2556 | checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" 2557 | 2558 | [[package]] 2559 | name = "rustix" 2560 | version = "0.38.39" 2561 | source = "registry+https://github.com/rust-lang/crates.io-index" 2562 | checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" 2563 | dependencies = [ 2564 | "bitflags", 2565 | "errno", 2566 | "libc", 2567 | "linux-raw-sys", 2568 | "windows-sys 0.52.0", 2569 | ] 2570 | 2571 | [[package]] 2572 | name = "rustls" 2573 | version = "0.23.16" 2574 | source = "registry+https://github.com/rust-lang/crates.io-index" 2575 | checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" 2576 | dependencies = [ 2577 | "once_cell", 2578 | "ring", 2579 | "rustls-pki-types", 2580 | "rustls-webpki", 2581 | "subtle", 2582 | "zeroize", 2583 | ] 2584 | 2585 | [[package]] 2586 | name = "rustls-native-certs" 2587 | version = "0.8.0" 2588 | source = "registry+https://github.com/rust-lang/crates.io-index" 2589 | checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" 2590 | dependencies = [ 2591 | "openssl-probe", 2592 | "rustls-pemfile", 2593 | "rustls-pki-types", 2594 | "schannel", 2595 | "security-framework", 2596 | ] 2597 | 2598 | [[package]] 2599 | name = "rustls-pemfile" 2600 | version = "2.2.0" 2601 | source = "registry+https://github.com/rust-lang/crates.io-index" 2602 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 2603 | dependencies = [ 2604 | "rustls-pki-types", 2605 | ] 2606 | 2607 | [[package]] 2608 | name = "rustls-pki-types" 2609 | version = "1.10.0" 2610 | source = "registry+https://github.com/rust-lang/crates.io-index" 2611 | checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" 2612 | 2613 | [[package]] 2614 | name = "rustls-webpki" 2615 | version = "0.102.8" 2616 | source = "registry+https://github.com/rust-lang/crates.io-index" 2617 | checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" 2618 | dependencies = [ 2619 | "ring", 2620 | "rustls-pki-types", 2621 | "untrusted", 2622 | ] 2623 | 2624 | [[package]] 2625 | name = "rustversion" 2626 | version = "1.0.18" 2627 | source = "registry+https://github.com/rust-lang/crates.io-index" 2628 | checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" 2629 | 2630 | [[package]] 2631 | name = "ryu" 2632 | version = "1.0.18" 2633 | source = "registry+https://github.com/rust-lang/crates.io-index" 2634 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 2635 | 2636 | [[package]] 2637 | name = "same-file" 2638 | version = "1.0.6" 2639 | source = "registry+https://github.com/rust-lang/crates.io-index" 2640 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 2641 | dependencies = [ 2642 | "winapi-util", 2643 | ] 2644 | 2645 | [[package]] 2646 | name = "schannel" 2647 | version = "0.1.26" 2648 | source = "registry+https://github.com/rust-lang/crates.io-index" 2649 | checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" 2650 | dependencies = [ 2651 | "windows-sys 0.59.0", 2652 | ] 2653 | 2654 | [[package]] 2655 | name = "scopeguard" 2656 | version = "1.2.0" 2657 | source = "registry+https://github.com/rust-lang/crates.io-index" 2658 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 2659 | 2660 | [[package]] 2661 | name = "security-framework" 2662 | version = "2.11.1" 2663 | source = "registry+https://github.com/rust-lang/crates.io-index" 2664 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 2665 | dependencies = [ 2666 | "bitflags", 2667 | "core-foundation", 2668 | "core-foundation-sys", 2669 | "libc", 2670 | "security-framework-sys", 2671 | ] 2672 | 2673 | [[package]] 2674 | name = "security-framework-sys" 2675 | version = "2.12.0" 2676 | source = "registry+https://github.com/rust-lang/crates.io-index" 2677 | checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" 2678 | dependencies = [ 2679 | "core-foundation-sys", 2680 | "libc", 2681 | ] 2682 | 2683 | [[package]] 2684 | name = "serde" 2685 | version = "1.0.214" 2686 | source = "registry+https://github.com/rust-lang/crates.io-index" 2687 | checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" 2688 | dependencies = [ 2689 | "serde_derive", 2690 | ] 2691 | 2692 | [[package]] 2693 | name = "serde-pickle" 2694 | version = "1.1.1" 2695 | source = "registry+https://github.com/rust-lang/crates.io-index" 2696 | checksum = "c762ad136a26407c6a80825813600ceeab5e613660d93d79a41f0ec877171e71" 2697 | dependencies = [ 2698 | "byteorder", 2699 | "iter-read", 2700 | "num-bigint", 2701 | "num-traits", 2702 | "serde", 2703 | ] 2704 | 2705 | [[package]] 2706 | name = "serde_derive" 2707 | version = "1.0.214" 2708 | source = "registry+https://github.com/rust-lang/crates.io-index" 2709 | checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" 2710 | dependencies = [ 2711 | "proc-macro2", 2712 | "quote", 2713 | "syn 2.0.87", 2714 | ] 2715 | 2716 | [[package]] 2717 | name = "serde_json" 2718 | version = "1.0.132" 2719 | source = "registry+https://github.com/rust-lang/crates.io-index" 2720 | checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" 2721 | dependencies = [ 2722 | "itoa", 2723 | "memchr", 2724 | "ryu", 2725 | "serde", 2726 | ] 2727 | 2728 | [[package]] 2729 | name = "serde_urlencoded" 2730 | version = "0.7.1" 2731 | source = "registry+https://github.com/rust-lang/crates.io-index" 2732 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2733 | dependencies = [ 2734 | "form_urlencoded", 2735 | "itoa", 2736 | "ryu", 2737 | "serde", 2738 | ] 2739 | 2740 | [[package]] 2741 | name = "shlex" 2742 | version = "1.3.0" 2743 | source = "registry+https://github.com/rust-lang/crates.io-index" 2744 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 2745 | 2746 | [[package]] 2747 | name = "simd-json" 2748 | version = "0.14.2" 2749 | source = "registry+https://github.com/rust-lang/crates.io-index" 2750 | checksum = "b1df0290e9bfe79ddd5ff8798ca887cd107b75353d2957efe9777296e17f26b5" 2751 | dependencies = [ 2752 | "ahash", 2753 | "getrandom", 2754 | "halfbrown", 2755 | "once_cell", 2756 | "ref-cast", 2757 | "serde", 2758 | "serde_json", 2759 | "simdutf8", 2760 | "value-trait", 2761 | ] 2762 | 2763 | [[package]] 2764 | name = "simdutf8" 2765 | version = "0.1.5" 2766 | source = "registry+https://github.com/rust-lang/crates.io-index" 2767 | checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" 2768 | 2769 | [[package]] 2770 | name = "siphasher" 2771 | version = "0.3.11" 2772 | source = "registry+https://github.com/rust-lang/crates.io-index" 2773 | checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" 2774 | 2775 | [[package]] 2776 | name = "slab" 2777 | version = "0.4.9" 2778 | source = "registry+https://github.com/rust-lang/crates.io-index" 2779 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 2780 | dependencies = [ 2781 | "autocfg", 2782 | ] 2783 | 2784 | [[package]] 2785 | name = "slotmap" 2786 | version = "1.0.7" 2787 | source = "registry+https://github.com/rust-lang/crates.io-index" 2788 | checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" 2789 | dependencies = [ 2790 | "version_check", 2791 | ] 2792 | 2793 | [[package]] 2794 | name = "smallvec" 2795 | version = "1.13.2" 2796 | source = "registry+https://github.com/rust-lang/crates.io-index" 2797 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 2798 | 2799 | [[package]] 2800 | name = "snafu" 2801 | version = "0.7.5" 2802 | source = "registry+https://github.com/rust-lang/crates.io-index" 2803 | checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6" 2804 | dependencies = [ 2805 | "doc-comment", 2806 | "snafu-derive", 2807 | ] 2808 | 2809 | [[package]] 2810 | name = "snafu-derive" 2811 | version = "0.7.5" 2812 | source = "registry+https://github.com/rust-lang/crates.io-index" 2813 | checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" 2814 | dependencies = [ 2815 | "heck 0.4.1", 2816 | "proc-macro2", 2817 | "quote", 2818 | "syn 1.0.109", 2819 | ] 2820 | 2821 | [[package]] 2822 | name = "snap" 2823 | version = "1.1.1" 2824 | source = "registry+https://github.com/rust-lang/crates.io-index" 2825 | checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" 2826 | 2827 | [[package]] 2828 | name = "socket2" 2829 | version = "0.5.7" 2830 | source = "registry+https://github.com/rust-lang/crates.io-index" 2831 | checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 2832 | dependencies = [ 2833 | "libc", 2834 | "windows-sys 0.52.0", 2835 | ] 2836 | 2837 | [[package]] 2838 | name = "spin" 2839 | version = "0.9.8" 2840 | source = "registry+https://github.com/rust-lang/crates.io-index" 2841 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 2842 | 2843 | [[package]] 2844 | name = "sqlparser" 2845 | version = "0.49.0" 2846 | source = "registry+https://github.com/rust-lang/crates.io-index" 2847 | checksum = "a4a404d0e14905361b918cb8afdb73605e25c1d5029312bd9785142dcb3aa49e" 2848 | dependencies = [ 2849 | "log", 2850 | ] 2851 | 2852 | [[package]] 2853 | name = "stable_deref_trait" 2854 | version = "1.2.0" 2855 | source = "registry+https://github.com/rust-lang/crates.io-index" 2856 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2857 | 2858 | [[package]] 2859 | name = "stacker" 2860 | version = "0.1.17" 2861 | source = "registry+https://github.com/rust-lang/crates.io-index" 2862 | checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" 2863 | dependencies = [ 2864 | "cc", 2865 | "cfg-if", 2866 | "libc", 2867 | "psm", 2868 | "windows-sys 0.59.0", 2869 | ] 2870 | 2871 | [[package]] 2872 | name = "static_assertions" 2873 | version = "1.1.0" 2874 | source = "registry+https://github.com/rust-lang/crates.io-index" 2875 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 2876 | 2877 | [[package]] 2878 | name = "streaming-decompression" 2879 | version = "0.1.2" 2880 | source = "registry+https://github.com/rust-lang/crates.io-index" 2881 | checksum = "bf6cc3b19bfb128a8ad11026086e31d3ce9ad23f8ea37354b31383a187c44cf3" 2882 | dependencies = [ 2883 | "fallible-streaming-iterator", 2884 | ] 2885 | 2886 | [[package]] 2887 | name = "streaming-iterator" 2888 | version = "0.1.9" 2889 | source = "registry+https://github.com/rust-lang/crates.io-index" 2890 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" 2891 | 2892 | [[package]] 2893 | name = "strength_reduce" 2894 | version = "0.2.4" 2895 | source = "registry+https://github.com/rust-lang/crates.io-index" 2896 | checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" 2897 | 2898 | [[package]] 2899 | name = "strum" 2900 | version = "0.26.3" 2901 | source = "registry+https://github.com/rust-lang/crates.io-index" 2902 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" 2903 | 2904 | [[package]] 2905 | name = "strum_macros" 2906 | version = "0.26.4" 2907 | source = "registry+https://github.com/rust-lang/crates.io-index" 2908 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" 2909 | dependencies = [ 2910 | "heck 0.5.0", 2911 | "proc-macro2", 2912 | "quote", 2913 | "rustversion", 2914 | "syn 2.0.87", 2915 | ] 2916 | 2917 | [[package]] 2918 | name = "subtle" 2919 | version = "2.6.1" 2920 | source = "registry+https://github.com/rust-lang/crates.io-index" 2921 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 2922 | 2923 | [[package]] 2924 | name = "syn" 2925 | version = "1.0.109" 2926 | source = "registry+https://github.com/rust-lang/crates.io-index" 2927 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 2928 | dependencies = [ 2929 | "proc-macro2", 2930 | "quote", 2931 | "unicode-ident", 2932 | ] 2933 | 2934 | [[package]] 2935 | name = "syn" 2936 | version = "2.0.87" 2937 | source = "registry+https://github.com/rust-lang/crates.io-index" 2938 | checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" 2939 | dependencies = [ 2940 | "proc-macro2", 2941 | "quote", 2942 | "unicode-ident", 2943 | ] 2944 | 2945 | [[package]] 2946 | name = "sync_wrapper" 2947 | version = "1.0.1" 2948 | source = "registry+https://github.com/rust-lang/crates.io-index" 2949 | checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" 2950 | dependencies = [ 2951 | "futures-core", 2952 | ] 2953 | 2954 | [[package]] 2955 | name = "synstructure" 2956 | version = "0.13.1" 2957 | source = "registry+https://github.com/rust-lang/crates.io-index" 2958 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 2959 | dependencies = [ 2960 | "proc-macro2", 2961 | "quote", 2962 | "syn 2.0.87", 2963 | ] 2964 | 2965 | [[package]] 2966 | name = "sysinfo" 2967 | version = "0.31.4" 2968 | source = "registry+https://github.com/rust-lang/crates.io-index" 2969 | checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" 2970 | dependencies = [ 2971 | "core-foundation-sys", 2972 | "libc", 2973 | "memchr", 2974 | "ntapi", 2975 | "windows", 2976 | ] 2977 | 2978 | [[package]] 2979 | name = "target-features" 2980 | version = "0.1.6" 2981 | source = "registry+https://github.com/rust-lang/crates.io-index" 2982 | checksum = "c1bbb9f3c5c463a01705937a24fdabc5047929ac764b2d5b9cf681c1f5041ed5" 2983 | 2984 | [[package]] 2985 | name = "target-lexicon" 2986 | version = "0.12.16" 2987 | source = "registry+https://github.com/rust-lang/crates.io-index" 2988 | checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" 2989 | 2990 | [[package]] 2991 | name = "thiserror" 2992 | version = "1.0.68" 2993 | source = "registry+https://github.com/rust-lang/crates.io-index" 2994 | checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" 2995 | dependencies = [ 2996 | "thiserror-impl", 2997 | ] 2998 | 2999 | [[package]] 3000 | name = "thiserror-impl" 3001 | version = "1.0.68" 3002 | source = "registry+https://github.com/rust-lang/crates.io-index" 3003 | checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" 3004 | dependencies = [ 3005 | "proc-macro2", 3006 | "quote", 3007 | "syn 2.0.87", 3008 | ] 3009 | 3010 | [[package]] 3011 | name = "tinystr" 3012 | version = "0.7.6" 3013 | source = "registry+https://github.com/rust-lang/crates.io-index" 3014 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 3015 | dependencies = [ 3016 | "displaydoc", 3017 | "zerovec", 3018 | ] 3019 | 3020 | [[package]] 3021 | name = "tinyvec" 3022 | version = "1.8.0" 3023 | source = "registry+https://github.com/rust-lang/crates.io-index" 3024 | checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" 3025 | dependencies = [ 3026 | "tinyvec_macros", 3027 | ] 3028 | 3029 | [[package]] 3030 | name = "tinyvec_macros" 3031 | version = "0.1.1" 3032 | source = "registry+https://github.com/rust-lang/crates.io-index" 3033 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 3034 | 3035 | [[package]] 3036 | name = "tokio" 3037 | version = "1.41.0" 3038 | source = "registry+https://github.com/rust-lang/crates.io-index" 3039 | checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" 3040 | dependencies = [ 3041 | "backtrace", 3042 | "bytes", 3043 | "libc", 3044 | "mio", 3045 | "pin-project-lite", 3046 | "socket2", 3047 | "tokio-macros", 3048 | "windows-sys 0.52.0", 3049 | ] 3050 | 3051 | [[package]] 3052 | name = "tokio-macros" 3053 | version = "2.4.0" 3054 | source = "registry+https://github.com/rust-lang/crates.io-index" 3055 | checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" 3056 | dependencies = [ 3057 | "proc-macro2", 3058 | "quote", 3059 | "syn 2.0.87", 3060 | ] 3061 | 3062 | [[package]] 3063 | name = "tokio-rustls" 3064 | version = "0.26.0" 3065 | source = "registry+https://github.com/rust-lang/crates.io-index" 3066 | checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" 3067 | dependencies = [ 3068 | "rustls", 3069 | "rustls-pki-types", 3070 | "tokio", 3071 | ] 3072 | 3073 | [[package]] 3074 | name = "tokio-util" 3075 | version = "0.7.12" 3076 | source = "registry+https://github.com/rust-lang/crates.io-index" 3077 | checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" 3078 | dependencies = [ 3079 | "bytes", 3080 | "futures-core", 3081 | "futures-sink", 3082 | "pin-project-lite", 3083 | "tokio", 3084 | ] 3085 | 3086 | [[package]] 3087 | name = "tower-service" 3088 | version = "0.3.3" 3089 | source = "registry+https://github.com/rust-lang/crates.io-index" 3090 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 3091 | 3092 | [[package]] 3093 | name = "tracing" 3094 | version = "0.1.40" 3095 | source = "registry+https://github.com/rust-lang/crates.io-index" 3096 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 3097 | dependencies = [ 3098 | "pin-project-lite", 3099 | "tracing-attributes", 3100 | "tracing-core", 3101 | ] 3102 | 3103 | [[package]] 3104 | name = "tracing-attributes" 3105 | version = "0.1.27" 3106 | source = "registry+https://github.com/rust-lang/crates.io-index" 3107 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 3108 | dependencies = [ 3109 | "proc-macro2", 3110 | "quote", 3111 | "syn 2.0.87", 3112 | ] 3113 | 3114 | [[package]] 3115 | name = "tracing-core" 3116 | version = "0.1.32" 3117 | source = "registry+https://github.com/rust-lang/crates.io-index" 3118 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 3119 | dependencies = [ 3120 | "once_cell", 3121 | ] 3122 | 3123 | [[package]] 3124 | name = "try-lock" 3125 | version = "0.2.5" 3126 | source = "registry+https://github.com/rust-lang/crates.io-index" 3127 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 3128 | 3129 | [[package]] 3130 | name = "typenum" 3131 | version = "1.17.0" 3132 | source = "registry+https://github.com/rust-lang/crates.io-index" 3133 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 3134 | 3135 | [[package]] 3136 | name = "unicode-ident" 3137 | version = "1.0.13" 3138 | source = "registry+https://github.com/rust-lang/crates.io-index" 3139 | checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" 3140 | 3141 | [[package]] 3142 | name = "unicode-reverse" 3143 | version = "1.0.9" 3144 | source = "registry+https://github.com/rust-lang/crates.io-index" 3145 | checksum = "4b6f4888ebc23094adfb574fdca9fdc891826287a6397d2cd28802ffd6f20c76" 3146 | dependencies = [ 3147 | "unicode-segmentation", 3148 | ] 3149 | 3150 | [[package]] 3151 | name = "unicode-segmentation" 3152 | version = "1.12.0" 3153 | source = "registry+https://github.com/rust-lang/crates.io-index" 3154 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 3155 | 3156 | [[package]] 3157 | name = "unicode-width" 3158 | version = "0.1.14" 3159 | source = "registry+https://github.com/rust-lang/crates.io-index" 3160 | checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" 3161 | 3162 | [[package]] 3163 | name = "unindent" 3164 | version = "0.2.3" 3165 | source = "registry+https://github.com/rust-lang/crates.io-index" 3166 | checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" 3167 | 3168 | [[package]] 3169 | name = "untrusted" 3170 | version = "0.9.0" 3171 | source = "registry+https://github.com/rust-lang/crates.io-index" 3172 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 3173 | 3174 | [[package]] 3175 | name = "url" 3176 | version = "2.5.3" 3177 | source = "registry+https://github.com/rust-lang/crates.io-index" 3178 | checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" 3179 | dependencies = [ 3180 | "form_urlencoded", 3181 | "idna", 3182 | "percent-encoding", 3183 | ] 3184 | 3185 | [[package]] 3186 | name = "utf16_iter" 3187 | version = "1.0.5" 3188 | source = "registry+https://github.com/rust-lang/crates.io-index" 3189 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 3190 | 3191 | [[package]] 3192 | name = "utf8_iter" 3193 | version = "1.0.4" 3194 | source = "registry+https://github.com/rust-lang/crates.io-index" 3195 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 3196 | 3197 | [[package]] 3198 | name = "uuid" 3199 | version = "1.11.0" 3200 | source = "registry+https://github.com/rust-lang/crates.io-index" 3201 | checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" 3202 | dependencies = [ 3203 | "getrandom", 3204 | ] 3205 | 3206 | [[package]] 3207 | name = "value-trait" 3208 | version = "0.10.1" 3209 | source = "registry+https://github.com/rust-lang/crates.io-index" 3210 | checksum = "9170e001f458781e92711d2ad666110f153e4e50bfd5cbd02db6547625714187" 3211 | dependencies = [ 3212 | "float-cmp", 3213 | "halfbrown", 3214 | "itoa", 3215 | "ryu", 3216 | ] 3217 | 3218 | [[package]] 3219 | name = "version_check" 3220 | version = "0.9.5" 3221 | source = "registry+https://github.com/rust-lang/crates.io-index" 3222 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 3223 | 3224 | [[package]] 3225 | name = "walkdir" 3226 | version = "2.5.0" 3227 | source = "registry+https://github.com/rust-lang/crates.io-index" 3228 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 3229 | dependencies = [ 3230 | "same-file", 3231 | "winapi-util", 3232 | ] 3233 | 3234 | [[package]] 3235 | name = "want" 3236 | version = "0.3.1" 3237 | source = "registry+https://github.com/rust-lang/crates.io-index" 3238 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 3239 | dependencies = [ 3240 | "try-lock", 3241 | ] 3242 | 3243 | [[package]] 3244 | name = "wasi" 3245 | version = "0.11.0+wasi-snapshot-preview1" 3246 | source = "registry+https://github.com/rust-lang/crates.io-index" 3247 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 3248 | 3249 | [[package]] 3250 | name = "wasm-bindgen" 3251 | version = "0.2.95" 3252 | source = "registry+https://github.com/rust-lang/crates.io-index" 3253 | checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" 3254 | dependencies = [ 3255 | "cfg-if", 3256 | "once_cell", 3257 | "wasm-bindgen-macro", 3258 | ] 3259 | 3260 | [[package]] 3261 | name = "wasm-bindgen-backend" 3262 | version = "0.2.95" 3263 | source = "registry+https://github.com/rust-lang/crates.io-index" 3264 | checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" 3265 | dependencies = [ 3266 | "bumpalo", 3267 | "log", 3268 | "once_cell", 3269 | "proc-macro2", 3270 | "quote", 3271 | "syn 2.0.87", 3272 | "wasm-bindgen-shared", 3273 | ] 3274 | 3275 | [[package]] 3276 | name = "wasm-bindgen-futures" 3277 | version = "0.4.45" 3278 | source = "registry+https://github.com/rust-lang/crates.io-index" 3279 | checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" 3280 | dependencies = [ 3281 | "cfg-if", 3282 | "js-sys", 3283 | "wasm-bindgen", 3284 | "web-sys", 3285 | ] 3286 | 3287 | [[package]] 3288 | name = "wasm-bindgen-macro" 3289 | version = "0.2.95" 3290 | source = "registry+https://github.com/rust-lang/crates.io-index" 3291 | checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" 3292 | dependencies = [ 3293 | "quote", 3294 | "wasm-bindgen-macro-support", 3295 | ] 3296 | 3297 | [[package]] 3298 | name = "wasm-bindgen-macro-support" 3299 | version = "0.2.95" 3300 | source = "registry+https://github.com/rust-lang/crates.io-index" 3301 | checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" 3302 | dependencies = [ 3303 | "proc-macro2", 3304 | "quote", 3305 | "syn 2.0.87", 3306 | "wasm-bindgen-backend", 3307 | "wasm-bindgen-shared", 3308 | ] 3309 | 3310 | [[package]] 3311 | name = "wasm-bindgen-shared" 3312 | version = "0.2.95" 3313 | source = "registry+https://github.com/rust-lang/crates.io-index" 3314 | checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" 3315 | 3316 | [[package]] 3317 | name = "wasm-streams" 3318 | version = "0.4.2" 3319 | source = "registry+https://github.com/rust-lang/crates.io-index" 3320 | checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" 3321 | dependencies = [ 3322 | "futures-util", 3323 | "js-sys", 3324 | "wasm-bindgen", 3325 | "wasm-bindgen-futures", 3326 | "web-sys", 3327 | ] 3328 | 3329 | [[package]] 3330 | name = "web-sys" 3331 | version = "0.3.72" 3332 | source = "registry+https://github.com/rust-lang/crates.io-index" 3333 | checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" 3334 | dependencies = [ 3335 | "js-sys", 3336 | "wasm-bindgen", 3337 | ] 3338 | 3339 | [[package]] 3340 | name = "winapi" 3341 | version = "0.3.9" 3342 | source = "registry+https://github.com/rust-lang/crates.io-index" 3343 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 3344 | dependencies = [ 3345 | "winapi-i686-pc-windows-gnu", 3346 | "winapi-x86_64-pc-windows-gnu", 3347 | ] 3348 | 3349 | [[package]] 3350 | name = "winapi-i686-pc-windows-gnu" 3351 | version = "0.4.0" 3352 | source = "registry+https://github.com/rust-lang/crates.io-index" 3353 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 3354 | 3355 | [[package]] 3356 | name = "winapi-util" 3357 | version = "0.1.9" 3358 | source = "registry+https://github.com/rust-lang/crates.io-index" 3359 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 3360 | dependencies = [ 3361 | "windows-sys 0.59.0", 3362 | ] 3363 | 3364 | [[package]] 3365 | name = "winapi-x86_64-pc-windows-gnu" 3366 | version = "0.4.0" 3367 | source = "registry+https://github.com/rust-lang/crates.io-index" 3368 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 3369 | 3370 | [[package]] 3371 | name = "windows" 3372 | version = "0.57.0" 3373 | source = "registry+https://github.com/rust-lang/crates.io-index" 3374 | checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" 3375 | dependencies = [ 3376 | "windows-core 0.57.0", 3377 | "windows-targets", 3378 | ] 3379 | 3380 | [[package]] 3381 | name = "windows-core" 3382 | version = "0.52.0" 3383 | source = "registry+https://github.com/rust-lang/crates.io-index" 3384 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 3385 | dependencies = [ 3386 | "windows-targets", 3387 | ] 3388 | 3389 | [[package]] 3390 | name = "windows-core" 3391 | version = "0.57.0" 3392 | source = "registry+https://github.com/rust-lang/crates.io-index" 3393 | checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" 3394 | dependencies = [ 3395 | "windows-implement", 3396 | "windows-interface", 3397 | "windows-result 0.1.2", 3398 | "windows-targets", 3399 | ] 3400 | 3401 | [[package]] 3402 | name = "windows-implement" 3403 | version = "0.57.0" 3404 | source = "registry+https://github.com/rust-lang/crates.io-index" 3405 | checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" 3406 | dependencies = [ 3407 | "proc-macro2", 3408 | "quote", 3409 | "syn 2.0.87", 3410 | ] 3411 | 3412 | [[package]] 3413 | name = "windows-interface" 3414 | version = "0.57.0" 3415 | source = "registry+https://github.com/rust-lang/crates.io-index" 3416 | checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" 3417 | dependencies = [ 3418 | "proc-macro2", 3419 | "quote", 3420 | "syn 2.0.87", 3421 | ] 3422 | 3423 | [[package]] 3424 | name = "windows-registry" 3425 | version = "0.2.0" 3426 | source = "registry+https://github.com/rust-lang/crates.io-index" 3427 | checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" 3428 | dependencies = [ 3429 | "windows-result 0.2.0", 3430 | "windows-strings", 3431 | "windows-targets", 3432 | ] 3433 | 3434 | [[package]] 3435 | name = "windows-result" 3436 | version = "0.1.2" 3437 | source = "registry+https://github.com/rust-lang/crates.io-index" 3438 | checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" 3439 | dependencies = [ 3440 | "windows-targets", 3441 | ] 3442 | 3443 | [[package]] 3444 | name = "windows-result" 3445 | version = "0.2.0" 3446 | source = "registry+https://github.com/rust-lang/crates.io-index" 3447 | checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" 3448 | dependencies = [ 3449 | "windows-targets", 3450 | ] 3451 | 3452 | [[package]] 3453 | name = "windows-strings" 3454 | version = "0.1.0" 3455 | source = "registry+https://github.com/rust-lang/crates.io-index" 3456 | checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" 3457 | dependencies = [ 3458 | "windows-result 0.2.0", 3459 | "windows-targets", 3460 | ] 3461 | 3462 | [[package]] 3463 | name = "windows-sys" 3464 | version = "0.52.0" 3465 | source = "registry+https://github.com/rust-lang/crates.io-index" 3466 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 3467 | dependencies = [ 3468 | "windows-targets", 3469 | ] 3470 | 3471 | [[package]] 3472 | name = "windows-sys" 3473 | version = "0.59.0" 3474 | source = "registry+https://github.com/rust-lang/crates.io-index" 3475 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 3476 | dependencies = [ 3477 | "windows-targets", 3478 | ] 3479 | 3480 | [[package]] 3481 | name = "windows-targets" 3482 | version = "0.52.6" 3483 | source = "registry+https://github.com/rust-lang/crates.io-index" 3484 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 3485 | dependencies = [ 3486 | "windows_aarch64_gnullvm", 3487 | "windows_aarch64_msvc", 3488 | "windows_i686_gnu", 3489 | "windows_i686_gnullvm", 3490 | "windows_i686_msvc", 3491 | "windows_x86_64_gnu", 3492 | "windows_x86_64_gnullvm", 3493 | "windows_x86_64_msvc", 3494 | ] 3495 | 3496 | [[package]] 3497 | name = "windows_aarch64_gnullvm" 3498 | version = "0.52.6" 3499 | source = "registry+https://github.com/rust-lang/crates.io-index" 3500 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 3501 | 3502 | [[package]] 3503 | name = "windows_aarch64_msvc" 3504 | version = "0.52.6" 3505 | source = "registry+https://github.com/rust-lang/crates.io-index" 3506 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 3507 | 3508 | [[package]] 3509 | name = "windows_i686_gnu" 3510 | version = "0.52.6" 3511 | source = "registry+https://github.com/rust-lang/crates.io-index" 3512 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 3513 | 3514 | [[package]] 3515 | name = "windows_i686_gnullvm" 3516 | version = "0.52.6" 3517 | source = "registry+https://github.com/rust-lang/crates.io-index" 3518 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 3519 | 3520 | [[package]] 3521 | name = "windows_i686_msvc" 3522 | version = "0.52.6" 3523 | source = "registry+https://github.com/rust-lang/crates.io-index" 3524 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 3525 | 3526 | [[package]] 3527 | name = "windows_x86_64_gnu" 3528 | version = "0.52.6" 3529 | source = "registry+https://github.com/rust-lang/crates.io-index" 3530 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 3531 | 3532 | [[package]] 3533 | name = "windows_x86_64_gnullvm" 3534 | version = "0.52.6" 3535 | source = "registry+https://github.com/rust-lang/crates.io-index" 3536 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 3537 | 3538 | [[package]] 3539 | name = "windows_x86_64_msvc" 3540 | version = "0.52.6" 3541 | source = "registry+https://github.com/rust-lang/crates.io-index" 3542 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 3543 | 3544 | [[package]] 3545 | name = "write16" 3546 | version = "1.0.0" 3547 | source = "registry+https://github.com/rust-lang/crates.io-index" 3548 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 3549 | 3550 | [[package]] 3551 | name = "writeable" 3552 | version = "0.5.5" 3553 | source = "registry+https://github.com/rust-lang/crates.io-index" 3554 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 3555 | 3556 | [[package]] 3557 | name = "xxhash-rust" 3558 | version = "0.8.12" 3559 | source = "registry+https://github.com/rust-lang/crates.io-index" 3560 | checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" 3561 | 3562 | [[package]] 3563 | name = "yoke" 3564 | version = "0.7.4" 3565 | source = "registry+https://github.com/rust-lang/crates.io-index" 3566 | checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" 3567 | dependencies = [ 3568 | "serde", 3569 | "stable_deref_trait", 3570 | "yoke-derive", 3571 | "zerofrom", 3572 | ] 3573 | 3574 | [[package]] 3575 | name = "yoke-derive" 3576 | version = "0.7.4" 3577 | source = "registry+https://github.com/rust-lang/crates.io-index" 3578 | checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" 3579 | dependencies = [ 3580 | "proc-macro2", 3581 | "quote", 3582 | "syn 2.0.87", 3583 | "synstructure", 3584 | ] 3585 | 3586 | [[package]] 3587 | name = "zerocopy" 3588 | version = "0.7.35" 3589 | source = "registry+https://github.com/rust-lang/crates.io-index" 3590 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 3591 | dependencies = [ 3592 | "byteorder", 3593 | "zerocopy-derive", 3594 | ] 3595 | 3596 | [[package]] 3597 | name = "zerocopy-derive" 3598 | version = "0.7.35" 3599 | source = "registry+https://github.com/rust-lang/crates.io-index" 3600 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 3601 | dependencies = [ 3602 | "proc-macro2", 3603 | "quote", 3604 | "syn 2.0.87", 3605 | ] 3606 | 3607 | [[package]] 3608 | name = "zerofrom" 3609 | version = "0.1.4" 3610 | source = "registry+https://github.com/rust-lang/crates.io-index" 3611 | checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" 3612 | dependencies = [ 3613 | "zerofrom-derive", 3614 | ] 3615 | 3616 | [[package]] 3617 | name = "zerofrom-derive" 3618 | version = "0.1.4" 3619 | source = "registry+https://github.com/rust-lang/crates.io-index" 3620 | checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" 3621 | dependencies = [ 3622 | "proc-macro2", 3623 | "quote", 3624 | "syn 2.0.87", 3625 | "synstructure", 3626 | ] 3627 | 3628 | [[package]] 3629 | name = "zeroize" 3630 | version = "1.8.1" 3631 | source = "registry+https://github.com/rust-lang/crates.io-index" 3632 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 3633 | 3634 | [[package]] 3635 | name = "zerovec" 3636 | version = "0.10.4" 3637 | source = "registry+https://github.com/rust-lang/crates.io-index" 3638 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 3639 | dependencies = [ 3640 | "yoke", 3641 | "zerofrom", 3642 | "zerovec-derive", 3643 | ] 3644 | 3645 | [[package]] 3646 | name = "zerovec-derive" 3647 | version = "0.10.3" 3648 | source = "registry+https://github.com/rust-lang/crates.io-index" 3649 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 3650 | dependencies = [ 3651 | "proc-macro2", 3652 | "quote", 3653 | "syn 2.0.87", 3654 | ] 3655 | 3656 | [[package]] 3657 | name = "zstd" 3658 | version = "0.13.2" 3659 | source = "registry+https://github.com/rust-lang/crates.io-index" 3660 | checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" 3661 | dependencies = [ 3662 | "zstd-safe", 3663 | ] 3664 | 3665 | [[package]] 3666 | name = "zstd-safe" 3667 | version = "7.2.1" 3668 | source = "registry+https://github.com/rust-lang/crates.io-index" 3669 | checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" 3670 | dependencies = [ 3671 | "zstd-sys", 3672 | ] 3673 | 3674 | [[package]] 3675 | name = "zstd-sys" 3676 | version = "2.0.13+zstd.1.5.6" 3677 | source = "registry+https://github.com/rust-lang/crates.io-index" 3678 | checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" 3679 | dependencies = [ 3680 | "cc", 3681 | "pkg-config", 3682 | ] 3683 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "polars-trading" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | name = "polars_trading" 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | pyo3 = { version = "*", features = ["extension-module", "abi3-py38"] } 12 | pyo3-polars = { version = "*", features = ["derive", "dtype-struct"] } 13 | serde = { version = "1", features = ["derive"] } 14 | polars = { version = "*", features = ["dtype-struct"] } 15 | num = "0.4.3" 16 | polars-arrow = "*" 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash 2 | 3 | install: 4 | unset CONDA_PREFIX && \ 5 | source .venv/bin/activate && maturin develop 6 | 7 | install-release: 8 | unset CONDA_PREFIX && \ 9 | source .venv/bin/activate && maturin develop --release 10 | 11 | pre-commit: 12 | cargo +nightly fmt --all && cargo clippy --all-features 13 | .venv/bin/python -m ruff check . --fix --exit-non-zero-on-fix 14 | .venv/bin/python -m ruff format polars_trading tests 15 | .venv/bin/mypy polars_trading tests 16 | 17 | test: 18 | .venv/bin/python -m pytest tests 19 | 20 | run: install 21 | source .venv/bin/activate && python run.py 22 | 23 | run-release: install-release 24 | source .venv/bin/activate && python run.py 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Polars Trading 2 | [![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/ngriffiths13/polars-trading) 3 | [![codecov](https://codecov.io/github/ngriffiths13/polars-trading/graph/badge.svg?token=T0BPP3DAD3)](https://codecov.io/github/ngriffiths13/polars-trading) 4 | -------------------------------------------------------------------------------- /polars_trading/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from polars_trading._internal import __version__ as __version__ 4 | -------------------------------------------------------------------------------- /polars_trading/_internal.pyi: -------------------------------------------------------------------------------- 1 | __version__: str 2 | -------------------------------------------------------------------------------- /polars_trading/_testing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngriffiths13/polars-trading/9ba592b3f0cc82f808420066bbd31099345cbc8e/polars_trading/_testing/__init__.py -------------------------------------------------------------------------------- /polars_trading/_testing/data.py: -------------------------------------------------------------------------------- 1 | from functools import lru_cache 2 | 3 | import polars as pl 4 | from mimesis import Fieldset, Finance 5 | from mimesis.locales import Locale 6 | 7 | 8 | @lru_cache 9 | def generate_trade_data(n_rows: int, n_companies: int = 3) -> pl.DataFrame: 10 | fs = Fieldset(locale=Locale.EN, i=n_rows) 11 | 12 | return pl.DataFrame( 13 | { 14 | "ts_event": fs( 15 | "datetime", 16 | ), 17 | "price": fs("finance.price", minimum=1, maximum=100), 18 | "size": fs("numeric.integer_number", start=10_000, end=100_000), 19 | "symbol": fs( 20 | "choice.choice", 21 | items=[Finance().stock_ticker() for _ in range(n_companies)], 22 | ), 23 | } 24 | ) 25 | -------------------------------------------------------------------------------- /polars_trading/_testing/features.py: -------------------------------------------------------------------------------- 1 | """Implementations of feature functionality in Pandas from AFML.""" 2 | 3 | import numpy as np 4 | import pandas as pd 5 | 6 | 7 | def get_weights_ffd(d: float, thresh: float) -> np.ndarray: 8 | """Calculate weights for frac_diff_ffd. 9 | 10 | Args: 11 | d: The fractional difference. 12 | thresh: The threshold. 13 | 14 | Returns: 15 | np.array: The weights. 16 | """ 17 | w = [1.0] 18 | k = 1 19 | while True: 20 | w_ = -w[-1] / k * (d - k + 1) 21 | if abs(w_) < thresh: 22 | break 23 | w.append(w_) 24 | k += 1 25 | return np.array(w[::-1]).reshape(-1, 1) 26 | 27 | 28 | def frac_diff_ffd(series: pd.DataFrame, d: float, thresh: float = 1e-5) -> pd.DataFrame: 29 | """Calculate the fractional difference of a series. 30 | 31 | Args: 32 | series: The series. 33 | d: The fractional difference. 34 | thresh: The threshold. 35 | 36 | Returns: 37 | pd.DataFrame: The fractional difference. 38 | """ 39 | w = get_weights_ffd(d, thresh) 40 | width = len(w) - 1 41 | df = {} 42 | for name in series.columns: 43 | series_f = series[[name]].ffill().dropna() 44 | df_ = pd.Series() 45 | for iloc1 in range(width, series_f.shape[0]): 46 | loc0 = series_f.index[iloc1 - width] 47 | loc1 = series_f.index[iloc1] 48 | df_[loc1] = np.dot(w.T, series_f.loc[loc0:loc1])[0, 0] 49 | df[name] = df_.copy(deep=True) 50 | return pd.concat(df, axis=1) 51 | -------------------------------------------------------------------------------- /polars_trading/_testing/labels.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | def get_daily_vol(close: pd.Series, span0: int = 100) -> pd.Series: 5 | # This function calculates returns as close to 24 hours ago as possible and then 6 | # calculates the exponentially weighted moving standard deviation of those returns. 7 | close = close.sort_index().copy() 8 | df0 = close.index.searchsorted(close.index - pd.Timedelta(days=1)) 9 | df0 = df0[df0 > 0] 10 | df0 = pd.Series( 11 | close.index[df0 - 1], index=close.index[close.shape[0] - df0.shape[0] :] 12 | ) 13 | df0 = close.loc[df0.index] / close.loc[df0.values].values - 1 14 | return df0.ewm(span=span0).std().fillna(0.0) 15 | 16 | 17 | def apply_pt_sl_on_t1( 18 | close: pd.Series, events: pd.DataFrame, pt_sl: tuple[float, float] 19 | ) -> pd.DataFrame: 20 | """Apply stop loss and profit taking. 21 | 22 | AFML pg. 45 23 | """ 24 | out = events[["t1"]].copy(deep=True) 25 | pt = pt_sl[0] * events["trgt"] if pt_sl[0] > 0 else pd.Series(index=events.index) 26 | sl = -pt_sl[1] * events["trgt"] if pt_sl[1] > 0 else pd.Series(index=events.index) 27 | 28 | for loc, t1 in events["t1"].fillna(close.index[-1]).items(): 29 | df0 = close[loc:t1] # path prices 30 | df0 = (df0 / close[loc] - 1) * events.at[loc, "side"] # path returns 31 | out.loc[loc, "sl"] = df0[df0 < sl[loc]].index.min() # earliest stop loss 32 | out.loc[loc, "pt"] = df0[df0 < pt[loc]].index.min() # earliest profit taking 33 | return out 34 | -------------------------------------------------------------------------------- /polars_trading/_utils.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | from functools import wraps 3 | from pathlib import Path 4 | from typing import Callable 5 | 6 | import polars as pl 7 | 8 | from polars_trading.typing import FrameType, IntoExpr 9 | 10 | LIB = Path(__file__).parent 11 | 12 | 13 | def validate_columns(*column_args: str) -> Callable: 14 | """Validate that the specified columns exist in the dataframe. 15 | 16 | Args: 17 | ---- 18 | *column_args: str - The column names to validate. 19 | 20 | Returns: 21 | ------- 22 | Callable 23 | 24 | """ 25 | 26 | def decorator(func: Callable) -> Callable: 27 | """Decorate validation of columns in a polars DataFrame. 28 | 29 | Args: 30 | ---- 31 | func: Callable 32 | 33 | Returns: 34 | ------- 35 | Callable 36 | 37 | """ 38 | 39 | @wraps(func) 40 | def wrapper(*args: FrameType, **kwargs: str) -> Callable: 41 | """Validate that the specified columns exist in the dataframe. 42 | 43 | Args: 44 | ---- 45 | *args: DataFrameTypes 46 | The first argument must be a polars DataFrame. 47 | **kwargs: str 48 | The column names to validate. 49 | 50 | Raises: 51 | ------ 52 | TypeError: If the first argument is not a polars DataFrame. 53 | ValueError: If any of the specified columns do not exist. 54 | 55 | Returns: 56 | ------- 57 | Callable 58 | 59 | """ 60 | # Get the dataframe from args or kwargs 61 | df = args[0] 62 | 63 | if not isinstance(df, pl.DataFrame | pl.LazyFrame): 64 | msg = "First argument must be a polars DataFrame" 65 | raise TypeError(msg) 66 | 67 | func_kwargs = { 68 | k: v.default 69 | for k, v in inspect.signature(func).parameters.items() 70 | if v.default is not inspect.Parameter.empty 71 | } 72 | func_kwargs.update(kwargs) 73 | required_columns = [func_kwargs[a] for a in column_args] 74 | # Check if all specified columns exist in the dataframe 75 | missing_columns = [col for col in required_columns if col not in df.columns] 76 | if missing_columns: 77 | missing_col_str = ", ".join(missing_columns) 78 | msg = f"Missing columns: {missing_col_str}" 79 | raise ValueError(msg) 80 | 81 | return func(*args, **kwargs) 82 | 83 | return wrapper 84 | 85 | return decorator 86 | 87 | 88 | def parse_into_expr(expr: IntoExpr) -> pl.Expr: 89 | """Parse a string into a polars expression. 90 | 91 | Args: 92 | ---- 93 | expr: IntoExpr - The expression to parse. 94 | 95 | Returns: 96 | ------- 97 | pl.Expr 98 | 99 | """ 100 | match expr: 101 | case pl.Expr(): 102 | pass 103 | case str(): 104 | expr = pl.col(expr) 105 | case _: 106 | expr = pl.lit(expr) 107 | return expr 108 | -------------------------------------------------------------------------------- /polars_trading/bars.py: -------------------------------------------------------------------------------- 1 | """Module containing functions to generate different types of bars.""" 2 | 3 | import polars as pl 4 | from polars.plugins import register_plugin_function 5 | 6 | from polars_trading._utils import LIB, validate_columns 7 | from polars_trading.typing import FrameType, IntoExpr 8 | 9 | 10 | def _bar_groups_expr(expr: IntoExpr, bar_size: float) -> pl.Expr: 11 | """Generate bar groups for a given expression. 12 | 13 | This expression will return a struct column with 2 fields: `id` and `amount`. 14 | These represent the group id field and the amount of the original value 15 | included in that group. 16 | 17 | This is intended to be used within a workflow and not by itself. The idea 18 | is that after generating the bar groups, you can make a duplicate row 19 | for each row where the amount does not equal the original input value and 20 | update the value to be the amount for the first one and the remainder for 21 | the duplicate. Then you can genrate your bars. 22 | 23 | Args: 24 | ---- 25 | expr (IntoExpr): The expression to generate bar groups for. 26 | bar_size (float): The size of the bars to generate. 27 | 28 | Returns: 29 | ------- 30 | pl.Expr: The expression with bar groups. 31 | 32 | """ 33 | return register_plugin_function( 34 | plugin_path=LIB, 35 | args=[expr], 36 | kwargs={"bar_size": bar_size}, 37 | is_elementwise=False, 38 | function_name="bar_groups", 39 | ) 40 | 41 | 42 | def _ohlcv_expr(timestamp_col: str, price_col: str, size_col: str) -> list[pl.Expr]: 43 | return [ 44 | pl.first(timestamp_col).name.suffix("_start"), 45 | pl.last(timestamp_col).name.suffix("_end"), 46 | pl.first(price_col).alias("open"), 47 | pl.max(price_col).alias("high"), 48 | pl.min(price_col).alias("low"), 49 | pl.last(price_col).alias("close"), 50 | ((pl.col(size_col) * pl.col(price_col)).sum() / pl.col(size_col).sum()).alias( 51 | "vwap" 52 | ), 53 | pl.sum(size_col).alias("volume"), 54 | pl.len().alias("n_trades"), 55 | ] 56 | 57 | 58 | @validate_columns("timestamp_col", "price_col", "size_col", "symbol_col") 59 | def time_bars( 60 | df: FrameType, 61 | *, 62 | timestamp_col: str, 63 | price_col: str = "price", 64 | size_col: str = "size", 65 | symbol_col: str = "symbol", 66 | bar_size: str = "1m", 67 | ) -> FrameType: 68 | """Generate time bars for a given DataFrame. 69 | 70 | Args: 71 | ---- 72 | df (FrameType): The DataFrame/LazyFrame to generate standard bars for. 73 | timestamp_col (str): The name of the timestamp column in the DataFrame. 74 | price_col (str, optional): The name of the price column in the DataFrame. 75 | Defaults to "price". 76 | size_col (str, optional): The name of the size column in the DataFrame. 77 | Defaults to "size". 78 | symbol_col (str, optional): The name of the symbol column in the DataFrame. 79 | Defaults to "symbol". 80 | bar_size (str, optional): The size of the bars to generate. 81 | Can use any number followed by a time symbol. For example: 82 | 83 | 1s = 1 second 84 | 2m = 2 minutes 85 | 3h = 3 hours 86 | 4d = 4 days 87 | 5w = 5 weeks 88 | 89 | Defaults to "1m". 90 | 91 | Returns: 92 | ------- 93 | FrameType: The DataFrame/LazyFrame with time bars. 94 | 95 | """ 96 | return ( 97 | df.drop_nulls(subset=price_col) 98 | .sort(timestamp_col) 99 | .with_columns(pl.col(timestamp_col).dt.truncate(bar_size).alias("__time_group")) 100 | .group_by("__time_group", symbol_col) 101 | .agg( 102 | *_ohlcv_expr(timestamp_col, price_col, size_col), 103 | ) 104 | .rename({"__time_group": timestamp_col}) 105 | .sort(f"{timestamp_col}_end") 106 | ) 107 | 108 | 109 | @validate_columns("timestamp_col", "price_col", "size_col", "symbol_col") 110 | def tick_bars( 111 | df: FrameType, 112 | *, 113 | timestamp_col: str, 114 | price_col: str = "price", 115 | size_col: str = "size", 116 | symbol_col: str = "symbol", 117 | bar_size: int = 100, 118 | split_by_date: bool = True, 119 | ) -> FrameType: 120 | """Generate tick bars for a given DataFrame. 121 | 122 | The function takes a DataFrame, a timestamp column, a price column, a size column, 123 | a symbol column, and a bar size as input. 124 | The bar size is the number of ticks that will be aggregated into a single bar. 125 | This function will never overlap bars between different days. 126 | 127 | Args: 128 | ---- 129 | df (FrameType): The DataFrame/LazyFrame to generate tick bars for. 130 | timestamp_col (str): The name of the timestamp column in the DataFrame. 131 | price_col (str): The name of the price column in the DataFrame. 132 | size_col (str): The name of the size column in the DataFrame. 133 | symbol_col (str): The name of the symbol column in the DataFrame. 134 | bar_size (int): The number of ticks to aggregate into a single bar. 135 | split_by_date (bool): Whether to split bars by date or not. 136 | 137 | Returns: 138 | ------- 139 | FrameType: The DataFrame/LazyFrame with tick bars. 140 | 141 | """ 142 | over_cols = [symbol_col] 143 | ohlcv = df.drop_nulls(subset=price_col).sort(timestamp_col) 144 | if split_by_date: 145 | ohlcv = ohlcv.with_columns(pl.col(timestamp_col).dt.date().alias("__date")) 146 | over_cols.append("__date") 147 | 148 | ohlcv = ohlcv.with_columns( 149 | (((pl.col(symbol_col).cum_count()).over(*over_cols) - 1) // bar_size).alias( 150 | "__tick_group", 151 | ) 152 | ) 153 | 154 | bars = ( 155 | ohlcv.group_by("__tick_group", *over_cols) 156 | .agg(*_ohlcv_expr(timestamp_col, price_col, size_col)) 157 | .drop("__tick_group") 158 | .sort(f"{timestamp_col}_end") 159 | ) 160 | if split_by_date: 161 | bars = bars.drop("__date") 162 | return bars 163 | 164 | 165 | @validate_columns("timestamp_col", "price_col", "size_col", "symbol_col") 166 | def volume_bars( 167 | df: FrameType, 168 | *, 169 | timestamp_col: str, 170 | price_col: str = "price", 171 | size_col: str = "size", 172 | symbol_col: str = "symbol", 173 | bar_size: int = 10_000, 174 | split_by_date: bool = True, 175 | ) -> FrameType: 176 | """Generate tick bars for a given DataFrame. 177 | 178 | The function takes a DataFrame, a timestamp column, a price column, a size column, 179 | a symbol column, and a bar size as input. 180 | The bar size is the volume that will be aggregated into a single bar. 181 | This function will never overlap bars between different days. 182 | 183 | Args: 184 | ---- 185 | df (FrameType): The DataFrame/LazyFrame to generate tick bars for. 186 | timestamp_col (str): The name of the timestamp column in the DataFrame. 187 | price_col (str): The name of the price column in the DataFrame. 188 | size_col (str): The name of the size column in the DataFrame. 189 | symbol_col (str): The name of the symbol column in the DataFrame. 190 | bar_size (int): The volume to aggregate into a single bar. 191 | split_by_date (bool): Whether to split bars by date or not. 192 | 193 | Returns: 194 | ------- 195 | FrameType: The DataFrame/LazyFrame with tick bars. 196 | 197 | """ 198 | over_cols = [symbol_col] 199 | ohlcv = df.drop_nulls(subset=price_col).sort(timestamp_col) 200 | if split_by_date: 201 | ohlcv = ohlcv.with_columns(pl.col(timestamp_col).dt.date().alias("__date")) 202 | over_cols.append("__date") 203 | 204 | ohlcv = ohlcv.with_columns( 205 | _bar_groups_expr(size_col, bar_size).over(*over_cols).alias("__bar_groups") 206 | ).unnest("__bar_groups") 207 | 208 | bars = ( 209 | ohlcv.vstack( 210 | ohlcv.filter(pl.col(size_col) != pl.col("bar_group__amount")).with_columns( 211 | pl.col(size_col) 212 | .sub(pl.col("bar_group__amount")) 213 | .alias("bar_group__amount"), 214 | pl.col("bar_group__id") + 1, 215 | ) 216 | ) 217 | .select( 218 | pl.all().exclude(size_col, "bar_group__amount"), 219 | pl.col("bar_group__amount").alias(size_col), 220 | ) 221 | .group_by(*over_cols, "bar_group__id") 222 | .agg(_ohlcv_expr(timestamp_col, price_col, size_col)) 223 | .drop("bar_group__id") 224 | .sort(f"{timestamp_col}_end") 225 | ) 226 | if split_by_date: 227 | bars = bars.drop("__date") 228 | return bars 229 | 230 | 231 | @validate_columns("timestamp_col", "price_col", "size_col", "symbol_col") 232 | def dollar_bars( 233 | df: FrameType, 234 | *, 235 | timestamp_col: str, 236 | price_col: str = "price", 237 | size_col: str = "size", 238 | symbol_col: str = "symbol", 239 | bar_size: int = 1_000_000, 240 | split_by_date: bool = True, 241 | ) -> FrameType: 242 | """Generate tick bars for a given DataFrame. 243 | 244 | The function takes a DataFrame, a timestamp column, a price column, a size column, 245 | a symbol column, and a bar size as input. 246 | The bar size is the dollar volume that will be aggregated into a single bar. 247 | This function will never overlap bars between different days. 248 | 249 | Args: 250 | ---- 251 | df (FrameType): The DataFrame/LazyFrame to generate tick bars for. 252 | timestamp_col (str): The name of the timestamp column in the DataFrame. 253 | price_col (str): The name of the price column in the DataFrame. 254 | size_col (str): The name of the size column in the DataFrame. 255 | symbol_col (str): The name of the symbol column in the DataFrame. 256 | bar_size (int): The dollar volume to aggregate into a single bar. 257 | split_by_date (bool): Whether to split bars by date or not. 258 | 259 | Returns: 260 | ------- 261 | FrameType: The DataFrame/LazyFrame with dollar bars. 262 | 263 | """ 264 | over_cols = [symbol_col] 265 | ohlcv = ( 266 | df.drop_nulls(subset=price_col) 267 | .sort(timestamp_col) 268 | .with_columns( 269 | pl.col(price_col).mul(pl.col(size_col)).alias("__dollar_volume"), 270 | ) 271 | ) 272 | if split_by_date: 273 | ohlcv = ohlcv.with_columns(pl.col(timestamp_col).dt.date().alias("__date")) 274 | over_cols.append("__date") 275 | 276 | ohlcv = ( 277 | ohlcv.with_columns( 278 | _bar_groups_expr("__dollar_volume", bar_size) 279 | .over(*over_cols) 280 | .alias("__bar_groups") 281 | ) 282 | .unnest("__bar_groups") 283 | .with_columns( 284 | pl.col("bar_group__amount") 285 | .truediv(pl.col(price_col)) 286 | .alias("bar_group__amount"), 287 | ) 288 | ) 289 | 290 | bars = ( 291 | ohlcv.vstack( 292 | ohlcv.filter(pl.col(size_col) != pl.col("bar_group__amount")).with_columns( 293 | pl.col(size_col) 294 | .sub(pl.col("bar_group__amount")) 295 | .alias("bar_group__amount"), 296 | pl.col("bar_group__id") + 1, 297 | ) 298 | ) 299 | .select( 300 | pl.all().exclude(size_col, "bar_group__amount"), 301 | pl.col("bar_group__amount").alias(size_col), 302 | ) 303 | .group_by(*over_cols, "bar_group__id") 304 | .agg(_ohlcv_expr(timestamp_col, price_col, size_col)) 305 | .drop("bar_group__id") 306 | .sort(f"{timestamp_col}_end") 307 | ) 308 | if split_by_date: 309 | bars = bars.drop("__date") 310 | return bars 311 | -------------------------------------------------------------------------------- /polars_trading/features/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngriffiths13/polars-trading/9ba592b3f0cc82f808420066bbd31099345cbc8e/polars_trading/features/__init__.py -------------------------------------------------------------------------------- /polars_trading/features/frac_diff.py: -------------------------------------------------------------------------------- 1 | """Module containing functions to generate fractionally differentiated features.""" 2 | 3 | import polars as pl 4 | from polars.plugins import register_plugin_function 5 | 6 | from polars_trading._utils import LIB 7 | from polars_trading.typing import IntoExpr 8 | 9 | 10 | def frac_diff(expr: IntoExpr, d: float, threshold: float) -> pl.Expr: 11 | """Generate expression to calculate the fractionally differentiated series. 12 | 13 | Args: 14 | ---- 15 | expr: IntoExpr - The expression to calculate the fractionally differentiated 16 | series. 17 | d: float - The fractional difference. 18 | threshold: float - The threshold. 19 | 20 | Returns: 21 | ------- 22 | pl.Expr: The expression to calculate the fractionally differentiated series. 23 | 24 | """ 25 | return register_plugin_function( 26 | plugin_path=LIB, 27 | args=[expr], 28 | kwargs={"d": d, "threshold": threshold}, 29 | is_elementwise=False, 30 | function_name="frac_diff", 31 | ) 32 | -------------------------------------------------------------------------------- /polars_trading/labels/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngriffiths13/polars-trading/9ba592b3f0cc82f808420066bbd31099345cbc8e/polars_trading/labels/__init__.py -------------------------------------------------------------------------------- /polars_trading/labels/dynamic_labels.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from datetime import timedelta 4 | from typing import TYPE_CHECKING 5 | 6 | import polars as pl 7 | 8 | from polars_trading._utils import validate_columns 9 | 10 | if TYPE_CHECKING: 11 | from polars_trading.typing import FrameType 12 | 13 | 14 | def daily_vol( 15 | df: FrameType, 16 | timestamp_col: str, 17 | price_col: str, 18 | symbol_col: str | None = None, 19 | span: int = 100, 20 | ) -> FrameType: 21 | """This function calculates the daily volatility of a price series. 22 | 23 | It uses an the daily volatiity by looking back at the return from the oldest price 24 | in the last 24 hour period to the current price. It then calculates the exponential 25 | weighted standard deviation of the returns. 26 | 27 | This currently fails to account for weekend returns when there is no trading. 28 | 29 | Marco Lopez de Prado, Advances in Financial Machine Learning, pg. 44 30 | 31 | Args: 32 | ---- 33 | df (DataFrame): The DataFrame containing the price series. 34 | timestamp_col (str): The column name containing the timestamps. 35 | price_col (str): The column name containing the prices. 36 | symbol_col (str | None): The column name containing the symbols. If None, it is 37 | assumed that the prices are for a single symbol. Defaults to None. 38 | span (int): The span of the exponential weighted standard deviation. Defaults to 39 | 100. 40 | 41 | Returns: 42 | FrameType: The DataFrame with the daily volatility. 43 | """ 44 | on_clause = [timestamp_col] if symbol_col is None else [timestamp_col, symbol_col] 45 | df = df.sort(timestamp_col) 46 | lagged_prices = df.select( 47 | *on_clause, 48 | (pl.col(timestamp_col) - timedelta(hours=24)).alias("lookback"), 49 | ).join_asof(df, left_on="lookback", right_on=timestamp_col, by=symbol_col) 50 | returns = df.join( 51 | lagged_prices.select(*on_clause, pl.col(price_col).alias("lookback_price")), 52 | on=on_clause, 53 | ).with_columns(pl.col(price_col).truediv("lookback_price").sub(1).alias("return")) 54 | vol_expr = ( 55 | pl.col("return") 56 | .ewm_std(span=span) 57 | .over(symbol_col) 58 | .alias("daily_return_volatility") 59 | ) 60 | return_cols = ( 61 | [ 62 | timestamp_col, 63 | symbol_col, 64 | vol_expr, 65 | ] 66 | if symbol_col 67 | else [ 68 | timestamp_col, 69 | vol_expr, 70 | ] 71 | ) 72 | 73 | return returns.select(*return_cols) 74 | 75 | 76 | def get_vertical_barrier_by_timedelta( 77 | df: FrameType, 78 | timestamp_col: str, 79 | offset: str | timedelta, 80 | symbol_col: str | None = None, 81 | ) -> FrameType: 82 | """Create a vertical barrier column. 83 | 84 | The vertical barrier column will be the first timestamp observation after the 85 | offset of the timestamp column. For example, if you have timestamps at: 86 | 2012-01-01 87 | 2012-01-02 88 | 2012-01-04 89 | And you offset by 1d, your vertical barriers will be: 90 | 2012-01-04 # This is the first timestamp after 2012-01-01 + 1 day 91 | 2012-01-04 92 | None 93 | 94 | Args: 95 | ---- 96 | df (DataFrame): The DataFrame containing the price series. 97 | timestamp_col (str): The column name containing the timestamps. 98 | offset (str | timedelta): A string denoting the offset or a timedelta object. 99 | If a string is passed, it should follow common polars formatting. 100 | symbol_col (str | None): The column name containing the symbols. If None, it is 101 | assumed that the prices are for a single symbol. Defaults to None. 102 | span (int): The span of the exponential weighted standard deviation. Defaults to 103 | 100. 104 | 105 | Returns: 106 | FrameType: The DataFrame with the vertical barrier. 107 | """ 108 | if isinstance(offset, str): 109 | offset_expr = pl.col(timestamp_col).dt.offset_by(offset) 110 | elif isinstance(offset, timedelta): 111 | offset_expr = pl.col(timestamp_col) + offset 112 | 113 | if symbol_col is None: 114 | offsets = df.select(timestamp_col, offset_expr.alias("offset")) 115 | else: 116 | offsets = df.select(symbol_col, timestamp_col, offset_expr.alias("offset")) 117 | 118 | if symbol_col is None: 119 | return offsets.join_asof( 120 | df.select(pl.col(timestamp_col).alias("vertical_barrier")), 121 | left_on="offset", 122 | right_on="vertical_barrier", 123 | strategy="forward", 124 | ).select(timestamp_col, "vertical_barrier") 125 | return offsets.join_asof( 126 | df.select(symbol_col, pl.col(timestamp_col).alias("vertical_barrier")), 127 | left_on="offset", 128 | right_on="vertical_barrier", 129 | strategy="forward", 130 | by=symbol_col, 131 | ).select(symbol_col, timestamp_col, "vertical_barrier") 132 | 133 | 134 | @validate_columns("timestamp_col", "price_col", "target_col") 135 | def apply_profit_taking_stop_loss( 136 | df: FrameType, 137 | timestamp_col: str, 138 | price_col: str, # noqa: ARG001 139 | target_col: str, 140 | vertical_barrier_col: str | None, 141 | profit_take: float | None = None, 142 | stop_loss: float | None = None, 143 | symbol_col: str | None = None, 144 | ) -> FrameType: 145 | out = df.sort(timestamp_col).with_columns( 146 | pl.col(target_col).mul(pl.lit(profit_take)).alias("__profit_take"), 147 | pl.col(target_col).mul(-pl.lit(stop_loss)).alias("__stop_loss"), 148 | ) 149 | 150 | if vertical_barrier_col is None: 151 | vertical_barrier_col = "__vertical_barier" 152 | out = out.with_columns(pl.lit(None).alias(vertical_barrier_col)) 153 | 154 | out = out.with_columns( 155 | pl.col(vertical_barrier_col).fill_null(pl.max(timestamp_col).over(symbol_col)) 156 | ) 157 | 158 | # TODO: Polars plugin here 159 | 160 | 161 | def get_triple_barrier_label() -> FrameType: 162 | """Calculate the triple barrier label. 163 | 164 | This function will take in the required parameters and return a DataFrame with the 165 | following columns: 166 | timestamp: The timestamp of the start of the data. 167 | touch_timestamp: The timestamp of the touch of the first barrier. 168 | return: The return between the timestamp and the touch timestamp. 169 | label: The label of the return. This can be done in two ways: 170 | - {1, 0, -1}: Which will indicate which barrier was first touched. 171 | - {1, -1}: Which will indicate which barrier was first touched or the sign 172 | of the return if the vertical barrier was touched first. 173 | """ 174 | -------------------------------------------------------------------------------- /polars_trading/labels/labels.py: -------------------------------------------------------------------------------- 1 | """This module contains functions to calculate labels for financial data.""" 2 | 3 | from __future__ import annotations 4 | 5 | from typing import TYPE_CHECKING 6 | 7 | import polars as pl 8 | 9 | from polars_trading._utils import parse_into_expr 10 | 11 | if TYPE_CHECKING: 12 | from polars_trading.typing import IntoExpr 13 | 14 | 15 | def _classify_by_threshold(values: pl.Expr, threshold: IntoExpr | None) -> pl.Expr: 16 | if threshold is None: 17 | return values.sign().cast(pl.Int32) 18 | threshold = parse_into_expr(threshold) 19 | return ( 20 | pl.when(values > threshold.abs()) 21 | .then(1) 22 | .when(values < -threshold.abs()) 23 | .then(-1) 24 | .when(values.is_between(-threshold.abs(), threshold.abs())) 25 | .then(0) 26 | .otherwise(None) 27 | ).cast(pl.Int32) 28 | 29 | 30 | def fixed_time_return_classification( 31 | prices: IntoExpr, 32 | window: int, 33 | threshold: IntoExpr | None = None, 34 | offset: int = 1, 35 | symbol: IntoExpr | None = None, 36 | ) -> pl.Expr: 37 | """Calculate the fixed time return as a classification label. 38 | 39 | This function calculates the fixed time return of a financial instrument. The 40 | return for time t is calculated as the percent change in the price at time 41 | t+{offset} to the price at time t+{offset + window}. The label is set to 1 if 42 | the return is greater than the threshold, -1 if the return is less than the 43 | negative threshold, and 0 otherwise. 44 | 45 | Args: 46 | ---- 47 | prices: IntoExpr - The prices of the financial instrument. 48 | window: int - The number of periods to look forward. 49 | threshold: IntoExpr | None - The threshold to classify the return. If None, 50 | the return is classified as the sign of the return. 51 | offset: int - The offset of the starting period. Defaults to 1. This is so by 52 | default we attempt to avoid lookahead bias. At time t, you ideally make a 53 | decision to capture the return from t+1 to t+1+window. This way you do not 54 | include the current price in your calculation that you likely can't execute 55 | at. 56 | symbol: IntoExpr | None - The symbol of the financial instrument. This is used 57 | to calculate returns for multiple symbols at once. If None, it is assumed 58 | that the prices are for a single symbol. 59 | 60 | Returns: 61 | ------- 62 | pl.Expr: The fixed time return classification label as an expression. 63 | """ 64 | return_expr = fixed_time_return(prices, window, offset) 65 | if symbol is not None: 66 | return_expr = return_expr.over(parse_into_expr(symbol)) 67 | return _classify_by_threshold(return_expr, threshold) 68 | 69 | 70 | def fixed_time_return( 71 | prices: IntoExpr, window: int, offset: int = 1, symbol: IntoExpr | None = None 72 | ) -> pl.Expr: 73 | """Calculate the fixed time return. 74 | 75 | This function calculates the fixed time return of a financial instrument. The 76 | return for time t is calculated as the percent change in the price at time 77 | t+{offset} to the price at time t+{offset + window}. 78 | 79 | Args: 80 | ---- 81 | prices: IntoExpr - The prices of the financial instrument. 82 | window: int - The number of periods to look forward. 83 | offset: int - The offset of the starting period. Defaults to 1. This is so by 84 | default we attempt to avoid lookahead bias. At time t, you ideally make a 85 | decision to capture the return from t+1 to t+1+window. This way you do not 86 | include the current price in your calculation that you likely can't execute 87 | at. 88 | symbol: IntoExpr | None - The symbol of the financial instrument. This is used 89 | to calculate returns for multiple symbols at once. If None, it is assumed 90 | that the prices are for a single symbol. 91 | 92 | Returns: 93 | ------- 94 | pl.Expr: The fixed time return as an expression. 95 | """ 96 | return_expr = ( 97 | parse_into_expr(prices) 98 | .shift(-offset - window) 99 | .truediv(parse_into_expr(prices).shift(-offset)) 100 | .sub(1) 101 | ) 102 | if symbol is not None: 103 | return_expr = return_expr.over(parse_into_expr(symbol)) 104 | return return_expr 105 | -------------------------------------------------------------------------------- /polars_trading/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngriffiths13/polars-trading/9ba592b3f0cc82f808420066bbd31099345cbc8e/polars_trading/py.typed -------------------------------------------------------------------------------- /polars_trading/typing.py: -------------------------------------------------------------------------------- 1 | """Type aliases for Polars DataFrame and Series objects.""" 2 | 3 | import sys 4 | from typing import TypeVar, Union 5 | 6 | import polars as pl 7 | 8 | if sys.version_info >= (3, 10): 9 | from typing import TypeAlias 10 | else: 11 | from typing_extensions import TypeAlias 12 | from polars._typing import IntoExpr as IntoExpr 13 | from polars.datatypes import DataType, DataTypeClass 14 | 15 | PolarsDataType: TypeAlias = Union[DataType, DataTypeClass] 16 | DataFrameTypes: TypeAlias = Union[pl.DataFrame, pl.LazyFrame] 17 | 18 | FrameType = TypeVar("FrameType", pl.DataFrame, pl.LazyFrame) 19 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["maturin>=1.0,<2.0", "polars>=1.3.0"] 3 | build-backend = "maturin" 4 | 5 | [project] 6 | name = "polars-trading" 7 | requires-python = ">=3.9" 8 | classifiers = [ 9 | "Programming Language :: Rust", 10 | "Programming Language :: Python :: Implementation :: CPython", 11 | "Programming Language :: Python :: Implementation :: PyPy", 12 | ] 13 | dependencies = ["polars[plot]>=1.3"] 14 | 15 | 16 | [tool.ruff.format] 17 | docstring-code-format = true 18 | 19 | [tool.ruff] 20 | lint.select = ["ALL"] 21 | lint.ignore = [ 22 | 'A003', 23 | 'ANN401', 24 | 'ARG002', # todo: enable 25 | 'ARG003', # todo: enable 26 | 'C901', 27 | 'COM812', 28 | 'D100', 29 | 'D103', 30 | 'D104', 31 | 'D105', 32 | 'D107', 33 | 'D203', 34 | 'D212', 35 | 'DTZ', 36 | 'E501', 37 | 'FBT003', # todo: enable 38 | 'FIX', 39 | 'ISC001', 40 | 'PD', 41 | 'PLR0911', 42 | 'PLR0912', 43 | 'PLR5501', 44 | 'PLR2004', 45 | 'PLR0913', 46 | 'PLC0414', 47 | 'PT011', 48 | 'PTH', 49 | 'RET505', 50 | 'S', 51 | 'SLF001', 52 | 'TD', 53 | 'TRY004', 54 | ] 55 | 56 | # Allow autofix for all enabled rules (when `--fix`) is provided. 57 | lint.fixable = ["ALL"] 58 | 59 | # Exclude a variety of commonly ignored directories. 60 | exclude = [ 61 | "tests", 62 | ".git", 63 | ".git-rewrite", 64 | ".mypy_cache", 65 | ".ruff_cache", 66 | "venv", 67 | ".ipynb", 68 | "venv", 69 | ] 70 | line-length = 88 71 | 72 | [tool.ruff.lint.pydocstyle] 73 | convention = "google" 74 | 75 | [tool.maturin] 76 | module-name = "polars_trading._internal" 77 | 78 | [[tool.mypy.overrides]] 79 | module = "polars.utils.udfs" 80 | ignore_missing_imports = true 81 | 82 | [tool.uv] 83 | dev-dependencies = [ 84 | "build>=1.2.1", 85 | "commitizen>=3.29.0", 86 | "marimo>=0.8.8", 87 | "mkdocs-gen-files>=0.5.0", 88 | "mkdocstrings[python]>=0.26.1", 89 | "pip>=24.2", 90 | "pre-commit>=3.8.0", 91 | "ruff>=0.6.3", 92 | "setuptools>=74.1.0", 93 | "wheel>=0.44.0", 94 | "pandas>=2.2.2", 95 | "pyarrow>=17.0.0", 96 | "pytest>=8.3.2", 97 | "pytest-benchmark[histogram]>=4.0.0", 98 | "pytest-codspeed>=2.2.1", 99 | "mimesis>=12.1.0", 100 | "pytest-cov>=5.0.0", 101 | "maturin>=1.7.4", 102 | ] 103 | 104 | [tool.commitizen] 105 | name = "cz_conventional_commits" 106 | tag_format = "$version" 107 | version_scheme = "semver2" 108 | version_provider = "cargo" 109 | update_changelog_on_bump = true 110 | major_version_zero = true 111 | 112 | [tool.pytest.ini_options] 113 | markers = ["pandas"] 114 | addopts = [ 115 | "--benchmark-disable", 116 | "--benchmark-columns=min,mean,median,max,stddev", 117 | "-m not pandas", 118 | "--cov=polars_trading", 119 | "--cov-report=term-missing", 120 | "--cov-fail-under=80", 121 | "--cov-config=pyproject.toml", 122 | ] 123 | [tool.coverage.run] 124 | omit = ["polars_trading/_testing/*"] 125 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | polars 2 | maturin 3 | ruff 4 | pytest 5 | mypy 6 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | group_imports = "StdExternalCrate" 2 | imports_granularity = "Module" 3 | match_block_trailing_comma = true 4 | -------------------------------------------------------------------------------- /src/bars.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::unused_unit)] 2 | use std::cmp::PartialOrd; 3 | 4 | use num::traits::{Signed, Zero}; 5 | use polars::prelude::*; 6 | use pyo3_polars::derive::polars_expr; 7 | use serde::Deserialize; 8 | 9 | fn create_row_groups(ca: &ChunkedArray, bar_size: T::Native) -> PolarsResult 10 | where 11 | T: PolarsNumericType, 12 | T::Native: Signed + Zero + PartialOrd, 13 | ChunkedArray: IntoSeries, 14 | { 15 | let mut row_group_ids: Vec = Vec::with_capacity(ca.len()); 16 | let mut row_group_amounts: Vec = Vec::with_capacity(ca.len()); 17 | let mut current_sum = T::Native::zero(); 18 | let mut group_id = 0; 19 | 20 | for val in ca.into_no_null_iter() { 21 | if current_sum + val >= bar_size { 22 | let remaining_amount = bar_size - current_sum; 23 | row_group_ids.push(group_id); 24 | row_group_amounts.push(remaining_amount); 25 | group_id += 1; 26 | current_sum = val - remaining_amount; 27 | } else { 28 | row_group_ids.push(group_id); 29 | row_group_amounts.push(val); 30 | current_sum += val; 31 | } 32 | } 33 | 34 | // Create ChunkedArrays 35 | let id_ca = Int32Chunked::new("bar_group__id".into(), &row_group_ids); 36 | let amount_ca = ChunkedArray::::from_slice("bar_group__amount".into(), &row_group_amounts); 37 | let length = id_ca.len(); 38 | 39 | // Create a StructChunked 40 | let fields = vec![id_ca.into_series(), amount_ca.into_series()]; 41 | 42 | StructChunked::from_series("row_groups".into(), length, fields.iter()) 43 | } 44 | 45 | #[derive(Deserialize)] 46 | struct BarGroupKwargs { 47 | bar_size: f64, 48 | } 49 | 50 | fn bar_group_struct(input_fields: &[Field]) -> PolarsResult { 51 | Ok(Field::new( 52 | input_fields[0].name().clone(), 53 | DataType::Struct(vec![ 54 | Field::new("bar_group__id".into(), DataType::Int32), 55 | Field::new("bar_group__amount".into(), input_fields[0].dtype().clone()), 56 | ]), 57 | )) 58 | } 59 | 60 | #[polars_expr(output_type_func=bar_group_struct)] 61 | fn bar_groups(inputs: &[Series], kwargs: BarGroupKwargs) -> PolarsResult { 62 | let groups = match inputs[0].dtype() { 63 | DataType::Float64 => create_row_groups(inputs[0].f64().unwrap(), kwargs.bar_size)?, 64 | DataType::Float32 => create_row_groups(inputs[0].f32().unwrap(), kwargs.bar_size as f32)?, 65 | DataType::Int64 => create_row_groups(inputs[0].i64().unwrap(), kwargs.bar_size as i64)?, 66 | DataType::Int32 => create_row_groups(inputs[0].i32().unwrap(), kwargs.bar_size as i32)?, 67 | _ => return Err(PolarsError::ComputeError("Unsupported type".into())), 68 | }; 69 | Ok(groups.into_series()) 70 | } 71 | -------------------------------------------------------------------------------- /src/frac_diff.rs: -------------------------------------------------------------------------------- 1 | use polars::prelude::*; 2 | use polars_arrow::bitmap::MutableBitmap; 3 | use pyo3_polars::derive::polars_expr; 4 | 5 | use serde::Deserialize; 6 | 7 | pub fn get_weights_ffd(d: f64, threshold: f64) -> Vec { 8 | let mut w = vec![1.]; 9 | let mut k = 1.0; 10 | loop { 11 | let w_: f64 = -w.last().unwrap() / k * (d - k + 1.0); 12 | if w_.abs() < threshold { 13 | break; 14 | } 15 | w.push(w_); 16 | k += 1.0; 17 | } 18 | w.reverse(); 19 | w 20 | } 21 | 22 | fn dot_product(a: &[f64], b: &[f64]) -> f64 { 23 | a.iter().zip(b.iter()).map(|(a, b)| a * b).sum() 24 | } 25 | 26 | #[derive(Deserialize)] 27 | struct FracDiffKwargs { 28 | d: f64, 29 | threshold: f64, 30 | } 31 | 32 | #[polars_expr(output_type=Float64)] 33 | fn frac_diff(inputs: &[Series], kwargs: FracDiffKwargs) -> PolarsResult { 34 | let prices = inputs[0].f64().unwrap().to_vec_null_aware(); 35 | let prices = if prices.is_left() { 36 | prices.left().unwrap() 37 | } else { 38 | return Err(PolarsError::InvalidOperation("Null price found".into())); 39 | }; 40 | let weights = get_weights_ffd(kwargs.d, kwargs.threshold); 41 | let n_weights = weights.len(); 42 | let mut outputs: Vec = Vec::with_capacity(prices.len()); 43 | let mut validity_mask = MutableBitmap::with_capacity(prices.len()); 44 | validity_mask.extend_constant(prices.len(), true); 45 | for i in 0..prices.len() { 46 | if i < (n_weights - 1) { 47 | outputs.push(0.0); 48 | validity_mask.set(i, false); 49 | } else { 50 | let window = &prices[i + 1 - n_weights..i + 1]; 51 | let output = dot_product(window, &weights); 52 | outputs.push(output); 53 | } 54 | } 55 | Ok( 56 | Float64Chunked::from_vec_validity("frac_diff".into(), outputs, validity_mask.into()) 57 | .into_series(), 58 | ) 59 | } 60 | -------------------------------------------------------------------------------- /src/labels.rs: -------------------------------------------------------------------------------- 1 | // #![allow(clippy::unused_unit)] 2 | // use std::cmp::PartialOrd; 3 | 4 | // use polars::prelude::*; 5 | // use pyo3_polars::derive::polars_expr; 6 | // use serde::Deserialize; 7 | 8 | // fn apply_profit_taking_stop_loss( 9 | // index: &ChunkedArray, 10 | // prices: &Float64Chunked, 11 | // profit_taking: &Float64Chunked, 12 | // stop_loss: &Float64Chunked, 13 | // ) -> (Option, Option) 14 | // where 15 | // T: PartialOrd + Clone, 16 | // { 17 | // let returns: Vec = prices 18 | // .iter() 19 | // .map(|x| x.unwrap() / prices.get(0).unwrap() - 1.0) 20 | // .collect(); 21 | // // Get the minimum index where profit take is greater than returns 22 | // let profit_taking_index = returns 23 | // .iter() 24 | // .zip(profit_taking.iter()) 25 | // .position(|(&ret, &pt)| ret >= pt); 26 | // let stop_loss_index = returns 27 | // .iter() 28 | // .zip(stop_loss.iter()) 29 | // .position(|(&ret, &sl)| ret <= sl); 30 | 31 | // match (profit_taking_index, stop_loss_index) { 32 | // (Some(pt), Some(sl)) => { 33 | // return ( 34 | // Some(index.get(pt).unwrap().clone()), 35 | // Some(index.get(sl).unwrap().clone()), 36 | // ) 37 | // }, 38 | // (Some(pt), None) => return (Some(index.get(pt).unwrap().clone()), None), 39 | // (None, Some(sl)) => return (None, Some(index.get(sl).unwrap().clone())), 40 | // (None, None) => return (None, None), 41 | // } 42 | // } 43 | 44 | // fn barrier_touch_struct(input_fields: &[Field]) -> PolarsResult { 45 | // let dtype = input_fields[0].data_type(); 46 | // Ok(Field::new( 47 | // input_fields[0].name(), 48 | // DataType::Struct(vec![ 49 | // Field::new("barrier_touch_start", dtype.clone()), 50 | // Field::new("barrier_touch_profit_take", dtype.clone()), 51 | // Field::new("barrier_touch_stop_loss", dtype.clone()), 52 | // Field::new("barrier_touch_vertical_barrier", dtype.clone()), 53 | // ]), 54 | // )) 55 | // } 56 | 57 | // #[polars_expr(output_type_func=barrier_touch_struct)] 58 | // fn get_barrier_touches(inputs: &[Series]) -> PolarsResult { 59 | // let targets = inputs[0].datetime()?; // Not sure what to do with this type yet. 60 | // let prices = inputs[1].f64()?; 61 | // let profit_taking = inputs[2].f64()?; 62 | // let stop_loss = inputs[3].f64()?; 63 | // let (pt, sl) = apply_profit_taking_stop_loss(targets, prices, profit_taking, stop_loss); 64 | // } 65 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use pyo3::prelude::*; 2 | use pyo3::types::{PyModule, PyModuleMethods}; 3 | use pyo3::{pymodule, Bound, PyResult}; 4 | use pyo3_polars::PolarsAllocator; 5 | 6 | mod bars; 7 | mod frac_diff; 8 | mod labels; 9 | 10 | #[pyfunction] 11 | fn get_weights_ffd_py(d: f64, threshold: f64) -> Vec { 12 | frac_diff::get_weights_ffd(d, threshold) 13 | } 14 | 15 | #[pymodule] 16 | fn _internal(m: &Bound<'_, PyModule>) -> PyResult<()> { 17 | m.add("__version__", env!("CARGO_PKG_VERSION"))?; 18 | m.add_function(wrap_pyfunction!(get_weights_ffd_py, m)?)?; 19 | Ok(()) 20 | } 21 | 22 | // #[global_allocator] 23 | // static ALLOC: PolarsAllocator = PolarsAllocator::new(); 24 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from polars_trading._testing.data import generate_trade_data 3 | 4 | 5 | @pytest.fixture 6 | def trade_data(request): 7 | return generate_trade_data(**request.param) 8 | -------------------------------------------------------------------------------- /tests/features/test_frac_diff.py: -------------------------------------------------------------------------------- 1 | from polars_trading._testing.features import get_weights_ffd, frac_diff_ffd 2 | from polars_trading._internal import get_weights_ffd_py 3 | from polars_trading.features.frac_diff import frac_diff 4 | import pytest 5 | from polars.testing import assert_frame_equal 6 | import pandas as pd 7 | import polars as pl 8 | 9 | 10 | def apply_pd_frac_diff(df: pd.DataFrame, d: float, threshold: float) -> pd.DataFrame: 11 | return ( 12 | df.set_index("ts_event") 13 | .groupby("symbol")[["price"]] 14 | .apply(frac_diff_ffd, 0.5, 1e-3) 15 | .reset_index() 16 | ) 17 | 18 | 19 | def test__get_weights_ffd__matches_pandas(): 20 | out = get_weights_ffd(0.5, 1e-3).flatten().tolist() 21 | out2 = get_weights_ffd_py(0.5, 1e-3) 22 | assert out == out2 23 | 24 | 25 | @pytest.mark.benchmark(group="get_weights_ffd") 26 | def test__get_weights_ffd__benchmark_rs(benchmark): 27 | benchmark(get_weights_ffd_py, 0.5, 1e-5) 28 | 29 | 30 | @pytest.mark.benchmark(group="get_weights_ffd") 31 | @pytest.mark.pandas 32 | def test__get_weights_ffd__benchmark_pandas(benchmark): 33 | benchmark(get_weights_ffd, 0.5, 1e-5) 34 | 35 | 36 | @pytest.mark.parametrize( 37 | "trade_data", [{"n_rows": 10_000, "n_companies": 3}], indirect=True 38 | ) 39 | def test__frac_diff__matches_pandas(trade_data): 40 | trade_data = trade_data.sort("ts_event") 41 | out = trade_data.select( 42 | "ts_event", "symbol", frac_diff("price", 0.5, 1e-3).over("symbol").alias("frac_diff") 43 | ) 44 | out2 = pl.DataFrame(apply_pd_frac_diff(trade_data.to_pandas(), 0.5, 1e-3)).rename( 45 | {"level_1": "ts_event", "price": "frac_diff"} 46 | ).cast(out.schema) 47 | assert_frame_equal( 48 | out.drop_nulls().sort("ts_event", "symbol"), 49 | out2.sort("ts_event", "symbol"), 50 | check_column_order=False, 51 | ) 52 | 53 | 54 | @pytest.mark.benchmark(group="frac_diff") 55 | @pytest.mark.parametrize( 56 | "trade_data", [{"n_rows": 10_000, "n_companies": 3}], indirect=True 57 | ) 58 | def test__frac_diff__benchmark_polars(benchmark, trade_data): 59 | trade_data = trade_data.lazy() 60 | benchmark( 61 | trade_data.select( 62 | "ts_event", "symbol", frac_diff("price", 0.5, 1e-3).alias("frac_diff") 63 | ).collect 64 | ) 65 | 66 | 67 | @pytest.mark.benchmark(group="frac_diff") 68 | @pytest.mark.pandas 69 | @pytest.mark.parametrize( 70 | "trade_data", [{"n_rows": 10_000, "n_companies": 3}], indirect=True 71 | ) 72 | def test__frac_diff__benchmark_pandas(benchmark, trade_data): 73 | benchmark(apply_pd_frac_diff, trade_data.to_pandas(), 0.5, 1e-5) 74 | -------------------------------------------------------------------------------- /tests/labels/test_dynamic_labels.py: -------------------------------------------------------------------------------- 1 | from polars_trading.labels.dynamic_labels import ( 2 | daily_vol, 3 | get_vertical_barrier_by_timedelta, 4 | ) 5 | import polars as pl 6 | from polars_trading._testing.labels import get_daily_vol 7 | import pytest 8 | from polars.testing import assert_frame_equal 9 | from datetime import datetime, timedelta 10 | 11 | 12 | @pytest.mark.parametrize( 13 | "trade_data", 14 | [ 15 | {"n_rows": 10_000, "n_companies": 1}, 16 | ], 17 | indirect=True, 18 | ) 19 | def test__daily_vol__single_security(trade_data): 20 | pl_result = daily_vol(trade_data.lazy(), "ts_event", "price", None, 5).collect() 21 | pd_result = get_daily_vol(trade_data.to_pandas().set_index("ts_event")["price"], 5) 22 | pd_result = pl.from_pandas(pd_result.reset_index()).rename( 23 | {"price": "daily_return_volatility"} 24 | ) 25 | assert_frame_equal(pl_result.drop_nulls(), pd_result) 26 | 27 | 28 | @pytest.mark.parametrize( 29 | "trade_data", 30 | [ 31 | {"n_rows": 10_000, "n_companies": 3}, 32 | ], 33 | indirect=True, 34 | ) 35 | def test__daily_vol__multi_security(trade_data): 36 | pl_result = ( 37 | daily_vol(trade_data, "ts_event", "price", "symbol", 5).sort( 38 | "ts_event", "symbol" 39 | ) 40 | ).drop_nulls() 41 | pd_result = ( 42 | trade_data.to_pandas() 43 | .set_index("ts_event")[["symbol", "price"]] 44 | .groupby("symbol")["price"] 45 | .apply(get_daily_vol, 5) 46 | ) 47 | pd_result = ( 48 | pl.from_pandas(pd_result.reset_index()) 49 | .rename({"price": "daily_return_volatility"}) 50 | .sort("ts_event", "symbol") 51 | ) 52 | assert_frame_equal( 53 | pl_result, pd_result, check_row_order=False, check_column_order=False 54 | ) 55 | 56 | 57 | @pytest.mark.benchmark(group="daily_vol") 58 | @pytest.mark.parametrize( 59 | "trade_data", 60 | [ 61 | {"n_rows": 100_000, "n_companies": 5}, 62 | ], 63 | indirect=True, 64 | ) 65 | def test__daily_vol__polars_benchmark(benchmark, trade_data): 66 | benchmark(daily_vol(trade_data.lazy(), "ts_event", "price", "symbol", 100).collect) 67 | 68 | 69 | @pytest.mark.pandas 70 | @pytest.mark.benchmark(group="daily_vol") 71 | @pytest.mark.parametrize( 72 | "trade_data", 73 | [ 74 | {"n_rows": 100_000, "n_companies": 5}, 75 | ], 76 | indirect=True, 77 | ) 78 | def test__daily_vol__pandas_benchmark(benchmark, trade_data): 79 | pd_df = trade_data.to_pandas().set_index("ts_event")[["symbol", "price"]] 80 | 81 | def get_daily_vol_pd(pd_df): 82 | return pd_df.groupby("symbol")["price"].apply(get_daily_vol).reset_index() 83 | 84 | benchmark(get_daily_vol_pd, pd_df) 85 | 86 | 87 | def test__daily_vol__weekend_returns(): 88 | df = pl.DataFrame( 89 | { 90 | "ts_event": [ 91 | datetime(2024, 1, 1, 0, 0, 0), 92 | datetime(2024, 1, 1, 3, 0, 0), 93 | datetime(2024, 1, 1, 6, 0, 0), 94 | datetime(2024, 1, 1, 9, 0, 0), 95 | datetime(2024, 1, 1, 15, 0, 0), 96 | datetime(2024, 1, 1, 20, 0, 0), 97 | datetime(2024, 1, 2, 1, 0, 0), 98 | datetime(2024, 1, 3, 5, 0, 0), 99 | datetime(2024, 1, 3, 7, 0, 0), 100 | datetime(2024, 1, 3, 9, 0, 0), 101 | ], 102 | "price": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 103 | } 104 | ) 105 | 106 | expected = pl.from_repr(""" 107 | shape: (10, 2) 108 | ┌─────────────────────┬─────────────────────────┐ 109 | │ ts_event ┆ daily_return_volatility │ 110 | │ --- ┆ --- │ 111 | │ datetime[μs] ┆ f64 │ 112 | ╞═════════════════════╪═════════════════════════╡ 113 | │ 2024-01-01 00:00:00 ┆ null │ 114 | │ 2024-01-01 03:00:00 ┆ null │ 115 | │ 2024-01-01 06:00:00 ┆ null │ 116 | │ 2024-01-01 09:00:00 ┆ null │ 117 | │ 2024-01-01 15:00:00 ┆ null │ 118 | │ 2024-01-01 20:00:00 ┆ null │ 119 | │ 2024-01-02 01:00:00 ┆ 0.0 │ 120 | │ 2024-01-03 05:00:00 ┆ 4.141625 │ 121 | │ 2024-01-03 07:00:00 ┆ 2.668519 │ 122 | │ 2024-01-03 09:00:00 ┆ 1.792192 │ 123 | └─────────────────────┴─────────────────────────┘ 124 | """) 125 | 126 | result = daily_vol(df.lazy(), "ts_event", "price", None, 3).collect() 127 | assert_frame_equal(result, expected) 128 | 129 | 130 | def test__get_vertical_barrier_by_timedelta__simple(): 131 | df = pl.DataFrame( 132 | { 133 | "ts_event": [ 134 | datetime(2024, 1, 1, 0, 0, 0), 135 | datetime(2024, 1, 1, 3, 0, 0), 136 | datetime(2024, 1, 1, 6, 0, 0), 137 | datetime(2024, 1, 1, 9, 0, 0), 138 | datetime(2024, 1, 1, 15, 0, 0), 139 | datetime(2024, 1, 1, 20, 0, 0), 140 | datetime(2024, 1, 2, 1, 0, 0), 141 | datetime(2024, 1, 3, 5, 0, 0), 142 | datetime(2024, 1, 3, 7, 0, 0), 143 | datetime(2024, 1, 3, 9, 0, 0), 144 | ], 145 | } 146 | ) 147 | 148 | expected = pl.from_repr(""" 149 | shape: (10, 2) 150 | ┌─────────────────────┬─────────────────────┐ 151 | │ ts_event ┆ vertical_barrier │ 152 | │ --- ┆ --- │ 153 | │ datetime[μs] ┆ datetime[μs] │ 154 | ╞ 155 | │ 2024-01-01 00:00:00 ┆ 2024-01-01 03:00:00 │ 156 | │ 2024-01-01 03:00:00 ┆ 2024-01-01 06:00:00 │ 157 | │ 2024-01-01 06:00:00 ┆ 2024-01-01 09:00:00 │ 158 | │ 2024-01-01 09:00:00 ┆ 2024-01-01 15:00:00 │ 159 | │ 2024-01-01 15:00:00 ┆ 2024-01-01 20:00:00 │ 160 | │ 2024-01-01 20:00:00 ┆ 2024-01-02 01:00:00 │ 161 | │ 2024-01-02 01:00:00 ┆ 2024-01-03 05:00:00 │ 162 | │ 2024-01-03 05:00:00 ┆ 2024-01-03 07:00:00 │ 163 | │ 2024-01-03 07:00:00 ┆ 2024-01-03 09:00:00 │ 164 | │ 2024-01-03 09:00:00 ┆ null │ 165 | └─────────────────────┴─────────────────────┘ 166 | """) 167 | 168 | result = get_vertical_barrier_by_timedelta(df.lazy(), "ts_event", "2h").collect() 169 | assert_frame_equal(result, expected) 170 | 171 | 172 | def test__get_vertical_barrier_by_timedelta__skip_rows(): 173 | df = pl.DataFrame( 174 | { 175 | "ts_event": [ 176 | datetime(2024, 1, 1, 0, 0, 0), 177 | datetime(2024, 1, 1, 3, 0, 0), 178 | datetime(2024, 1, 1, 6, 0, 0), 179 | datetime(2024, 1, 1, 9, 0, 0), 180 | datetime(2024, 1, 1, 15, 0, 0), 181 | datetime(2024, 1, 1, 20, 0, 0), 182 | datetime(2024, 1, 2, 1, 0, 0), 183 | datetime(2024, 1, 3, 5, 0, 0), 184 | datetime(2024, 1, 3, 7, 0, 0), 185 | datetime(2024, 1, 3, 9, 0, 0), 186 | ], 187 | } 188 | ) 189 | 190 | expected = pl.from_repr(""" 191 | shape: (10, 2) 192 | ┌─────────────────────┬─────────────────────┐ 193 | │ ts_event ┆ vertical_barrier │ 194 | │ --- ┆ --- │ 195 | │ datetime[μs] ┆ datetime[μs] │ 196 | ╞ 197 | │ 2024-01-01 00:00:00 ┆ 2024-01-01 03:00:00 │ 198 | │ 2024-01-01 03:00:00 ┆ 2024-01-01 06:00:00 │ 199 | │ 2024-01-01 06:00:00 ┆ 2024-01-01 09:00:00 │ 200 | │ 2024-01-01 09:00:00 ┆ 2024-01-01 15:00:00 │ 201 | │ 2024-01-01 15:00:00 ┆ 2024-01-01 20:00:00 │ 202 | │ 2024-01-01 20:00:00 ┆ 2024-01-02 01:00:00 │ 203 | │ 2024-01-02 01:00:00 ┆ 2024-01-03 05:00:00 │ 204 | │ 2024-01-03 05:00:00 ┆ 2024-01-03 09:00:00 │ 205 | │ 2024-01-03 07:00:00 ┆ null │ 206 | │ 2024-01-03 09:00:00 ┆ null │ 207 | └─────────────────────┴─────────────────────┘ 208 | """) 209 | 210 | result = get_vertical_barrier_by_timedelta(df.lazy(), "ts_event", "3h").collect() 211 | assert_frame_equal(result, expected) 212 | 213 | 214 | def test__get_vertical_barrier_by_timedelta__timedelta(): 215 | df = pl.DataFrame( 216 | { 217 | "ts_event": [ 218 | datetime(2024, 1, 1, 0, 0, 0), 219 | datetime(2024, 1, 1, 3, 0, 0), 220 | datetime(2024, 1, 1, 6, 0, 0), 221 | datetime(2024, 1, 1, 9, 0, 0), 222 | datetime(2024, 1, 1, 15, 0, 0), 223 | datetime(2024, 1, 1, 20, 0, 0), 224 | datetime(2024, 1, 2, 1, 0, 0), 225 | datetime(2024, 1, 3, 5, 0, 0), 226 | datetime(2024, 1, 3, 7, 0, 0), 227 | datetime(2024, 1, 3, 9, 0, 0), 228 | ], 229 | } 230 | ) 231 | 232 | expected = pl.from_repr(""" 233 | shape: (10, 2) 234 | ┌─────────────────────┬─────────────────────┐ 235 | │ ts_event ┆ vertical_barrier │ 236 | │ --- ┆ --- │ 237 | │ datetime[μs] ┆ datetime[μs] │ 238 | ╞ 239 | │ 2024-01-01 00:00:00 ┆ 2024-01-01 03:00:00 │ 240 | │ 2024-01-01 03:00:00 ┆ 2024-01-01 06:00:00 │ 241 | │ 2024-01-01 06:00:00 ┆ 2024-01-01 09:00:00 │ 242 | │ 2024-01-01 09:00:00 ┆ 2024-01-01 15:00:00 │ 243 | │ 2024-01-01 15:00:00 ┆ 2024-01-01 20:00:00 │ 244 | │ 2024-01-01 20:00:00 ┆ 2024-01-02 01:00:00 │ 245 | │ 2024-01-02 01:00:00 ┆ 2024-01-03 05:00:00 │ 246 | │ 2024-01-03 05:00:00 ┆ 2024-01-03 07:00:00 │ 247 | │ 2024-01-03 07:00:00 ┆ 2024-01-03 09:00:00 │ 248 | │ 2024-01-03 09:00:00 ┆ null │ 249 | └─────────────────────┴─────────────────────┘ 250 | """) 251 | 252 | result = get_vertical_barrier_by_timedelta( 253 | df.lazy(), "ts_event", timedelta(hours=2) 254 | ).collect() 255 | assert_frame_equal(result, expected) 256 | 257 | 258 | @pytest.mark.benchmark(group="vertical_barrier") 259 | @pytest.mark.parametrize( 260 | "trade_data", 261 | [ 262 | {"n_rows": 100_000, "n_companies": 5}, 263 | ], 264 | indirect=True, 265 | ) 266 | def test__get_vertical_barrier_by_timedelta__benchmark(benchmark, trade_data): 267 | benchmark(get_vertical_barrier_by_timedelta, trade_data, "ts_event", "1h", "symbol") 268 | -------------------------------------------------------------------------------- /tests/labels/test_labels.py: -------------------------------------------------------------------------------- 1 | from polars_trading.labels.labels import ( 2 | fixed_time_return, 3 | fixed_time_return_classification, 4 | ) 5 | import polars as pl 6 | from polars.testing import assert_series_equal 7 | import pytest 8 | 9 | 10 | def test__fixed_time_return__single_security(): 11 | df = pl.DataFrame( 12 | { 13 | "ts": [1, 2, 3, 4, 5], 14 | "p": [1.0, 2.0, 3.0, 4.0, 5.0], 15 | "s": [1, 2, 3, 4, 5], 16 | "sy": ["A", "A", "A", "A", "A"], 17 | } 18 | ) 19 | 20 | result = df.with_columns(fixed_time_return("p", 1).alias("label")) 21 | assert_series_equal( 22 | result["label"], 23 | pl.Series(values=[0.5, 0.3333333333333333, 0.25, None, None]), 24 | check_names=False, 25 | ) 26 | 27 | 28 | def test__fixed_time_return__multi_security(): 29 | df = pl.DataFrame( 30 | { 31 | "ts": [1, 2, 3, 4, 5, 1, 2, 3, 4, 5], 32 | "p": [1.0, 2.0, 3.0, 4.0, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0], 33 | "s": [1, 2, 3, 4, 5, 1, 2, 3, 4, 5], 34 | "sy": ["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"], 35 | } 36 | ) 37 | 38 | result = df.with_columns(fixed_time_return("p", 1, symbol="sy").alias("label")) 39 | assert_series_equal( 40 | result["label"], 41 | pl.Series( 42 | values=[ 43 | 0.5, 44 | 0.3333333333333333, 45 | 0.25, 46 | None, 47 | None, 48 | 0.5, 49 | 0.3333333333333333, 50 | 0.25, 51 | None, 52 | None, 53 | ] 54 | ), 55 | check_names=False, 56 | ) 57 | 58 | 59 | def test__fixed_time_return_classification__float_threshold(): 60 | df = pl.DataFrame( 61 | { 62 | "ts": [1, 2, 3, 4, 5], 63 | "p": [1.0, 2.0, 3.0, 4.0, 5.0], 64 | "s": [1, 2, 3, 4, 5], 65 | "sy": ["A", "A", "A", "A", "A"], 66 | } 67 | ) 68 | 69 | result = df.with_columns( 70 | fixed_time_return_classification("p", 1, 0.3).alias("label") 71 | ) 72 | assert_series_equal( 73 | result["label"], 74 | pl.Series(values=[1, 1, 0, None, None], dtype=pl.Int32), 75 | check_names=False, 76 | ) 77 | 78 | 79 | def test__fixed_time_return_classification__no_threshold(): 80 | df = pl.DataFrame( 81 | { 82 | "ts": [1, 2, 3, 4, 5], 83 | "p": [1.0, 2.0, 3.0, 4.0, 5.0], 84 | "s": [1, 2, 3, 4, 5], 85 | "sy": ["A", "A", "A", "A", "A"], 86 | } 87 | ) 88 | 89 | result = df.with_columns( 90 | fixed_time_return_classification( 91 | "p", 92 | 1, 93 | ).alias("label") 94 | ) 95 | assert_series_equal( 96 | result["label"], 97 | pl.Series(values=[1, 1, 1, None, None], dtype=pl.Int32), 98 | check_names=False, 99 | ) 100 | 101 | 102 | def test__fixed_time_return_classification__expr_threshold(): 103 | df = pl.DataFrame( 104 | { 105 | "ts": [1, 2, 3, 4, 5], 106 | "p": [1.0, 2.0, 3.0, 4.0, 5.0], 107 | "t": [0.7, 0.3, 0.1, 0.3, 0.3], 108 | "s": [1, 2, 3, 4, 5], 109 | "sy": ["A", "A", "A", "A", "A"], 110 | } 111 | ) 112 | 113 | result = df.with_columns( 114 | fixed_time_return_classification("p", 1, "t").alias("label") 115 | ) 116 | assert_series_equal( 117 | result["label"], 118 | pl.Series(values=[0, 1, 1, None, None], dtype=pl.Int32), 119 | check_names=False, 120 | ) 121 | 122 | 123 | @pytest.mark.benchmark 124 | @pytest.mark.parametrize( 125 | "trade_data", 126 | [ 127 | {"n_rows": 100_000, "n_companies": 5}, 128 | ], 129 | indirect=True, 130 | ) 131 | def test__fixed_time_return_classification__benchmark(trade_data, benchmark): 132 | benchmark( 133 | trade_data.lazy() 134 | .select(fixed_time_return_classification("price", 50, 0.2, symbol="symbol")) 135 | .collect 136 | ) 137 | -------------------------------------------------------------------------------- /tests/test__utils.py: -------------------------------------------------------------------------------- 1 | from polars_trading._utils import validate_columns 2 | import pytest 3 | import polars as pl 4 | 5 | 6 | @pytest.mark.benchmark 7 | def test__validate_columns__valid(): 8 | @validate_columns("timestamp_col", "price_col", "size_col", "symbol_col") 9 | def dummy_func(df, **kwargs): 10 | return df 11 | 12 | df = pl.DataFrame( 13 | { 14 | "ts": [1, 2, 3], 15 | "p": [1.0, 2.0, 3.0], 16 | "s": [1, 2, 3], 17 | "sy": ["A", "B", "C"], 18 | } 19 | ) 20 | 21 | dummy_func(df, timestamp_col="ts", price_col="p", size_col="s", symbol_col="sy") 22 | 23 | 24 | @pytest.mark.benchmark 25 | def test__validate_columns__invalid(): 26 | @validate_columns("timestamp_col", "price_col", "size_col", "symbol_col") 27 | def dummy_func(df, **kwargs): 28 | return df 29 | 30 | df = pl.DataFrame( 31 | { 32 | "ts": [1, 2, 3], 33 | "p": [1.0, 2.0, 3.0], 34 | "s": [1, 2, 3], 35 | "sy": ["A", "B", "C"], 36 | } 37 | ) 38 | 39 | with pytest.raises(ValueError): 40 | dummy_func( 41 | df, timestamp_col="ts", price_col="pr", size_col="s", symbol_col="sy" 42 | ) 43 | 44 | 45 | @pytest.mark.benchmark 46 | def test__validate_columns__df_not_passed(): 47 | @validate_columns("timestamp_col", "price_col", "size_col", "symbol_col") 48 | def dummy_func(df, **kwargs): 49 | return df 50 | 51 | df = { 52 | "ts": [1, 2, 3], 53 | "p": [1.0, 2.0, 3.0], 54 | "s": [1, 2, 3], 55 | "sy": ["A", "B", "C"], 56 | } 57 | 58 | with pytest.raises(TypeError): 59 | dummy_func(df, timestamp_col="ts", price_col="p", size_col="s", symbol_col="sy") 60 | 61 | 62 | @pytest.mark.benchmark 63 | def test__validate_columns__default_args(): 64 | @validate_columns("timestamp_col", "price_col", "size_col", "symbol_col") 65 | def dummy_func(df, timestamp_col="ts", **kwargs): 66 | return df 67 | 68 | df = pl.DataFrame( 69 | { 70 | "ts": [1, 2, 3], 71 | "p": [1.0, 2.0, 3.0], 72 | "s": [1, 2, 3], 73 | "sy": ["A", "B", "C"], 74 | } 75 | ) 76 | dummy_func(df, price_col="p", size_col="s", symbol_col="sy") 77 | -------------------------------------------------------------------------------- /tests/test_bars.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import polars as pl 3 | import pytest 4 | from datetime import datetime 5 | from polars.testing import assert_frame_equal 6 | 7 | from polars_trading.bars import time_bars, tick_bars, volume_bars, dollar_bars 8 | from polars_trading._testing.data import generate_trade_data 9 | 10 | 11 | def pandas_time_bars(df: pd.DataFrame, period: str) -> pd.DataFrame: 12 | df.index = pd.to_datetime(df["ts_event"]) 13 | df["pvt"] = df["price"] * df["size"] 14 | df = df.sort_index() 15 | resampled_df = ( 16 | df.groupby([df.index.to_period(period), "symbol"]) 17 | .agg( 18 | ts_event_start=pd.NamedAgg(column="ts_event", aggfunc="first"), 19 | ts_event_end=pd.NamedAgg(column="ts_event", aggfunc="last"), 20 | n_trades=pd.NamedAgg(column="ts_event", aggfunc="count"), 21 | open=pd.NamedAgg(column="price", aggfunc="first"), 22 | high=pd.NamedAgg(column="price", aggfunc="max"), 23 | low=pd.NamedAgg(column="price", aggfunc="min"), 24 | close=pd.NamedAgg(column="price", aggfunc="last"), 25 | volume=pd.NamedAgg(column="size", aggfunc="sum"), 26 | vwap=pd.NamedAgg(column="pvt", aggfunc="sum"), 27 | ) 28 | .reset_index("symbol") 29 | ) 30 | resampled_df.index.names = ["ts_event"] 31 | resampled_df["vwap"] = resampled_df["vwap"] / resampled_df["volume"] 32 | return resampled_df 33 | 34 | 35 | def pandas_tick_bars(df: pd.DataFrame, n_ticks: int) -> pd.DataFrame: 36 | df["ts_event"] = pd.to_datetime(df["ts_event"]) 37 | df = df.sort_values("ts_event") 38 | df["pvt"] = df["price"] * df["size"] 39 | df["date"] = pd.to_datetime(df["ts_event"]).dt.date 40 | df["tick_group"] = (df.groupby(["symbol", "date"]).cumcount() // n_ticks).astype( 41 | int 42 | ) 43 | resampled_df = ( 44 | df.groupby(["date", "tick_group", "symbol"]) 45 | .agg( 46 | ts_event_start=pd.NamedAgg(column="ts_event", aggfunc="first"), 47 | ts_event_end=pd.NamedAgg(column="ts_event", aggfunc="last"), 48 | n_trades=pd.NamedAgg(column="ts_event", aggfunc="count"), 49 | open=pd.NamedAgg(column="price", aggfunc="first"), 50 | high=pd.NamedAgg(column="price", aggfunc="max"), 51 | low=pd.NamedAgg(column="price", aggfunc="min"), 52 | close=pd.NamedAgg(column="price", aggfunc="last"), 53 | volume=pd.NamedAgg(column="size", aggfunc="sum"), 54 | vwap=pd.NamedAgg(column="pvt", aggfunc="sum"), 55 | ) 56 | .reset_index() 57 | .drop(["date", "tick_group"], axis=1) 58 | ) 59 | resampled_df["vwap"] = resampled_df["vwap"] / resampled_df["volume"] 60 | return resampled_df 61 | 62 | 63 | @pytest.mark.parametrize( 64 | "trade_data", [{"n_rows": 10_000, "n_companies": 3}], indirect=True 65 | ) 66 | def test__time_bars__matches_pandas(trade_data): 67 | pd_df = pandas_time_bars(trade_data.to_pandas(), "1d") 68 | pd_df.index = pd_df.index.to_timestamp() 69 | pd_df = pd_df.reset_index() 70 | res = time_bars(trade_data, timestamp_col="ts_event", bar_size="1d") 71 | 72 | assert_frame_equal( 73 | res, 74 | pl.from_pandas(pd_df, schema_overrides=res.schema), 75 | check_row_order=False, 76 | check_column_order=False, 77 | ) 78 | 79 | 80 | @pytest.mark.benchmark(group="time_bars") 81 | @pytest.mark.parametrize( 82 | "trade_data", 83 | [ 84 | {"n_rows": 10_000, "n_companies": 3}, 85 | ], 86 | indirect=True, 87 | ) 88 | def test__time_bars__polars_benchmark(benchmark, trade_data): 89 | benchmark(time_bars, trade_data, timestamp_col="ts_event", bar_size="1d") 90 | 91 | 92 | @pytest.mark.pandas 93 | @pytest.mark.benchmark(group="time_bars") 94 | @pytest.mark.parametrize( 95 | "trade_data", 96 | [ 97 | {"n_rows": 10_000, "n_companies": 3}, 98 | ], 99 | indirect=True, 100 | ) 101 | def test__time_bars__pandas_benchmark(benchmark, trade_data): 102 | trade_data = trade_data.to_pandas() 103 | benchmark(pandas_time_bars, trade_data, "1d") 104 | 105 | 106 | @pytest.mark.parametrize( 107 | "trade_data", [{"n_rows": 10_000, "n_companies": 3}], indirect=True 108 | ) 109 | def test__tick_bars__matches_pandas(trade_data): 110 | pd_df = pandas_tick_bars(trade_data.to_pandas(), 100) 111 | res = tick_bars(trade_data, timestamp_col="ts_event", bar_size=100) 112 | 113 | assert_frame_equal( 114 | res, 115 | pl.from_pandas(pd_df, schema_overrides=res.schema), 116 | check_row_order=False, 117 | check_column_order=False, 118 | ) 119 | 120 | 121 | @pytest.mark.benchmark(group="tick_bars") 122 | @pytest.mark.parametrize( 123 | "trade_data", 124 | [ 125 | {"n_rows": 10_000, "n_companies": 3}, 126 | ], 127 | indirect=True, 128 | ) 129 | def test__tick_bars__polars_benchmark(benchmark, trade_data): 130 | benchmark(tick_bars, trade_data, timestamp_col="ts_event", bar_size=100) 131 | 132 | 133 | @pytest.mark.pandas 134 | @pytest.mark.benchmark(group="tick_bars") 135 | @pytest.mark.parametrize( 136 | "trade_data", 137 | [ 138 | {"n_rows": 10_000, "n_companies": 3}, 139 | ], 140 | indirect=True, 141 | ) 142 | def test__tick_bars__pandas_benchmark(benchmark, trade_data): 143 | trade_data = trade_data.to_pandas() 144 | benchmark(pandas_tick_bars, trade_data, 100) 145 | 146 | 147 | @pytest.mark.benchmark(group="volume_bars") 148 | @pytest.mark.parametrize( 149 | "trade_data", 150 | [ 151 | {"n_rows": 10_000, "n_companies": 3}, 152 | ], 153 | indirect=True, 154 | ) 155 | def test__volume_bars__polars_benchmark(benchmark, trade_data): 156 | benchmark(volume_bars, trade_data, timestamp_col="ts_event", bar_size=10_000) 157 | 158 | 159 | @pytest.mark.benchmark(group="dollar_bars") 160 | @pytest.mark.parametrize( 161 | "trade_data", 162 | [ 163 | {"n_rows": 10_000, "n_companies": 3}, 164 | ], 165 | indirect=True, 166 | ) 167 | def test__dollar_bars__polars_benchmark(benchmark, trade_data): 168 | benchmark(dollar_bars, trade_data, timestamp_col="ts_event", bar_size=100_000) 169 | --------------------------------------------------------------------------------