Skip to content

Releases

trendfollowing v1.4.0

Choose a tag to compare

@ArturSepp ArturSepp released this 22 Oct 04:09

Changed

  • Dropped Python 3.10 support; the minimum supported Python version is now 3.11.
  • Required patched Pillow >= 13.0.0 for every supported interpreter and removed the
    Python 3.10 lockfile fallback to Pillow 12.3.0.
  • Updated the CI matrix, minimum-dependency job and installation documentation for
    Python 3.11+, and removed the obsolete test/docs TOML parser compatibility dependency.

Fixed

  • Updated the locked certifi dependency to 2026.10.19 to address its reported vulnerability.

Installation

python -m pip install --upgrade "trendfollowing==1.4.0"

Requires Python 3.11+ and Pillow 13.0.0+.

trendfollowing v1.3.0

Choose a tag to compare

@ArturSepp ArturSepp released this 01 Oct 11:40
396dd43

What's Changed

  • Add automatic Desktop checks and protect main with required CI by @ArturSepp in #15
  • Remove the JOIM paper's tests and references by @ArturSepp in #16
  • Add the trendfollowing handbook to the documentation by @ArturSepp in #17
  • Release trendfollowing 1.3.0 by @ArturSepp in #18

Full Changelog: v1.2.0...v1.3.0

trendfollowing 1.1.0

Choose a tag to compare

@ArturSepp ArturSepp released this 17 Aug 05:32
9e56f58

trendfollowing 1.1.0

This non-breaking adoption release makes the package easier to install, discover, verify, and
use outside a source checkout.

Highlights:

  • migrated the installable package to a standard src/ layout;
  • bundled the immutable futures dataset in wheels and source distributions;
  • added deterministic root examples and task-oriented documentation;
  • aligned package, citation, README, runtime, and documentation metadata;
  • added clean-wheel, deployed-documentation, resource, and version-contract checks; and
  • brought package code, tests, and examples under the declared Ruff E/F/W gate.

The full test matrix, independent numerical replication checks, warning-as-error documentation
build, artifact inspection, and clean wheel/sdist installs passed before publication. Numerical
results and public call signatures are unchanged.

See the changelog
and documentation.

v1.0.5

Choose a tag to compare

@ArturSepp ArturSepp released this 01 Aug 18:07

Fixed

  • Every axis=1 pd.concat in trendfollowing and in papers/ states sort= explicitly — 62 call sites, 43 sort=True where the joined index is dates and 19 sort=False where it is a lag, a span, a Monte-Carlo path or a fund label. pandas 2.2 sorted the union of two DatetimeIndexes whatever the argument said; pandas 3.0 honours an explicit sort=False and pandas 4 drops the implicit sort too. The exposure is the same in both trees: a backtest nav joined to a benchmark on a different calendar (backtests.py, backtest_figs.py, paper_figures.py) would be built on an out-of-order time axis, with no exception — a different number in a published exhibit. Behaviour under the installed pandas is unchanged; the arguments state what was already happening.

Added

  • tests/test_concat_sort_convention.py: an axis=1 pd.concat under trendfollowing/ or papers/ without an explicit sort= fails the suite. Static — reads the source with ast and imports nothing.

Full changelog: CHANGELOG.md

trendfollowing 1.0.4

Choose a tag to compare

@ArturSepp ArturSepp released this 28 Jul 19:14

Portfolio-level volatility targeting in the European system produced undefined
leverage on days of non-positive portfolio variance, and this release is the first
to carry the fix.
np.reciprocal(..., where=portfolio_var > 0.0) was called
without out=, so the cells the mask skips were left holding whatever the freshly
allocated buffer contained rather than zero. run_european_tf_system with
portfolio_covar_span set could therefore apply arbitrary leverage on those days,
and the value was not reproducible between runs. The fix (4b6e39a, 2026-07-22)
allocates a zero array and passes it as out=, so a non-positive-variance day
gets zero leverage. Any European-system result produced with portfolio_covar_span
set on a version at or below 1.0.3 should be regenerated.

trendfollowing/systems/american.py and trendfollowing/systems/tsmom.py still
call np.reciprocal the same way. Those two lines are unchanged in this release
and are the open item behind it.

1.0.3 was published without a changelog entry; it was a version bump in
pyproject.toml and nothing else (ff28a8a).

Added

  • tests/test_version_metadata.py: pyproject.toml, CITATION.cff and the
    @software BibTeX entry in README.md must carry the same version, and
    date-released must be an ISO date. The three had drifted — see below.
  • A version-carrying @software BibTeX entry in README.md. The README cited the
    paper and nothing else, so a replication had no way to record which version of
    the code it ran; for a replication package that is the citation that matters.

Fixed

  • CITATION.cff said 1.0.0 against a published 1.0.3, so anyone citing the package
    from that file named a release three patches behind the code that produced the
    paper's tables. It now says 1.0.4 with a current date-released, and the new test
    fails if it drifts again.

Changed

  • numpy floor raised to >=2.0, matching the rest of the stack. No resolution
    changes: qis already requires it, so every install has resolved numpy 2.x
    regardless of what this file declared.
  • ruff no longer selects I. Import order here groups the scientific stack before
    the project packages, which isort's ordering contradicts; the rule was selected in
    this repository and in no other of the stack.
  • AGENTS.md records the top-level tests/ layout as a deliberate
    replication-package deviation rather than a drift from the in-package convention
    the siblings use.

Removed

  • .coverage and example_ar1_knife_edge.png are no longer tracked. Both are
    generated: the PNG is written into the working directory by
    examples/analytic_sharpe_vs_span.py, and nothing in the README or the papers
    tree references it. .gitignore now covers .coverage* and example_*.png.

trendfollowing 1.0.3

Choose a tag to compare

@ArturSepp ArturSepp released this 22 Jul 16:06

Internal cleanup; no public API or numerical change.

Changed

  • universe.generate_data no longer passes the unused credit_df argument when persisting the packaged dataset, and a commented-out @qis.timer decorator on load_data is removed. No public signature changes; the packaged data are unaffected.

Notes

  • Install: pip install trendfollowing==1.0.3
  • Full history in CHANGELOG.md.

trendfollowing 1.0.2

Choose a tag to compare

@ArturSepp ArturSepp released this 22 Jul 16:03

Internal cleanup; no public API or numerical change.

Changed

  • universe.generate_data no longer passes the unused credit_df argument when persisting the packaged dataset, and a commented-out @qis.timer decorator on load_data is removed. No public signature changes; the packaged data are unaffected.

Notes

  • Install: pip install trendfollowing==1.0.2
  • Full history in CHANGELOG.md.

trendfollowing 1.0.1

Choose a tag to compare

@ArturSepp ArturSepp released this 22 Jul 06:47

Centralises the return conventions shared by the two trend-following papers into a single module, and fixes paper typos. First tagged release.

Added

  • trendfollowing.conventions: the single source for the conventions both papers fix. Exports AF_DAILY = 260 (the paper's trading-day annualisation, used in place of the 252 that qis infers from the calendar density of the futures panel, so the papers pass the constant explicitly rather than relying on inference), PPY_QUARTERLY = 4, PPY_MONTHLY = 12 and compute_daily_annualised_vol. Sharpe ratios are arithmetic throughout — sqrt(a) * mean / std of periodic simple excess returns — because the JOIM paper's regime decomposition (Proposition 1) is exact only under arithmetic means and the SIFIN paper's analytic Sharpe ratios use the same convention. All four symbols are re-exported from the package top level.

Changed

  • Replication scripts (aggregated_skewness_fig.py, sg_sharpe_test.py, verify_skewness_directions.py) now take their annualisation and Sharpe convention from trendfollowing.conventions instead of restating it locally.
  • Daily futures data are stored as prices built from log returns; returns are extracted with qis.to_returns with the is_log_returns flag stated at the call, and periodic returns for regime sampling are arithmetic simple returns at calendar anchors.

Fixed

  • Typos in the SIFIN paper source; removed a stray sg.log and a generated .thm file from the repository.

Notes

  • Install: pip install trendfollowing==1.0.1
  • No prior tags exist; this is the first tagged release, superseding 1.0.0 on PyPI.