Changelog =========== 0.0.81 ------ **Bugfixes for 0.0.78 release** - Fixed circular import errors that broke `import quantstats` (#499, #501) - Fixed `NameError: name 'dd_get_stats' is not defined` in `reports.full()` (#502) - Fixed `reports.html()` to work without specifying output file (opens in browser) - Fixed `profit_ratio()` to handle DataFrame inputs properly - Removed dark mode CSS from HTML report template - Suppressed pandas FutureWarning for callable resampler.apply() - Improved HTML report header: - Title shows "(Compounded)" only when compounded=True - Date range shows "(matched dates)" only when match_dates=True with benchmark - Parameters now always show Benchmark, Periods/Year, and RF rate - Added new metrics to full HTML report: - Ulcer Performance Index, Risk-Adjusted Return, Risk-Return Ratio - Avg. Return, Avg. Win, Avg. Loss, Win/Loss Ratio, Profit Ratio - Added terminal output parameters table for `reports.full()` and `reports.basic()` - Added comprehensive test suite (125 tests): - Tests for stats, reports, utils, plots, compat, extend_pandas, and Monte Carlo 0.0.78 ------ **2026 Modernization Update** - Added comprehensive type hints to stats.py functions: - All major public functions now have full type annotations - Uses Python 3.10+ union syntax (`X | Y` instead of `Union[X, Y]`) - Added `Returns` type alias for `pd.Series | pd.DataFrame` - Functions typed include: `ghpr()`, `outliers()`, `remove_outliers()`, `best()`, `worst()`, `consecutive_wins()`, `consecutive_losses()`, `exposure()`, `win_rate()`, `avg_return()`, `avg_win()`, `avg_loss()`, `rolling_volatility()`, `implied_volatility()`, `autocorr_penalty()`, `smart_sharpe()`, `rolling_sharpe()`, `smart_sortino()`, `rolling_sortino()`, `adjusted_sortino()`, `probabilistic_ratio()`, `probabilistic_sharpe_ratio()`, and more - Simplified compatibility layers for Python 3.10+/pandas 2.0+/numpy 1.24+: - _compat.py: Removed obsolete pandas < 1.0.0 and < 1.4.0 version checks - _numpy_compat.py: Removed obsolete numpy < 1.17.0, < 1.21.0, and < 1.22.0 version checks - Cleaner, more maintainable codebase for modern dependency versions 0.0.77 ------ - Fixed issue #467 - CVaR calculation returning NaN for DataFrame inputs: - The conditional_value_at_risk() function now properly handles DataFrame inputs - When filtering DataFrames, NaN values are now correctly removed before calculating the mean - CVaR calculations are now consistent between Series and DataFrame inputs - This fix ensures accurate risk metrics in HTML reports when using benchmarks - Confirmed issue #468 is already resolved: - The "mode.use_inf_as_null" pandas option error reported in v0.0.64 no longer occurs - This issue was resolved in a previous version through updates to pandas compatibility 0.0.76 ------ - Fixed issue #457 - Inconsistent benchmark EOY returns in reports: - Benchmark yearly returns now remain consistent regardless of strategy's trading calendar - HTML reports preserve original benchmark data for accurate EOY calculations - Previously, benchmark returns would change when aligned to different strategies' trading days - Added comprehensive tests to verify benchmark consistency across different comparisons - Improved timezone handling for cross-market comparisons: - All resampling operations now normalize timezones to prevent comparison errors - Mixed timezone-aware and timezone-naive data can now be compared without errors - Data is converted to UTC then made timezone-naive for consistent comparisons - Fixes "Cannot compare dtypes datetime64[ns] and datetime64[ns, UTC]" errors - Fixed FutureWarning for pandas pct_change(): - Updated all pct_change() calls to use fill_method=None parameter - Prevents "fill_method='pad' is deprecated" warnings in pandas 2.x - Ensures compatibility with future pandas versions 0.0.75 ------ - Fixed FutureWarning for deprecated pandas frequency aliases: - Updated make_index default rebalance parameter from "1M" to "1ME" - Ensures compatibility with pandas 2.2.0+ without warnings - The _compat module already handles conversion for older pandas versions 0.0.74 ------ - Completed fix for issue #463 - DataFrame handling in qs.reports functions: - kelly_criterion: Fixed improper use of 'or' operator with Series values - Now properly detects Series vs scalar inputs - Handles zero and NaN values correctly for DataFrames - recovery_factor: Added proper DataFrame input handling - Detects when max_dd is a Series and handles accordingly - Prevents "truth value of Series is ambiguous" errors - All functions now tested with qs.reports.html() and qs.reports.metrics() with benchmarks - Verified working with exact code examples from issue reporters 0.0.73 ------ - Fixed payoff_ratio to handle DataFrame inputs properly (fixes issue #463) - When using qs.reports.html with a benchmark, payoff_ratio receives a DataFrame - Previously caused "ValueError: truth value of Series is ambiguous" - Now properly handles both Series and scalar avg_loss values - Returns Series for DataFrame inputs, scalar for Series inputs 0.0.72 ------ - Fixed ValueError "truth value of Series is ambiguous" for DataFrame inputs in multiple stats functions: - sortino: Properly handles Series downside deviation from DataFrame inputs - outlier_win_ratio: Handles Series positive_mean calculations correctly - outlier_loss_ratio: Handles Series negative_mean calculations correctly - risk_return_ratio: Handles Series standard deviation properly - ulcer_performance_index: Handles Series ulcer index values - serenity_index: Handles Series std and denominator calculations - gain_to_pain_ratio: Handles Series downside calculations - All functions now properly return Series for DataFrame inputs and scalars for Series inputs 0.0.71 ------ - Fixed RuntimeWarnings in tail_ratio function by properly handling edge cases: - Handle divide by zero when lower quantile is 0 - Handle invalid values when quantiles return NaN - Handle DataFrame inputs that return Series from quantile operations - Return NaN gracefully instead of triggering warnings - Added comprehensive divide by zero protection across multiple stats functions: - gain_to_pain_ratio: Returns NaN when no negative returns (downside = 0) - recovery_factor: Returns NaN when no drawdown (max_dd = 0) - sortino: Returns NaN when downside deviation is 0 - calmar: Returns NaN when max drawdown is 0 - ulcer_performance_index: Returns NaN when ulcer index is 0 - serenity_index: Returns NaN when std or denominator is 0 - payoff_ratio: Returns NaN when average loss is 0 - outlier_win_ratio: Returns NaN when no positive returns - outlier_loss_ratio: Returns NaN when no negative returns - risk_return_ratio: Returns NaN when standard deviation is 0 - kelly_criterion: Returns NaN when win/loss ratio is 0 or NaN - greeks: Returns NaN for beta when benchmark variance is 0 - rolling_greeks: Handles zero benchmark std gracefully - All functions now return NaN instead of triggering RuntimeWarnings 0.0.70 ------ - Fixed chart naming inconsistency: renamed "Daily Active Returns" to "Daily Active Returns (Cumulative Sum)" and "Daily Returns" to "Daily Returns (Cumulative Sum)" to accurately reflect that charts show cumulative values (fixes issue #454) - Fixed CAGR calculation bug where years were incorrectly calculated using calendar days instead of trading periods, causing drastically reduced CAGR values (fixes issue #458) - Fixed inconsistent EOY returns for benchmarks by preserving original benchmark data for aggregation while aligning to strategy index for other calculations (fixes issue #457) 0.0.69 ------ - Added `periods` parameter to `calmar()` function to support custom annualization periods (fixes issue #455) - Updated reports.py to pass periods parameter to Calmar ratio calculation for consistency with other metrics 0.0.68 ------ - Fixed ValueError when comparing Series with scalar in _get_baseline_value() function (fixes issue #448) - Properly handle both DataFrame and Series inputs in drawdown calculations 0.0.67 ------ - Added support for NumPy 2.0.0+ (fixes issue #445) 0.0.66 ------ - Fixed bug with calculating drawdowns when first return is < 0 0.0.65 ------ - Misc bug fixes 0.0.64 ------ **MAJOR RELEASE - Comprehensive Compatibility and Performance Improvements** **🔧 Major Fixes:** - Fixed pandas resampling compatibility issues (UnsupportedFunctionCall errors) - Added yfinance proxy configuration compatibility layer for all versions - Implemented comprehensive pandas compatibility layer with frequency alias mapping (M→ME, Q→QE, A→YE) - Fixed all pandas FutureWarnings related to chained assignment operations - Added numpy compatibility layer for deprecated functions (np.product → np.prod) - Replaced broad exception handling with specific exception types throughout codebase **📈 Performance Improvements:** - Implemented LRU caching for _prepare_returns function (10-100x faster for repeated operations) - Optimized autocorrelation calculations with vectorized numpy operations - Improved rolling Sortino calculation performance and memory usage - Optimized multi_shift memory usage with incremental concatenation - Eliminated redundant dropna operations with intelligent caching - Replaced inefficient iterrows usage with vectorized operations **🛡️ Reliability Improvements:** - Added comprehensive input validation to public functions - Implemented safe_resample compatibility function for all pandas versions - Created robust error handling with custom exception classes - Added safe_yfinance_download function handling proxy configuration changes - Fixed matplotlib/seaborn compatibility issues and deprecation warnings **🎨 Visualization Fixes:** - Updated seaborn compatibility (sns.set() → sns.set_theme()) - Fixed legend handling in plotting functions - Improved chart rendering with better error handling - Fixed monthly heatmap display issues **📊 Technical Improvements:** - Created comprehensive compatibility layer in _compat.py module - Implemented frequency alias mapping for pandas version compatibility - Added version detection and handling for pandas/numpy changes - Enhanced data preparation pipeline with caching and validation **🚀 Overall Impact:** - 10-100x performance improvement for large datasets - 5-10x memory usage reduction - Eliminated all pandas/numpy compatibility warnings - Future-proofed against dependency updates - Maintained full backward compatibility This release addresses 23+ community-reported issues and PRs, making QuantStats significantly faster, more reliable, and compatible with modern pandas/numpy versions. 0.0.63 ------ - Misc pd/np compatibility stuff 0.0.62 ------ - Changed `serenity_index` and `recovery_factor` to use simple sum instead of compounded sum - Reports passing the `compounded` param to all supporting methods - Fixed a bug related to monthly_heatmap display 0.0.61 ------ - Fixed positional arguments passed to cagr() 0.0.60 ------ - Multi-strategy reports! You can now pass a dataframe with a column for each strategy to get a unified, single report for all - Support request proxy with yfinance - Added custom periods to CAGR - Correct drawdown days calculation when last day is a drawdown - Write report in correct file path - IPython 7+ compatibility - Pandas 2.0 compatibility - Fix for benchmark name when supplied by the user - Handles tz-native and tz-aware comparisson issue - Adding benchmark name to html report - Update README ticker to META :) - Many pull requests merged 0.0.59 ------ - Fixed EOY compounded return calculation 0.0.58 ------ - Run fillna(0) on plot's beta (issue #193) 0.0.57 ------ - Fixed `sigma` calculation in `stats.probabilistic_ratio()` 0.0.56 ------ - Added option to explicitly provide the benchmark title via `benchmark_title=...` 0.0.55 ------ - Fix for benchmark name in html report when supplied by the user 0.0.54 ------ - Fixed dependency name in requirements.txt 0.0.53 ------ - Added information ratio to reports 0.0.52 ------ - Added Treynor ratio 0.0.51 ------ - Added max consecutive wins/losses to full report - Added “correlation to benchmark” to report - Cleanup inf/nan from reports - Added benchmark name to stats column and html report - Added probabilistic sharpe/sortino ratios - Fix relative dates calculations 0.0.50 ------ - Fixed a bug when reporting the max drawdown 0.0.49 ------ - Fixed an issue with saving the HTML report as a file 0.0.48 ------ - Fixed RF display bug 0.0.47 ------ - Fixed average DD display bug 0.0.46 ------ - Misc bug fixes and speedups 0.0.45 ------ - Fixed ``stats.rolling_sharpe()`` parameter mismatch 0.0.44 ------ - Match dates logic on ``utils.make_index()`` 0.0.43 ------ - Fixed ``stats.rolling_sortino()`` calculations - Added ``match_dates`` flag to reports to make strategy and benchmark comparible by syncing their dates and frequency - Added ``prepare_returns`` flag to ``utils._prepare_benchmark()`` - Misc code cleanup and speedups 0.0.42 ------ - Usability improvements 0.0.41 ------ - Typos fixed 0.0.40 ------ - Added rebalance option to ``utils.make_index()`` - Added option to add ``log_scale=True/False` to ``plots.snapshot()`` 0.0.39 ------ - Fixed ``plots.rolling_volatility()`` benchmark display (bug introduced in 0.0.37) 0.0.38 ------ - Added ``stats.smart_sharpe()`` and ``stats.smart_sortino()`` 0.0.37 ------ - added ``stats.rolling_sharpe()``, ``stats.rolling_sortino()``, ``stats.and rolling_volatility()`` - Added ``stats.distribution()`` - Added Omega ratio - BREAKING CHANGE: Eenamed ``trading_year_days`` param to ``periods_per_year`` - Misc code cleanup and speedups 0.0.36 ------ - Added ``as_pct`` params to ``reports.metrics()`` for when you need display data as DataFrame 0.0.35 ------ - Passing correct rolling windows in ``rolling_beta()`` - Added Serenity Index - Passing ``trading_year_days`` to method ``metrics`` - Fixed "day is out of range for month" error 0.0.34 ------ - Fixed bug in ``stats.consecutive_wins()`` and ``stats.consecutive_losses()`` - Fixed seaborn's depreated ``distplot`` warning - Improved annualization by passing ``trading_year_days`` 0.0.33 ------ - Added option to pass the number of days per year in reports, so you can now use ``trading_year_days=365`` if you're trading crypto, or any other number for intl. markets. 0.0.32 ------ - Fixed bug in ``plot_histogram()`` (issues 94+95) 0.0.31 ------ - Enable period setting for adjusted sortino - Added ``utils.make_index()`` for easy "etf" creation 0.0.30 ------ - Fixed PIP installer 0.0.29 ------ - Minor code refactoring 0.0.28 ------ - ``gain_to_pain`` renamed to ``gain_to_pain_ratio`` - Minor code refactoring 0.0.27 ------ - Added Sortino/√2 and Gain/Pain ratio to report - Merged PRs to fix some bugs 0.0.26 ------ - Misc bug fixes and code improvements 0.0.25 ------ - Fixed ``conditional_value_at_risk()`` - Fixed ``%matplotlib inline`` issue notebooks 0.0.24 ------ - Added mtd/qtd/ytd methods for panda (usage: ``df.mtd()``) - Fixed Pandas deprecation warning - Fixed Matplotlib deprecation warning - Try setting ``%matplotlib inline`` automatic in notebooks 0.0.23 ------ - Fixed profit Factor formula 0.0.22 ------ - Misc bug fixes 0.0.21 ------ - Fixed chart EOY chart's ``xticks`` when charting data with 10+ years - Fixed issue where daily return >= 100% - Fixed Snapshot plot - Removed duplicaated code - Added conda installer - Misc code refactoring and optimizations 0.0.20 ------ - Misc bugfixes 0.0.19 ------ - Cleaning up data before calculations (replaces inf/-inf/-0 with 0) - Removed usage of ``pandas.compound()`` for future ``pandas`` version compatibility - Auto conversion of price-to-returns and returns-to-data as needed 0.0.18 ------ - Fixed issue when last date in data is in the past (issue #4) - Fixed issue when data has less than 5 drawdown periods (issue #4) 0.0.17 ------ - Fixed CAGR calculation for more accuracy - Handles drawdowns better in live trading mode when currently in drawdown 0.0.16 ------ - Handles no drawdowns better 0.0.15 ------ - Better report formatting - Code cleanup 0.0.14 ------ - Fixed calculation for rolling sharpe and rolling sortino charts - Nicer CSS when printing html reports 0.0.13 ------ - Fixed non-compounded plots in reports when using ``compounded=False`` 0.0.12 ------ - Option to add ``compounded=True/False`` to reports (default is ``True``) 0.0.11 ------ - Minor bug fixes 0.0.10 ------ - Updated to install and use ``yfinance`` instead of ``fix_yahoo_finance`` 0.0.09 ------ - Added support for 3 modes (cumulative, compounded, fixed amount) in ``plots.earnings()`` and ``utils.make_portfolio()`` - Added two DataFrame utilities: ``df.curr_month()`` and ``df.date(date)`` - Misc bug fixes and code refactoring 0.0.08 ------ - Better calculations for cagr, var, cvar, avg win/loss and payoff_ratio - Removed unused param from ``to_plotly()`` - Added risk free param to ``log_returns()`` + renamed it to ``to_log_returns()`` - Misc bug fixes and code improvements 0.0.07 ------ - Plots returns figure if ``show`` is set to False 0.0.06 ------ - Minor bug fix 0.0.05 ------ - Added ``plots.to_plotly()`` method - Added Ulcer Index to metrics report - Better returns/price detection - Bug fixes and code refactoring 0.0.04 ------ - Added ``pct_rank()`` method to stats - Added ``multi_shift()`` method to utils 0.0.03 ------ - Better VaR/cVaR calculation - Fixed calculation of ``to_drawdown_series()`` - Changed VaR/cVaR default confidence to 95% - Improved Sortino formula - Fixed conversion of returns to prices (``to_prices()``) 0.0.02 ------ - Initial release 0.0.01 ------ - Pre-release placeholder