v1.1.0 — Portfolio becomes real
[1.1.0] - 2026-07-05
The "portfolio becomes real" release. v1.0 hardened the research half of the
north star (never show fabricated market data as live); 1.1 turns that same
integrity lens on the portfolio half — a real cash/transaction spine, honest
realized-vs-unrealized P&L, and the retirement of the old global, shared-across-
users portfolio (a privacy contradiction) in favour of a per-user one.
Added
- Portfolio cash ledger (v1.1 "portfolio becomes real", spine) — cash is now
derived from the transaction ledger as the single source of truth: a buy debits
cash, a sell/dividend/deposit credits it, a withdrawal debits it, and fees always
cost cash. Newdeposit/withdrawaltransaction types (cash-only, no symbol).
GET /api/portfolios,/api/portfolios/{id}, and/api/portfolios/{id}/analytics
now reportcash_balanceandnet_liquidation_value(holdings + cash). - Portfolio transaction UI (v1.1) — the Portfolio Manager can now record
buy/sell/dividend/deposit/withdrawal transactions (the endpoints existed but no
UI ever called them), with a live cash-impact preview and a trade-history table.
New Net Liquidation and Cash metric cards surface the ledger balance. - Upcoming events in the Portfolio Manager (v1.1) — dividends, earnings and
corporate actions for your holdings now show in the Manager's events calendar,
not only on the legacy view / dedicated Dividends page. - Deep analytics on the per-user portfolio (v1.1, consolidation) — the
Portfolio Manager now carries everything the old view had: correlation matrix,
benchmark-overlay equity curve, the full risk-metric set (Sharpe, Sortino, beta,
alpha, information ratio, max drawdown), an upcoming-dividend tracker, and
Brinson + factor attribution — all scoped to the selected portfolio via new
owner-checkedGET /api/portfolios/{id}/analytics/*and/attributionroutes
(with aprimaryalias for dashboards). - AI Risk Assessment + backtesting in the Manager (v1.1) — the local-LLM risk
narrative (on-demand) and the backtester (seeded from the portfolio's holdings)
now live in the Manager. - Sell from a holding row (v1.1) — each holding has a "Sell" button that
pre-fills the transaction form (sell / that symbol / full size / current price)
so a sale is attributed to the position instead of typed from scratch. - Holdings CSV export in the Manager (it already had CSV import).
Changed
- The equity portfolio is now per-user, full stop (v1.1, consolidation) — the
Portfolio Manager (/api/portfolios) is the only portfolio; the legacy
manager|legacy view toggle is gone and every surface that read a portfolio
(home, cockpit, HUD, launchpad, correlation dashboard, risk / stress / factor /
dividends / reports) now reads the caller's own primary portfolio via
GET /api/portfolios/primary.
Removed
- The global, user-less legacy portfolio (v1.1, consolidation) — the shared
Holdingtable and its/api/portfolio,/api/portfolio/analytics/*,
/api/portfolio/holdings*and/api/portfolio/{id}/attributionendpoints are
deleted. On a shared instance every user saw and edited the same holdings — a
contradiction of the "private terminal" thesis; portfolios are per-user now.
(The global/watchlists/itemsfeed is unaffected.) - Tax-lot accounting (the
TaxLotmodel,/api/portfolio/tax-lots*endpoints
and the Tax Lot Manager UI) — a jurisdiction-specific rabbit hole where a wrong
number is worse than none; deliberately shelved.
Fixed
- Import from Legacy / bulk add crashed with a 500 (v1.1) — adding a holding
auto-generated itslot_idfrom a second-resolution timestamp, so adding the
same symbol more than once within a second (as the legacy import does) collided
on the(portfolio_id, symbol, lot_id)unique constraint. Auto lot_ids now
carry a random suffix, and a genuine duplicatelot_idreturns a clean409
instead of an unhandled500. - Realized P&L was proceeds, not gains (v1.1) — analytics summed
shares * sell_price - fees, overstating realized P&L by the entire cost basis.
Now computed by replaying the ledger chronologically (running average cost per
symbol):shares_sold * (sell_price - avg_cost) - fees, dividends excluded
(they remain individend_income_ytd). New purebackend/services/portfolio_pnl.py.
Annualized return now uses net liquidation (holdings + cash) as current equity.
The "Total P&L" card is relabelled "Unrealized P&L" to match what it shows. - Multi-portfolio analytics annualized-return crashed on portfolios whose
transactions carried bareYYYY-MM-DDdates (naive vs. tz-aware datetime
subtraction); inception dates are now normalised to UTC. - Multi-portfolio analytics used India defaults for risk metrics (risk-free
0.06,
benchmarkNIFTY50); now0.04/S&P500in line with the de-India defaults.