Skip to content

Commit a85138f

Browse files
authored
Release notes (#57)
1 parent 523571e commit a85138f

6 files changed

Lines changed: 170 additions & 3 deletions

File tree

.github/copilot-instructions.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,15 @@ 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.

.github/workflows/build.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ jobs:
4949
with:
5050
token: ${{ secrets.CODECOV_TOKEN }}
5151
files: ./build/coverage.xml
52-
- name: publish
53-
if: ${{ matrix.python-version == '3.14' && github.event.head_commit.message == 'release' }}
54-
run: make publish
5552

5653
image:
5754
if: github.ref == 'refs/heads/main'

.github/workflows/release.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: release
2+
3+
# Triggered by `v*` tags. Builds and publishes the package to PyPI, then
4+
# extracts the matching section from docs/release-notes.md and publishes it
5+
# as the GitHub Release body. Re-runs idempotently update an existing
6+
# release rather than failing.
7+
8+
on:
9+
push:
10+
tags:
11+
- "v*"
12+
13+
permissions:
14+
contents: write
15+
16+
jobs:
17+
release:
18+
runs-on: ubuntu-latest
19+
env:
20+
PYTHON_ENV: ci
21+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23+
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
24+
FMP_API_KEY: ${{ secrets.FMP_API_KEY }}
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- name: install rops
29+
uses: quantmind/rops/.github/actions/setup-rops@main
30+
env:
31+
GITHUB_TOKEN: ${{ secrets.TOKEN_DEPLOYMENT }}
32+
33+
- name: install taplo
34+
run: rops tools update taplo
35+
36+
- name: Set up Python
37+
uses: actions/setup-python@v5
38+
with:
39+
python-version: "3.14"
40+
41+
- name: Install uv
42+
run: pip install -U pip uv
43+
44+
- name: Install dependencies
45+
run: make install-dev
46+
47+
- name: run lint
48+
run: make lint-check
49+
50+
- name: run tests
51+
run: make tests
52+
53+
- name: publish to PyPI
54+
run: make publish
55+
56+
- name: Extract release notes
57+
run: |
58+
TAG="${GITHUB_REF_NAME}"
59+
awk -v tag="## ${TAG}" '
60+
$0 == tag { in_section = 1; next }
61+
/^## / && in_section { exit }
62+
in_section { print }
63+
' docs/release-notes.md > /tmp/notes.md
64+
if [ ! -s /tmp/notes.md ]; then
65+
echo "No section '## ${TAG}' found in docs/release-notes.md" >&2
66+
exit 1
67+
fi
68+
echo "--- extracted notes for ${TAG} ---"
69+
cat /tmp/notes.md
70+
71+
- name: Publish GitHub Release
72+
run: |
73+
TAG="${GITHUB_REF_NAME}"
74+
if gh release view "$TAG" >/dev/null 2>&1; then
75+
gh release edit "$TAG" --notes-file /tmp/notes.md
76+
else
77+
gh release create "$TAG" --title "$TAG" --notes-file /tmp/notes.md
78+
fi

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,17 @@ publish: ## Release to pypi
4848
@uv build
4949
@uv publish --token $(PYPI_TOKEN)
5050

51+
.PHONY: release
52+
release: ## Tag current version (from pyproject.toml) and push
53+
$(eval VERSION := $(shell grep '^version' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/'))
54+
@read -p "Tagging with v$(VERSION), are you sure? [Y/n] " ans; \
55+
ans=$${ans:-Y}; \
56+
if [ "$$ans" = "Y" ] || [ "$$ans" = "y" ]; then \
57+
git tag -a v$(VERSION) -m "v$(VERSION)" && git push origin v$(VERSION); \
58+
else \
59+
echo "Aborted."; \
60+
fi
61+
5162
.PHONY: tests
5263
tests: ## Unit tests
5364
@./dev/test

docs/release-notes.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Release Notes
2+
3+
This page is the source of truth for quantflow release notes. Each section
4+
below maps to a tagged release on
5+
[GitHub](https://github.com/quantmind/quantflow/releases). When a new tag is
6+
pushed, the matching section is extracted by
7+
`.github/workflows/release.yml` and published as the GitHub Release body.
8+
9+
## v0.8.0
10+
11+
Volatility-surface calibration overhaul. This release adds a two-factor BNS
12+
model, a double-Heston model (with optional jumps), Lewis and COS pricing
13+
methods, and reworks the calibration package layout. Several module renames
14+
and signature changes were made along the way: see **Breaking changes** below.
15+
16+
### Breaking changes
17+
18+
**Module renames.**
19+
20+
- `quantflow.sp.weiner` is now `quantflow.sp.wiener` (typo fix). Update
21+
imports.
22+
- `quantflow.options.calibration` is now a package, not a single module.
23+
Top-level imports keep working through the package `__init__.py`
24+
re-exports. Code reaching into the old `quantflow.options.heston_calibration`
25+
must switch to `quantflow.options.calibration.heston`.
26+
27+
**`ModelOptionPrice` field rename.** (#47)
28+
29+
- `ModelOptionPrice.moneyness` previously meant `log(K/F)`. It now means
30+
standardised moneyness `log(K/F) / sqrt(ttm)`, and the raw log-strike is
31+
exposed as a new field `log_strike`. Code reading `option.moneyness` and
32+
expecting a log-strike must switch to `option.log_strike`.
33+
- `get_intrinsic_value(moneyness=...)` argument renamed to `log_strike=...`.
34+
35+
### New features
36+
37+
- **`BNS2`**: two-factor Barndorff-Nielsen & Shephard stochastic-volatility
38+
model with a single Brownian motion driving a convex combination of
39+
independent Gamma-OU variances and per-factor leverage. New section in the
40+
BNS calibration tutorial. (#54)
41+
- **`DoubleHeston` and `DoubleHestonJ`**: two-factor Heston (with optional
42+
log-price jumps) and matching `DoubleHestonCalibration` /
43+
`DoubleHestonJCalibration`. (#46)
44+
- **Lewis and COS option-pricing methods**: selectable via
45+
`OptionPricingMethod`, alongside the existing Carr-Madan / FFT path. (#47)
46+
- **CIR tutorial** with PDF comparison example. (#49)
47+
48+
### Improvements and fixes
49+
50+
- Heston calibration convergence fixes. (#45, #49)
51+
- BNS calibration: dedicated `BNSCalibration` class extracted, characteristic
52+
exponent derivation cleaned up, broader test coverage. (#50, #51)
53+
- OU module reworked: clearer Gamma-OU API, stronger tests for moments and
54+
the integrated Laplace transform. (#51)
55+
- `pricing_method_comparison` example simplified; redundant time-comparison
56+
code removed. (#48)
57+
58+
### Documentation and assets
59+
60+
- New logo set (favicon, lockup, marks, social banners) under
61+
`docs/assets/logos/`. (#53)
62+
- New `docs/mcp.md` page covering the MCP server.
63+
- Bibliography rebuilt from BibTeX via `docs/bib2md.py`; glossary expanded;
64+
mathjax tweaks for inline rendering. (#47, #49)
65+
- Tutorial-writing instructions added at
66+
`.github/instructions/tutorial.instructions.md`.
67+
68+
[Full changelog](https://github.com/quantmind/quantflow/compare/v0.7.0...v0.8.0)

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ nav:
131131
- Glossary: glossary.md
132132
- Contributing: contributing.md
133133
- Bibliography: bibliography.md
134+
- Release Notes: release-notes.md
134135
markdown_extensions:
135136
- attr_list
136137
- tables

0 commit comments

Comments
 (0)