tycheon 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. tycheon/__init__.py +32 -0
  2. tycheon/_svg.py +55 -0
  3. tycheon/_vendor/kronos/LICENSE +21 -0
  4. tycheon/_vendor/kronos/README.md +39 -0
  5. tycheon/_vendor/kronos/UPSTREAM.json +12 -0
  6. tycheon/_vendor/kronos/model/kronos.py +662 -0
  7. tycheon/_vendor/kronos/model/module.py +570 -0
  8. tycheon/agents/README.md +33 -0
  9. tycheon/agents/__init__.py +7 -0
  10. tycheon/backtest/__init__.py +57 -0
  11. tycheon/backtest/costs.py +121 -0
  12. tycheon/backtest/factories.py +145 -0
  13. tycheon/backtest/guards.py +142 -0
  14. tycheon/backtest/metrics.py +381 -0
  15. tycheon/backtest/walk_forward.py +246 -0
  16. tycheon/calibration/__init__.py +33 -0
  17. tycheon/calibration/conformal.py +411 -0
  18. tycheon/calibration/diagnostics.py +227 -0
  19. tycheon/calibration/forecaster.py +110 -0
  20. tycheon/calibration/metrics.py +125 -0
  21. tycheon/calibration/plots.py +87 -0
  22. tycheon/calibration/scores.py +288 -0
  23. tycheon/covariates/__init__.py +27 -0
  24. tycheon/covariates/features.py +149 -0
  25. tycheon/covariates/residual.py +349 -0
  26. tycheon/covariates/store.py +164 -0
  27. tycheon/data/__init__.py +23 -0
  28. tycheon/data/actions.py +140 -0
  29. tycheon/data/asof.py +84 -0
  30. tycheon/data/providers/__init__.py +1 -0
  31. tycheon/data/providers/base.py +128 -0
  32. tycheon/data/providers/file.py +86 -0
  33. tycheon/data/providers/licensed.py +91 -0
  34. tycheon/data/providers/yfinance.py +109 -0
  35. tycheon/data/sample.py +194 -0
  36. tycheon/data/schema.py +143 -0
  37. tycheon/data/store.py +205 -0
  38. tycheon/errors.py +45 -0
  39. tycheon/governance/README.md +37 -0
  40. tycheon/governance/__init__.py +9 -0
  41. tycheon/models/__init__.py +23 -0
  42. tycheon/models/base.py +563 -0
  43. tycheon/models/baselines/__init__.py +20 -0
  44. tycheon/models/baselines/_common.py +29 -0
  45. tycheon/models/baselines/arima.py +68 -0
  46. tycheon/models/baselines/drift.py +49 -0
  47. tycheon/models/baselines/garch.py +80 -0
  48. tycheon/models/baselines/random_walk.py +48 -0
  49. tycheon/models/baselines/seasonal_naive.py +57 -0
  50. tycheon/models/chronos/__init__.py +5 -0
  51. tycheon/models/chronos/forecaster.py +113 -0
  52. tycheon/models/devices.py +37 -0
  53. tycheon/models/kronos/__init__.py +10 -0
  54. tycheon/models/kronos/forecaster.py +306 -0
  55. tycheon/models/kronos/sampling.py +172 -0
  56. tycheon/models/kronos/specs.py +83 -0
  57. tycheon/models/kronos/vendor.py +139 -0
  58. tycheon/models/kronos/windowing.py +121 -0
  59. tycheon/models/timesfm/__init__.py +5 -0
  60. tycheon/models/timesfm/forecaster.py +133 -0
  61. tycheon/py.typed +0 -0
  62. tycheon/risk/__init__.py +68 -0
  63. tycheon/risk/measures.py +283 -0
  64. tycheon/risk/plots.py +112 -0
  65. tycheon/risk/portfolio.py +362 -0
  66. tycheon/risk/report.py +556 -0
  67. tycheon/risk/scenarios.py +261 -0
  68. tycheon/routing/__init__.py +25 -0
  69. tycheon/routing/ensemble.py +396 -0
  70. tycheon/routing/regimes.py +157 -0
  71. tycheon/serve/__init__.py +1 -0
  72. tycheon-0.1.0.dist-info/METADATA +319 -0
  73. tycheon-0.1.0.dist-info/RECORD +76 -0
  74. tycheon-0.1.0.dist-info/WHEEL +4 -0
  75. tycheon-0.1.0.dist-info/licenses/LICENSE +202 -0
  76. tycheon-0.1.0.dist-info/licenses/third_party/kronos/LICENSE +21 -0
tycheon/__init__.py ADDED
@@ -0,0 +1,32 @@
1
+ """Tycheon — calibrated financial forecasting and risk.
2
+
3
+ Kronos forecasts the path; Tycheon tells you how much to trust it.
4
+
5
+ Tycheon is the forecasting and risk layer: conformal prediction intervals and
6
+ reliability diagnostics, exogenous covariates beyond OHLCV, regime-weighted
7
+ routing across Kronos / TimesFM / Chronos and honest baselines, translation of
8
+ forecasts into VaR, Expected Shortfall and drawdown probabilities, and
9
+ leakage-proof walk-forward evaluation.
10
+
11
+ Three invariants hold everywhere in this package:
12
+
13
+ * **Point-in-time.** Every data read takes an ``as_of`` and refuses anything
14
+ published after it. Leakage tests are mandatory for every data path.
15
+ * **Uncertainty is not optional.** Every forecast carries intervals or
16
+ quantiles, calibration status, the model mix, its ``as_of`` and a model card
17
+ reference.
18
+ * **Baselines are published honestly.** Every evaluation reports the
19
+ random-walk baseline and a Diebold-Mariano test, including when the baseline
20
+ wins.
21
+
22
+ For research and risk analytics. Not investment advice.
23
+ """
24
+
25
+ from importlib.metadata import PackageNotFoundError, version
26
+
27
+ try:
28
+ __version__ = version("tycheon")
29
+ except PackageNotFoundError: # pragma: no cover - only when run from a bare tree
30
+ __version__ = "0.0.0.dev0"
31
+
32
+ __all__ = ["__version__"]
tycheon/_svg.py ADDED
@@ -0,0 +1,55 @@
1
+ """Shared helpers for the diagnostic plots: matplotlib is optional, output is inline SVG.
2
+
3
+ Plots are returned as SVG *strings* so an HTML report can embed them with no external files,
4
+ no scripts and no network access. Text and lines use ``currentColor`` so a figure follows the
5
+ page's light or dark theme.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import importlib
11
+ import io
12
+ import re
13
+ from typing import TYPE_CHECKING, Any
14
+
15
+ from tycheon.errors import OptionalDependencyError
16
+
17
+ if TYPE_CHECKING:
18
+ from matplotlib.figure import Figure
19
+
20
+ #: Colours chosen to read on both light and dark backgrounds.
21
+ BLUE = "#3b82c4"
22
+ ORANGE = "#e08a2c"
23
+ RED = "#d1495b"
24
+ GREEN = "#3aa17e"
25
+ GREY = "#8a8f98"
26
+
27
+
28
+ def require_matplotlib() -> Any:
29
+ """Import ``matplotlib`` or explain which extra installs it."""
30
+ try:
31
+ return importlib.import_module("matplotlib")
32
+ except ImportError as exc:
33
+ raise OptionalDependencyError(
34
+ "plots need matplotlib. Install the extra: pip install 'tycheon[report]'"
35
+ ) from exc
36
+
37
+
38
+ def new_figure(width: float = 6.0, height: float = 3.6) -> Figure:
39
+ """A figure not attached to pyplot (no global state, safe in servers and tests)."""
40
+ require_matplotlib()
41
+ from matplotlib.figure import Figure
42
+
43
+ return Figure(figsize=(width, height), layout="constrained")
44
+
45
+
46
+ def figure_to_svg(fig: Figure) -> str:
47
+ """Serialise ``fig`` to an inline-able SVG string that follows the page colour scheme."""
48
+ buffer = io.StringIO()
49
+ fig.savefig(buffer, format="svg", transparent=True)
50
+ svg = buffer.getvalue()
51
+ start = svg.find("<svg")
52
+ body = svg[start:] if start >= 0 else svg
53
+ body = re.sub(r"<metadata>.*?</metadata>\s*", "", body, flags=re.DOTALL)
54
+ # black text and axes become the surrounding text colour (light and dark themes)
55
+ return body.replace("#000000", "currentColor").replace("rgb(0%, 0%, 0%)", "currentColor")
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 ShiYu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,39 @@
1
+ # Vendored: Kronos
2
+
3
+ Upstream: <https://github.com/shiyu-coder/Kronos> at commit
4
+ `67b630e67f6a18c9e9be918d9b4337c960db1e9a`, MIT licensed
5
+ (Copyright (c) 2025 ShiYu). The licence file is retained here verbatim and ships
6
+ inside the wheel.
7
+
8
+ ## What is here
9
+
10
+ | File | Why |
11
+ |---|---|
12
+ | `model/kronos.py` | `KronosTokenizer`, `Kronos`, the sampling helpers. |
13
+ | `model/module.py` | The transformer building blocks they import. |
14
+ | `LICENSE` | Upstream MIT licence. Must travel with the code. |
15
+ | `UPSTREAM.json` | Commit and SHA-256 of every file above. |
16
+
17
+ Upstream's `model/__init__.py`, predictor examples, fine-tuning pipeline and web
18
+ UI are deliberately **not** vendored. Tycheon does not call upstream's
19
+ `KronosPredictor`: its sampler averages the sample paths away, and Tycheon needs
20
+ them (see ADR 0002).
21
+
22
+ ## Rules
23
+
24
+ 1. **Do not edit these files.** `tests/test_vendored_kronos.py` hashes them
25
+ against `UPSTREAM.json` and fails on any difference, so an accidental edit,
26
+ an editor reformat or a line-ending change cannot slip in.
27
+ 2. Everything Tycheon adds lives in `src/tycheon/models/kronos/`, never here.
28
+ 3. To update, vendor the new upstream commit in a PR of its own, regenerate
29
+ `UPSTREAM.json`, and re-run the slow Kronos tests. Read upstream's diff
30
+ first: a changed sampler or normalisation is a changed model.
31
+ 4. Excluded from ruff, mypy and every pre-commit hook, because reformatting
32
+ vendored code makes it impossible to diff against upstream.
33
+
34
+ ## How it is imported
35
+
36
+ Upstream does `from model.module import *` behind a `sys.path.append("../")`.
37
+ Putting a top-level package called `model` on `sys.path` would shadow anything
38
+ else with that name, so `tycheon.models.kronos.vendor` loads the two files by
39
+ path and resolves that one import itself, then removes every trace of it.
@@ -0,0 +1,12 @@
1
+ {
2
+ "repository": "https://github.com/shiyu-coder/Kronos",
3
+ "commit": "67b630e67f6a18c9e9be918d9b4337c960db1e9a",
4
+ "license": "MIT",
5
+ "copyright": "Copyright (c) 2025 ShiYu",
6
+ "note": "Byte-identical copies. Do not edit; see third_party/kronos/README.md.",
7
+ "files": {
8
+ "LICENSE": "acb2d194d378204e5f2be4dcd24d39ecac437903620c790c3315a96dab388fdc",
9
+ "model/kronos.py": "0a5f90282e2039c2de0771473419715c845def154896dbd0f5747837e6241032",
10
+ "model/module.py": "a4df669998fa8115ac219b06687abaff2fac0fce9da762007dd142038949eee5"
11
+ }
12
+ }