-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathpyproject.toml
More file actions
191 lines (175 loc) · 8.57 KB
/
Copy pathpyproject.toml
File metadata and controls
191 lines (175 loc) · 8.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
[project]
name = "TinyCTA"
# Derived from the git tag by hatch-vcs (see [tool.hatch.version]) rather than written
# here, so the tag is the single source of truth and no commit can disagree with it.
dynamic = ["version"]
description = "A lightweight Python package for Commodity Trading Advisor (CTA) strategies"
readme = "README.md"
license = "MIT"
license-files = ["LICENSE"]
authors = [{name = "Thomas Schmelzer", email = "thomas.schmelzer@gmail.com"}]
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
dependencies = [
"cvx-linalg>=0.9.0",
"numpy>=2.0.0",
# >=1.43.0: ewm_std yields null (not 0.0) for a single observation, which fixes
# vol_adj's first log return and makes the engine's warmup length determinate.
"polars>=1.43.0",
"pydantic>=2.13.3",
]
[project.optional-dependencies]
# Hyperparameter-optimisation and notebook-experiment layer (tinycta.hyper).
# Install with: pip install tinycta[hyper]
hyper = [
"jquantstats>=0.9.6",
"loguru>=0.7.3",
"optuna>=4.8.0",
"pyyaml>=6.0.3",
]
[project.urls]
Homepage = "https://github.com/tschm/tinycta"
Repository = "https://github.com/tschm/tinycta"
[dependency-groups]
dev = [
"pre-commit==4.6.2",
"marimo==0.24.2",
"pandas>=2.2.3",
"pandas-stubs>=2.2",
"types-PyYAML>=6.0",
]
# Mirrors the [project.optional-dependencies] hyper extra. The dev/CI environment
# needs it so the tinycta.hyper test suite can be collected and run; it is wired
# into the default sync via [tool.uv] default-groups below rather than an inline
# {include-group = ...} entry, which the legacy TOML parser used by mutmut cannot
# parse when mixed with string requirements in the same array.
hyper = [
"jquantstats>=0.9.6",
"loguru>=0.7.3",
"optuna>=4.8.0",
"pyyaml>=6.0.3",
]
test = [
"pytest>=9.1.0",
"pytest-cov>=6.0",
"pytest-html>=4.0",
"pytest-mock>=3.0",
"pytest-xdist>=3.0",
"pytest-timeout>=2.0",
"hypothesis>=6.155.3",
"pytest-benchmark>=5.2.3",
]
[tool.uv]
# Install both dev tooling and the hyper extra by default so `uv sync` provides
# everything needed to collect and run the full test suite (including tinycta.hyper).
default-groups = ["dev", "hyper"]
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/tinycta"]
[tool.hatch.version]
# Resolves [project].dynamic = ["version"] from `git describe`. Tags are vX.Y.Z and
# hatch-vcs strips the leading "v" by default, so v0.14.0 builds 0.14.0; a commit off
# the tag builds a PEP 440 dev version (0.14.1.dev42+g<sha>).
#
# This makes the build history-dependent: a shallow clone that cannot see the tag does
# not fail, it silently builds 0.1.dev1+g<sha>. rhiza_release.yml is the only workflow
# that checks out in this repo (the rest are stubs delegating to jebel-quant/rhiza) and
# each of its checkouts uses fetch-depth: 0. The backstop is its "Verify built
# distribution version" step, which parses the filename in dist/ and fails the release
# unless it carries the tag -- nothing earlier can catch a wrong derived version.
source = "vcs"
[tool.rhiza-task]
# Settings recovered from the make layer that rhiza v1.4.0 retired (.rhiza/rhiza.mk,
# .rhiza/make.d/*.mk, .rhiza/.env). They have nowhere else to live now, and each one
# below differs from the rhiza-task default — leaving it out silently weakens a gate.
# make: `TYPECHECKER ?= both` (python.mk). CLI default: "ty" alone.
# Without this the `typecheck` gate drops `mypy --strict src` and runs ty only.
# Note it also gets stricter than the make layer was: the old shell `case` let mypy's
# status decide, so a ty failure could pass. Both must now be green.
typechecker = "both"
# make: `RHIZA_CHECKS_VERSION ?= 0.2.1` (quality.mk). CLI default: the v0.2.0 git ref.
# Without this the rhiza-test gate silently downgrades to the older check set.
#
# Raised 0.2.1 -> 0.6.0 when [project].version became dynamic. Every release up to and
# including 0.5.0 reads `project["version"]` unconditionally, so a derived version fails
# test_version_follows_semver (empty string against the semver regex) and the git-tag
# comparison (InvalidVersion on ""). 0.6.0 is the first release that asks whether the
# version is dynamic and skips those two assertions; there is no older version to pin.
pytest-rhiza = "pytest-rhiza==0.6.0"
# make: `MKDOCS_EXTRA_PACKAGES = --with 'mkdocstrings[python]' --with-editable '.[hyper]'`
# (Makefile). CLI default: ["mkdocstrings[python]"] only. Each entry becomes one `--with`,
# and naming the setting REPLACES the default list — so mkdocstrings is repeated here
# deliberately rather than inherited. Without ".[hyper]" the isolated uvx env that builds
# the book cannot import tinycta and `book` dies with
# "ModuleNotFoundError: No module named 'tinycta'"; the hyper extra is required because
# mkdocstrings/griffe imports tinycta.hyper, and tinycta.linalg pulls in cvx-linalg.
mkdocs-extra-packages = ["mkdocstrings[python]", ".[hyper]"]
# Not set, on purpose — the make layer's value already equals the rhiza-task default,
# so pinning it here would only create a second place to drift:
# source-folder ("src"), tests-folder ("tests"), marimo-folder ("docs/notebooks"),
# coverage-fail-under (90 — and [tool.coverage.report] sets no fail-under to outrank it),
# book-output ("_book"), zensical-version (">=0.0.36"),
# uv-sync-args ("--all-extras --all-groups"), license-fail-on ("GPL;LGPL;AGPL").
# ci-os-matrix is deliberately NOT set: .rhiza/.env carried a comment explaining that
# rhiza_ci.yml exports the matrix per caller, and pinning it here defeats that.
# license-ignore-packages stays empty: the make layer's only entry was `+= docutils` from
# the template's own marimo.mk, and rhiza-task appends docutils itself when marimo is
# in the task registry.
# rhiza-checks stays unset: the make layer accumulated five checks via `RHIZA_CHECKS +=`
# across python.mk/quality.mk/test.mk, and rhiza-task derives exactly those five from
# the layer set. Verified identical.
# layers stays unset: it is detected from the manifests present, and resolves to "python".
[tool.deptry.package_module_name_map]
cvx-linalg = "cvx"
loguru = "loguru"
numpy = "numpy"
optuna = "optuna"
pandas-stubs = []
polars = "polars"
pre-commit = "pre_commit"
marimo = "marimo"
pydantic = "pydantic"
pyyaml = "yaml"
types-pyyaml = []
[tool.bumpversion]
# Lives here, not in .rhiza/.cfg.toml: bump-my-version only auto-discovers
# .bumpversion.toml, .bumpversion.cfg, setup.cfg and pyproject.toml. From a
# path it never reads, it silently falls back to `git describe` and can cut a
# release at a version that already exists.
#
# No current_version and no [[tool.bumpversion.files]] entry for the version:
# there is no longer a version written anywhere to rewrite. [project].version is
# dynamic (see [tool.hatch.version]), so the tag alone decides what gets built and
# a release is a tag, not an edit. The table stays because bump-my-version still
# has to *discover* a config -- from a path it never reads it falls back to
# `git describe` -- and because the two settings below still bind if it is run.
allow_dirty = false
# /rhiza:release commits and tags itself so the changelog lands in the bump
# commit; a bare `bump-my-version bump` would add a second commit and a
# duplicate tag.
commit = false
tag = false
[tool.check_test_layout]
# Enforced by scripts/check_test_layout.py (wired into .pre-commit-config.yaml)
# rather than by the strict upstream gate. That variant keeps the forward rule
# intact — every source module needs a mirrored test file, every source class a
# matching Test* class — and relaxes only the reverse orphan-class rule, because
# tests here are grouped into behavioural classes (TestRiskPosition,
# TestOutputPathConfinement) that describe a scenario around a source *function*.
# Meta-tests, property suites and three named auxiliary suites are
# allowlisted. Per-module coverage is guaranteed independently by the full
# statement-and-branch coverage gate.
enforce = false
# No "%" anywhere in this value: radon reads every [tool.*] table in this file
# through configparser, whose interpolation treats "%" as a sigil and raises
# "invalid interpolation syntax" before radon can run at all.
reason = "Enforced by scripts/check_test_layout.py (pre-commit): strict forward mirroring plus a documented allowlist for meta/property/auxiliary suites; per-module coverage guaranteed by the full statement-and-branch coverage gate."
[tool.coverage.run]
branch = true