V0 Changelog#
0.58.6 (2026-05-19)#
Fixed#
generate_comprehensive_excel_reportnow restores thedateindex column on theportfolio_bench_total_valuesheet.pd.concat([register_df, benchmark[...]], axis=1)was silently droppingindex.namebecause the two source DataFrames carried different names (register_df.index.name == "date"vsbenchmark.index.name == "date_column"fromStandardField.DATE.value). Without a name,include_index = dataframe.index.name is not NoneevaluatedFalseand the writer skipped both the header and every date cell, leaving the sheet with only the value columns. The concat result is now explicitly renamed to"date", mirroring the other data sheets.
0.58.5 (2026-05-13)#
Changed#
BatchConfigParser.parse_dict()/parse_file()now rejectexecution_priceinglobal_defaultswith aBatchConfigErrorpointing touser_column_trade_execution_price. The key was silently ignored since v0.57.0 (whenexecution_pricewas removed from the Excel configuration and order execution was wired toStandardField.TRADE_EXECUTION_PRICEexclusively), which let users believe they were configuring the execution price via the batch dict/YAML when in fact onlyuser_column_trade_execution_pricewas being read. Surfacing the error closes that hidden mismatch and makes the batch path consistent with the Excel path.
0.58.4 (2026-05-13)#
Changed#
MultiPortfolioRunner.run()now logs the empty-batch failure vialogger.error(...)before raisingNoPortfoliosDiscoveredError. The error message appears as a single[ERROR]line in the configured logger format (matching the surrounding[INFO] Discovered 0 portfolio files ...line) instead of only surfacing as a raw Python traceback when callers invoke the runner directly without a top-leveltry/except BacktestErrorwrapper like the one inbacktest_engine.main().
0.58.3 (2026-05-13)#
Added#
NoPortfoliosDiscoveredErrorexception (subclass ofBatchConfigError→ConfigurationError) exported fromkaxanuk.backtest_engine.exceptions.
Fixed#
MultiPortfolioRunner.run()no longer crashes with an opaqueIndexError: list index out of rangeinside_build_reference_configurationwhenportfolio_directoryis configured but resolves to zero portfolios (empty directory, missing directory, or no files matching the expected format). It now raisesNoPortfoliosDiscoveredErrorwith a message that includes the scanned directory and the expected format.
0.58.2 (2026-05-12)#
Fixed#
MultiPortfolioBacktester.generate_individual_reportsnow sets the benchmarkDatetimeIndexfrom the canonicalStandardField.DATEcolumn (currently"date_column") instead of the literal string"date"that does not exist in the schema. The old lookup silently fell through and calledpd.to_datetimeon the integer RangeIndex (0, 1, 2, …), producing timestamps near 1970-01-01 that propagated to every annual-returns row, the Max Drawdown Date of the benchmark, and the embedded chart. Annual returns and Max Drawdown Date for the benchmark now align with the portfolio’s date range. Same fix applied to theregister_dflookup for symmetry.
0.58.1 (2026-05-12)#
Fixed#
portfolio_drawdown_viznow picks thedate_columnfrom the benchmark DataFrame when present, instead of relying on its index. The previous 0.58.0 fix coerced the index to datetime, but when the benchmark comes from apa.Table.to_pandas()the index is a plain RangeIndex (0, 1, 2, …) andpd.to_datetimeinterpreted those integers as nanoseconds-since-epoch, leaving every point near 1970-01-01 — the visible vertical line in the embedded Excel charts.
0.58.0 (2026-05-12)#
Breaking Changes#
Renamed environment variable
KNPC_API_KEY_KAXANUK→KNBE_API_KEY_KAXANUK. Update yourConfig/.envfile accordingly.
Added#
arrow_to_pandas_for_analysis()helper inkaxanuk.backtest_engine.modules.type_converters. Converts apyarrow.Tableto apandas.DataFramewith analysis-friendly dtypes:decimal128/decimal256columns are coerced tofloat64anddate32/timestampcolumns todatetime64[ns]. Use it when feeding a backtest’s PyArrow result into matplotlib, numpy or scikit-learn.
Fixed#
portfolio_drawdown_vizno longer renders a spurious vertical line at 1970-01-01 when the caller passes a benchmark DataFrame that originated from apa.Table.to_pandas()(object dtype withdatetime.dateindex anddecimal.Decimalvalues). The function now coerces the index and the plotted columns defensively before drawing.
Documentation#
Full Sphinx documentation overhaul: real runtime dependencies in
docs/requirements.txt(no moreMagicMockin signatures), newBacktest Componentssection coveringcost_models,enums,execution,interfacesandorchestratorssubpackages, enriched docstrings across thebacktestpackage and the data/portfolio/market pipelines, CLI page rebuilt with intro + summary table + common workflows, andSee Alsocross-references from load methods to the user guide. Build now finishes with 0 warnings.Fixed two malformed
.. deprecated::directives inportfolio_configuration_service.pyso the rendered notice reads “Deprecated since version 0.40.0: Use load_from_file() instead.” instead of the previous garbled output.load_portfolio_from_nameandload_portfolio_from_weightsare excluded from the Sphinx API reference (still callable from Python for backwards compatibility).
0.57.0 (2026-04-15)#
Breaking Changes#
Removed ``execution_price`` Excel configuration field. Order execution now always uses the column named in
trade_execution_price_column(internally mapped toStandardField.TRADE_EXECUTION_PRICE). To migrate, runkaxanuk.backtest_engine update exceland delete theexecution_pricerow from your existingConfig/backtest_engine_parameters.xlsxif you updated manually.Renamed environment variable
KAXANUK_LICENSE_KEY→KNPC_API_KEY_KAXANUK. Update yourConfig/.envfile accordingly.``MarketDataBundlePyarrow.get_execution_table()`` signature changed. The method no longer accepts an
execution_priceparameter; it returns the TRADE_EXECUTION_PRICE table directly.Excel template format version bumped from
0.54.0to0.56.0. The engine enforces this check at startup — outdated Excels must be regenerated viakaxanuk.backtest_engine update excel.Minimum rebalance dates relaxed from 2 → 1. Users relying on the previous validation for error detection should revisit their portfolio files.
Added#
__parameters_format_version__constant exported fromkaxanuk.backtest_enginefor tracking Excel schema version independently of the package version.Explicit version-compatibility check at Excel load time: raises
ConfigurationHandlerErrorwith a “run update excel” hint when the Excel format is outdated, and logs a warning when the Excel is newer than the engine supports.Support for buy-and-hold portfolios: a single rebalance date is now valid.
Validation preventing any price column (
commission_price_column,trade_execution_price_column,mark_to_market_price_column) from being set to the same value asuser_column_date.packagingadded as an explicit dependency for semantic version comparison.
Changed#
__version__bumped to0.57.0,__parameters_format_version__bumped to0.56.0.CLI module (
services/cli.py) aligned stylistically with sibling packages: added-> Nonereturn annotations, periods to docstrings, removed dead commented code.dependenciesinpyproject.tomlsorted alphabetically (case-insensitive).
Fixed#
Duplicate log output when
ExcelConfiguratorwas instantiated in a session that already had a root logger configured (logger.propagate = Falseand handler-deduplication guard added).
0.55.0 (2026-04-01)#
Added#
``load_config_env()`` helper that loads
Config/.envinto the process environment, eliminating the need to manuallyset KNPC_API_KEY_KAXANUK=…in the terminal before every runConfig/.envtemplate generated automatically byinit excelwith a placeholder for the license keypython-dotenvdependency for.envfile loadingload_config_envexported at the top-level package namespace (from kaxanuk.backtest_engine import load_config_env)
Changed#
Template
__main__.pynow callsload_config_env()before any license-validated codeLicense error message updated to recommend
Config/.envas the primary configuration methodREADME examples updated to include
load_config_env()call
0.54.0 (2026-03-31)#
Added#
Runtime license validation (phone-home) to protect against unauthorized use
license_validatorservice with device fingerprinting, local cache (24h TTL), and 7-day offline grace periodLicense validation at all entry points:
__main__.py,main(), andPyArrowBacktester.run()Custom exception hierarchy:
LicenseError,LicenseNotFoundError,LicenseValidationError,LicenseServerErrorHMAC-signed local cache file (
~/.kaxanuk_cache) to prevent tamperingIn-process validation flag to avoid redundant server calls within the same session
httpxdependency for license server communication
Changed#
.gitignoreupdated to exclude.kaxanuk_licenseand.kaxanuk_cachefiles
0.52.0 (2026-03-04)#
Added#
Batch backtesting capability for running multiple portfolios in a single execution
BatchRunnerorchestrator withSharedDataPoolfor efficient market data reuse across portfoliosBatchConfigParserfor dict/YAML-based batch configurationDirectory scanning mode to auto-discover portfolio files
Comparative Excel report ranking portfolios by configurable metric
Individual Excel reports per portfolio with:
Full performance metrics
Drawdown analysis
Annual returns breakdown
Benchmark statistics computation in batch processing
Alpha calculation in batch path
Changed#
PyArrow Decimal-to-float coercion at numpy math operation boundaries for compatibility
0.51.0 (2026-02-18)#
Added#
BacktestSuiteclass withadd_variation()method to define configuration overrides per variation“auto” date derivation from portfolio rebalancing dates
Comparative Excel reports with:
Summary metrics across all variations
Cumulative returns comparison
Drawdown comparison charts
Fixed#
Alpha metric calculation bug
CAGR (Compound Annual Growth Rate) metric calculation bug
0.50.0 (2026-01-16)#
Added#
New PyArrow-based backtesting engine (backtest_2) with component-oriented design:
Explicit PortfolioStateManager, ExecutionBroker, and ReportingEngine components
Pluggable commission and slippage models via interfaces
Immutable BacktestReport dataclass as structured result container
Clear separation between configuration (inputs) and runtime state
Ability to run multiple backtest cases (different parameters) with only one data pipeline
Fixed#
Summary card alpha now uses the same calculation as annual returns table, ensuring consistent alpha display across dashboards
0.49.0 (2025-11-25)#
Added#
StandardFieldenum for type-safe field names (VWAP, ADJUSTED_VWAP, ADJUSTED_CLOSE, DATE)Long-short portfolio support with
allow_shortparameter in PortfolioEntityPortfolioEntity.from_dict()class method for creating portfolios from dictionaries
Changed#
Portfolio validation now supports both long-only and long-short strategies
README documentation updated
Removed#
Unnecessary configuration entity fields
0.48.0 (2025-10-30)#
Added#
Annual returns table to Excel report
Annual returns analysis to dashboard
Alpha metric to annual returns table (both dashboard and Excel report)
Fixed#
Performance metrics formatting
Dashboard alpha metric format display
0.47.0 (2025-10-15)#
Added#
Helper functions module (
input_handlers_helpers) for common data processing operationsInteractive dropdown menu in portfolio weights evolution chart to filter tickers
Comprehensive docstrings to almost all codes
Changed#
ExcelPortfolioInputHandler now returns
pa.Tableinstead ofpd.DataFrameDashboard pie chart now displays Top 10 assets alphabetically with “Others” category for remaining positions
Benchmark builder now uses
ADJ_CLOSE_COLUMN_NAMEconstant instead of hardcoded stringsExcel portfolio validates first column must be ‘Ticker’
0.46.0 (2025-10-06)#
Added#
MissingBenchmarkexception and benchmark validation before processingBenchmark availability validation (
_validate_benchmark_availability())
Changed#
Backtest engine optimized (converted class parameters to Python float for better performance)
Portfolio transformer now includes all ticker weights (not just >0)
Increased decimal precision for financial calculations
Fixed#
Portfolio calculation bugs
_convert_df_to_python()now properly handles None/NaN values (converts to 0.0)
0.45.0 (2025-10-02)#
Added#
Execution price selection option (customizable execution price for backtesting)
safe_decimal()function for PyArrow Decimal conversions_convert_df_to_python()method for converting PyArrow scalars to Python values
Changed#
Migrated data handling from Pandas to PyArrow
Build system changed from
pdm-backendtohatchling
Fixed#
Input handler and Entities bugs
Removed#
Unnecessary project directories and files
0.44.0 (2025-08-27)#
Added#
Project templates for easier setup (
__main__.pytemplate for CLI init).gitkeepfiles for empty directories
Changed#
Rebalancing logic improvements
CLI interface updates and improvements
pdm.locknow excluded from version control
Fixed#
CLI bugs
0.43.0 (2025-08-12)#
Added#
Benchmark name displayed in plot legends
Sortino ratio calculation with robust downside deviation methodology
Changed#
Dashboard color scheme updated to company brand colors
Interactive pie chart now updates based on selected date
Fixed#
Functions for CVaR and VaR calculations with robust historical and parametric Gaussian methods (including Cornish-Fisher modification) were fixed
0.42.0 (2025-07-29)#
Added#
Broker interfaces implementation
Config factory as alternative to Excel configuration
PyArrow-based portfolio entity
Custom exceptions for better error handling
Mixed date format support
New ‘portfolio’ Excel report sheet added
0.41.0 (2025-06-17)#
Added#
Portfolio weights evolution plot
Custom market data column names support
Changed#
Market data builder updated to support custom column names
Fixed#
Annualized return calculation
CAGR calculation
Alpha metric calculation
0.40.1 (2025-06-04)#
Fixed#
OS Error on cli
init scriptbecause of entry script template missing from wheel data
0.40.0 (2025-06-04)#
Changed#
First public release, now on PyPI