Skip to content

Commit a5b532b

Browse files
lsbardelclaude
andauthored
Bump to 0.9.0 (#60)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 73880ac commit a5b532b

6 files changed

Lines changed: 156 additions & 41 deletions

File tree

.github/copilot-instructions.md

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,25 +45,3 @@ applyTo: '/**'
4545

4646
* Strategy runtime markdown descriptions (read by `load_description()` at runtime) live inside the package at `quantflow/options/strategies/docs/` — they must be inside the package to be accessible when the library is installed
4747
* mkdocs documentation pages live in `docs/api/options/` — do not mix these two locations
48-
49-
## Releasing
50-
51-
The release procedure is fully driven by `make release` and the `release.yml` workflow:
52-
53-
1. Bump `version` in `pyproject.toml` to the new release version.
54-
2. Add a `## vX.Y.Z` section to `docs/release-notes.md` with the notes for the release. The header text is matched verbatim by the workflow's `awk` extractor, so it must be `## vX.Y.Z` exactly (no trailing dash, no title after the version).
55-
3. Commit and merge to `main`.
56-
4. From `main`, run `make release` — it reads the version from `pyproject.toml`, prompts for confirmation, then creates an annotated `vX.Y.Z` tag and pushes it.
57-
5. The tag push triggers `.github/workflows/release.yml`, which runs lint and tests, publishes the package to PyPI (`make publish`), and posts the extracted `## vX.Y.Z` section as the GitHub Release body.
58-
59-
Do not publish to PyPI manually or via the old `head_commit.message == 'release'` flow — the tag-triggered workflow is the only supported path.
60-
61-
### Release-notes conventions
62-
63-
The `## vX.Y.Z` section in `docs/release-notes.md` must follow these conventions, since the same content is rendered both on the docs site and as the GitHub Release body:
64-
65-
* Open with a one-paragraph summary describing the theme of the release. If the release contains breaking changes, point readers to the **Breaking changes** section in that paragraph.
66-
* Group entries under H3 subsections in this order: `### Breaking changes`, `### New features`, `### Improvements and fixes`, `### Documentation and assets`. Omit any subsection that has no entries.
67-
* Every PR reference must be a markdown link of the form `[#NN](https://github.com/quantmind/quantflow/pull/NN)`. Never write a bare `(#NN)` — both readers (docs and GitHub) benefit from the explicit URL, and GitHub's auto-linking only works in some contexts. When a single entry references multiple PRs, list them comma-separated inside one set of parentheses, each as its own markdown link.
68-
* Build the PR list by running `git log vPREV..HEAD --oneline` against the previous release tag and following each squashed-merge commit back to its PR. Cross-check with `gh pr list --state merged --base main` for any PRs merged since the previous tag.
69-
* End the section with a `[Full changelog](https://github.com/quantmind/quantflow/compare/vPREV...vX.Y.Z)` link comparing the new tag against the previous one.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Release Instructions
2+
3+
Releases are driven by `v*` git tags. Pushing a tag triggers
4+
`.github/workflows/release.yml`, which runs lint and the test suite, publishes
5+
the package to PyPI (`make publish`), then extracts the matching `## vX.Y.Z`
6+
section from `docs/release-notes.md` and publishes it as the GitHub Release
7+
body.
8+
9+
## Cutting a release
10+
11+
1. Bump `version` in `pyproject.toml` to the new release version.
12+
2. Add a `## vX.Y.Z` section at the top of `docs/release-notes.md` with the
13+
notes for the release. The header text is matched verbatim by the
14+
workflow's `awk` extractor, so it must be `## vX.Y.Z` exactly (no trailing
15+
dash, no title after the version). The release workflow fails if this
16+
section is missing.
17+
3. Commit and merge to `main`; let the `build` workflow pass.
18+
4. From `main`, run `make release` — it reads the version from
19+
`pyproject.toml`, asks for confirmation, then creates an annotated `vX.Y.Z`
20+
tag and pushes it. The `release` workflow takes it from there.
21+
22+
Do not publish to PyPI manually, and do not revive the old
23+
`head_commit.message == 'release'` flow — the tag-triggered workflow is the
24+
only supported path.
25+
26+
## Release-notes conventions
27+
28+
The `## vX.Y.Z` section in `docs/release-notes.md` is rendered both on the
29+
docs site and as the GitHub Release body, so it must follow these conventions:
30+
31+
- Open with a one-paragraph summary describing the theme of the release. If
32+
the release contains breaking changes, point readers to the **Breaking
33+
changes** section in that paragraph.
34+
- Group entries under H3 subsections in this order: `### Breaking changes`,
35+
`### New features`, `### Improvements and fixes`,
36+
`### Documentation and assets`. Omit any subsection that has no entries.
37+
- Every PR reference must be a markdown link of the form
38+
`[#NN](https://github.com/quantmind/quantflow/pull/NN)` — never a bare
39+
`(#NN)`. GitHub's auto-linking only works in some contexts, and the explicit
40+
URL works everywhere. When one entry references multiple PRs, list them
41+
comma-separated inside one set of parentheses, each as its own link.
42+
- Build the PR list by running `git log vPREV..HEAD --oneline` against the
43+
previous release tag and following each squashed-merge commit back to its
44+
PR. Cross-check with `gh pr list --state merged --base main` for any PRs
45+
merged since the previous tag.
46+
- End the section with a
47+
`[Full changelog](https://github.com/quantmind/quantflow/compare/vPREV...vX.Y.Z)`
48+
link comparing the new tag against the previous one.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@readme.md
22
@.github/copilot-instructions.md
33
@.github/instructions/makefile.instructions.md
4+
@.github/instructions/release.instructions.md
45
@.github/instructions/tutorial.instructions.md

docs/release-notes.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,94 @@ below maps to a tagged release on
66
pushed, the matching section is extracted by
77
`.github/workflows/release.yml` and published as the GitHub Release body.
88

9+
## v0.9.0
10+
11+
Pricing-engine and calibration overhaul. `MaturityPricer` now evaluates call
12+
prices and Greeks lazily at arbitrary log-strikes instead of carrying a
13+
precomputed grid, Fourier pricers take a moneyness-based truncation parameter,
14+
and the volatility-surface calibration can fit Black implied vols directly.
15+
This release contains several API changes: see **Breaking changes** below.
16+
17+
### Breaking changes
18+
19+
**`MaturityPricer` reworked.** ([#59](https://github.com/quantmind/quantflow/pull/59))
20+
21+
- The precomputed `std`, `log_strike` and `call` arrays are gone. A
22+
`MaturityPricer` now holds a single `pricing` field (an
23+
`OptionPricingResult`) that evaluates call prices and Greeks on demand at
24+
any log-strike.
25+
- `moneyness` is now a method, `moneyness(log_strikes)`, not a cached array
26+
property. The `time_value` and `intrinsic_value` array properties and the
27+
`interp(...)` helper were removed; use `prices(log_strikes)` to get a
28+
DataFrame of prices and implied vols on a chosen log-strike grid.
29+
30+
**Fourier pricing truncation: `max_log_strike` → moneyness parameters.**
31+
([#59](https://github.com/quantmind/quantflow/pull/59))
32+
33+
- `Marginal1D.call_option`, `call_option_carr_madan` and `call_option_lewis`
34+
take `max_moneyness` (a multiple of the marginal standard deviation)
35+
instead of `max_log_strike`. The COS path takes
36+
`cos_moneyness_std_precision` instead.
37+
- `OptionPricingResult.call_at(...)` is renamed `call_price(...)`, the
38+
`method` field is removed, and a new abstract `call_greeks(log_strike)`
39+
returns a `Greeks` namedtuple `(price, delta, gamma)`.
40+
41+
**`OptionPricerBase.call_price``call_prices`.**
42+
([#59](https://github.com/quantmind/quantflow/pull/59)) The method is now
43+
vectorised: it takes arrays of times-to-maturity and log-strikes and prices
44+
them in a single maturity-grouped call.
45+
46+
**`DIVFMPricer` no longer builds a fixed moneyness grid.**
47+
([#59](https://github.com/quantmind/quantflow/pull/59)) The
48+
`max_moneyness_ttm` and `n` fields are removed; the fitted IV surface is
49+
evaluated on demand through `OptionPricingResultDIVFM`.
50+
51+
### New features
52+
53+
- **Implied-vol calibration residuals.** New `ResidualKind` enum and a
54+
`residual_kind` field on `VolModelCalibration`: set it to `ResidualKind.IV`
55+
to fit the model to Black implied vols (recovered by inverting the model
56+
price) rather than to forward-space prices. The IV residual is naturally
57+
well-scaled across moneyness, so `moneyness_weight` is not applied in that
58+
mode. ([#59](https://github.com/quantmind/quantflow/pull/59))
59+
- **Greeks from the pricing result.** `OptionPricingCosResult.call_greeks`
60+
returns closed-form price, delta and gamma from the COS expansion; the
61+
transform-based result derives delta and gamma by differentiating the call
62+
grid; DIVFM uses finite differences on the fitted surface.
63+
([#59](https://github.com/quantmind/quantflow/pull/59))
64+
- **COS truncation control on `OptionPricer`.** New
65+
`cos_moneyness_std_precision` field (default 12) sets the width of the COS
66+
integration interval in standard deviations.
67+
([#59](https://github.com/quantmind/quantflow/pull/59))
68+
69+
### Improvements and fixes
70+
71+
- Calibration residuals are now computed in a single vectorised pricing call.
72+
Deep-wing strikes where the model price falls outside the no-arbitrage band
73+
(so Newton fails to invert it) are masked out instead of poisoning the fit,
74+
and a parameter set that fails to invert on more than half the options is
75+
rejected with a large penalty.
76+
([#59](https://github.com/quantmind/quantflow/pull/59))
77+
- Calibration plots now evaluate the model on a fresh moneyness grid;
78+
`plot(max_moneyness=...)` no longer accepts `None`.
79+
([#59](https://github.com/quantmind/quantflow/pull/59))
80+
- `OptionEntry.mid_price()` no longer caches through a private attribute.
81+
([#59](https://github.com/quantmind/quantflow/pull/59))
82+
- Stale Jupytext notebook mirrors under `notebooks/` removed.
83+
([#59](https://github.com/quantmind/quantflow/pull/59))
84+
85+
### Documentation and assets
86+
87+
- New GitHub social-preview banner under `docs/assets/logos/png/`.
88+
([#59](https://github.com/quantmind/quantflow/pull/59))
89+
- `docs/api/options/black.md` and the volatility-surface calibration examples
90+
updated for the new pricer API.
91+
([#59](https://github.com/quantmind/quantflow/pull/59))
92+
- The release procedure moved out of `.github/copilot-instructions.md` into
93+
its own `.github/instructions/release.instructions.md`.
94+
95+
[Full changelog](https://github.com/quantmind/quantflow/compare/v0.8.0...v0.9.0)
96+
997
## v0.8.0
1098

1199
Volatility-surface calibration overhaul. This release adds a two-factor BNS

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "quantflow"
3-
version = "0.8.0"
3+
version = "0.9.0"
44
description = "quantitative analysis"
55
authors = [ { name = "Luca Sbardella", email = "luca@quantmind.com" } ]
66
license = "BSD-3-Clause"

uv.lock

Lines changed: 18 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)