feat(portfolio): value-history tracking, returns analysis, and portfolio statistics - #114
Merged
Merged
Conversation
…rtfolio statistics Close a seed-parity gap in the portfolio engine. Portfolio now tracks a portfolio_values history (seeded with initial cash) and exposes: - record_value(prices): append a per-step valuation to the history - calculate_returns(lookback): daily/cumulative/annualized returns, Sharpe ratio (rf=2%), and max drawdown - calculate_portfolio_statistics(prices): per-position shares/price/value/ allocation plus a Herfindahl-Hirschman concentration index (raw and normalized) and the number of assets held HHI is computed on renormalized non-cash weights so the index stays in [0, 1] regardless of the cash position (the seed's raw-fraction form can go negative in cash-heavy portfolios). Adds tests for the new methods and for the alloc.__main__ entry point.
This was referenced Aug 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes a parity gap in the portfolio engine.
Portfolionow tracks aportfolio_valueshistory (seeded with initial cash) and exposes two newcapabilities that were previously computed ad-hoc (or not at all) in
core.py:record_value(prices)— append a per-step valuation to the history.calculate_returns(lookback=None)— daily / cumulative / annualizedreturns, Sharpe ratio (risk-free 2%), and max drawdown.
calculate_portfolio_statistics(prices)— per-positionshares/price/value/allocation plus a Herfindahl-Hirschman concentration
index (raw + normalized) and the number of assets held.
HHI normalization
HHI is computed on renormalized non-cash weights so the index stays in
[0, 1]regardless of the cash position. The raw-fraction form (squaringallocation fractions that sum to < 1 when cash is held) can produce a
normalized HHI below zero in cash-heavy portfolios; renormalizing the
non-cash weights to sum to 1 keeps the index well-defined.
Tests
TestValueHistory,TestCalculateReturns,TestPortfolioStatisticsclasses in
tests/test_portfolio.pycovering seeding, recording,cumulative/daily returns, max drawdown, lookback windowing, Sharpe sign,
per-position reporting, and HHI for single/equal/cash-heavy portfolios.
TestMainEntryPointclass covering thealloc.__main__entry point(delegation identity + exit-code propagation).
Full suite: 571 passed (up from 556).
ruff check alloc/andmypy alloc/ --ignore-missing-importsboth clean.Follow-ups
record_value()intoSimulationRunnerand retire the ad-hocSharpe/ROI in
core.py(issue TICKET-045: Wire Portfolio value-history into SimulationRunner; retire ad-hoc Sharpe/ROI #111).