V0 Changelog#
0.3.0 (2026-09-27)#
Added#
One licence check for every KaxaNuk library. Attribution validates its licence through
kaxanuk-license-client1.0, the package the Backtest Engine, Attribution Analysis and Portfolio Construction share, instead of a validator of its own. It is a new dependency,kaxanuk-license-client~=1.0, which takes the client’s fixes without a new attribution release, and it comes from KaxaNuk’s private package index, the one thepip installcommand of the welcome email names, which serves it to any valid licence.services.license_validatorstays as a thin wrapper with the names attribution and the KaxaNuk Research Lab use:validate_license(),_state(now the client’s own dict, changed in place and never replaced), the licence errors as attributes of the module, and a newreset_validation_state(), which forgets that the process validated so the next call checks again. It also holdsPRODUCT, what attribution tells the client about itself: the productattribution-analysis, the key inKNAA_API_KEY_KAXANUK, another server inKNAA_LICENSE_SERVER_URL, the unified licence server by default, and the logger it has always used,kaxanuk.attribution_analysis.services.license_validator. The Research Lab, which puts each user’s key inKNAA_API_KEY_KAXANUK, clears_state["validated"]before validating and catches the errors by name, keeps working as it is.``LicenseConfigurationError``, raised when
KNAA_LICENSE_SERVER_URLorKAXANUK_LICENSE_SERVER_URLis not an http or https URL a request can be sent to, before anything is sent. The licence errors,LicenseErrorand its four subclasses, now inherit fromAttributionAnalysisErrorand from the client’s matching error at once, so bothexcept AttributionAnalysisErrorandexcept kaxanuk.license_client.LicenseErrorcatch them.``KNAA_LICENSE_SERVER_URL`` points attribution, and only attribution, at another licence server.
KAXANUK_LICENSE_SERVER_URLstill works, for every KaxaNuk library, and is read after it.
Changed#
The licence is checked on the unified KaxaNuk licence server, for this product. Without a server variable, attribution validates on the licence server that serves every KaxaNuk library instead of on a server of its own, and the request names the product,
attribution-analysis, and attribution’s version: a licence that does not include Attribution Analysis is refused with a message naming the products it does include.The analysis keeps running when the licence server cannot be reached, for 3 days. A successful check is saved, and inside 24 hours a run does not contact the server at all, as before. When the server cannot be reached, a check saved less than 3 days ago stands in, with a warning each run saying how much of the grace is left. “Cannot be reached” is now anything that is not a verdict on the licence: no connection, a timeout, a redirect, a 400, 408, 422, 425, 429 or 5xx, or a 200 that cannot be read. In 0.2 the grace was 7 days but covered only connection errors and timeouts, and any answer other than a 200, an outage on our side included, rejected the licence outright. The grace runs from the last successful check, never past the expiry the server reported, and ignores a check stamped more than an hour in the future, so neither repeated offline runs nor a rolled-back clock can stretch it.
A rejection is final. A 401, 402, 403 or 404, or a 200 whose
okis nottrue, raisesLicenseValidationErrorat once and deletes the saved check, so going offline cannot bring a revoked licence back. In 0.2 a rejection left the saved check in place, where it went on standing in offline for up to 7 days after the last success, and a 200 whoseokwas"yes"or1was accepted.Where the saved checks live. One file per licence key, named after the key’s SHA-256 digest, in the folder
%LOCALAPPDATA%\KaxaNuk\licence-cache\attribution-analysison Windows and$XDG_CACHE_HOME/kaxanuk/licence-cache/attribution-analysiselsewhere (~/.cachewithoutXDG_CACHE_HOME);KAXANUK_LICENSE_CACHE_DIRmoves them. Each holds the key’s digest, never the key, is signed, is tied to the device and to Attribution Analysis, and is written atomically, so a process that validates several users’ keys, like the Research Lab’s, never mixes them.~/.kaxanuk_attribution_cache, the single cache of 0.2 and earlier, is neither read nor removed:the first run after upgrading needs to reach the licence server*, and the old file can be deleted by hand.
``.kaxanuk_license`` is read as a ``.env`` file. The line
KNAA_API_KEY_KAXANUK=<key>is attribution’s, and a file holding a single key without a name serves every product; in 0.2 the first line counted, whatever product it named. AKNAA_API_KEY_KAXANUKholding only spaces now counts as unset instead of being sent as an empty key.validate_license()returns the client’sValidationResult: keyword-only, withok,messageand the licence’sexpires_at. Code that built attribution’s two-fieldValidationResultby position has to name its fields. Every licence message and log line is ASCII and never carries the licence key.Development.
kaxanuk-license-clientis the only package taken from KaxaNuk’s private index, and it is taken from nowhere else ([[tool.pdm.source]]withinclude_packagesandexclude_packages): installing the project with PDM needsKAXANUK_INDEX_KEYset to a licence key.Read the Docs no longer installs the package. Installing it would need the licence client, which only the private index serves: autodoc imports the package from
src/,kaxanuk.license_clientis mocked,docs/source/conf.pyreads the version from the source instead of importing it, and thedocsdependency group now also lists the package’s runtime dependencies.
Fixed#
The offline-grace warning reached nobody on a Spanish Windows console. Its em dash cannot be encoded in cp850, and the bare
StreamHandlerinservices.configuration_loggerturned that into aUnicodeEncodeErrorinsidelogging: the user saw--- Logging error ---and the warning itself was lost. The console is now moved to UTF-8 when it is not on it already, a console that refuses to be reconfigured gets the record with the offending characters replaced rather than no record at all, and the optional log file is written as UTF-8 instead of in the machine’s codepage.
0.2.0 (2026-07-12)#
Added#
Input handlers now slices the file right away with the actual start date.
Fixed#
Formating in the [attribution_analysis_parameters.xlsx](templates/attribution_analysis/Config/attribution_analysis_parameters.xlsx) configuration
0.1.0 (2026-07-03)#
Added#
Brinson-Fachler attribution, decomposing active return into allocation, selection and interaction effects per asset and date.
KN Five-Factor Model (KN5FM) attribution, decomposing portfolio return into per-factor contributions plus an idiosyncratic residual.
Excel-based configuration workbook (
attribution_analysis_parameters.xlsx) and CLI (init,run,update,autorun).CSV and Parquet market data input handlers, and CSV/Excel portfolio and benchmark weight handlers.
Interactive Dash dashboard for cumulative factor contributions and summary statistics.
License key validation against the KaxaNuk license server, with local caching and an offline grace period.
Added a data-integrity check to PortfolioWeights that rejects weight series without
~daily (240–260/year) observation density, catching backtest-granularity files passed in by mistake. * Auto date alignment across all input tables (asset returns, portfolio/benchmark weights,
benchmark returns, factor returns) to their common date range before running any calculation.
User-defined column name mapping for market-data inputs, so CSV/Parquet files don’t need to match a fixed schema.
Performance statistics module (Sharpe ratio, annualized return/volatility, skewness, kurtosis, max drawdown, historic and Gaussian VaR/CVaR) surfaced in the dashboard’s summary panel.
Synthetic factor-exposure generator for prototyping the factor model pipeline without real factor data.
PyArrow-based columnar architecture used throughout for high-performance, vectorized computation.
Pandas-based reference implementations of both attribution methodologies, provided alongside the PyArrow implementations for validation and comparison.
Excel-workbook schema-version check that prompts
update excelwhen the configuration template is outdated.