Conversation
…ase docs - Add `push` trigger to `.github/workflows/release.yml` for the `dev` branch. - Restrict `mkdocs deploy` to the `main` branch and `release` events, preventing pre-release documentation from overwriting the live documentation site. - Implement conditional tags in `docker/metadata-action`: tag builds on `dev` as `nightly`, while keeping `latest` reserved for `main`. - Isolate the Playwright screenshots cache for the `dev` branch as `screenshots-dev-`, allowing fast incremental builds on development pushes. - Keep manual screenshot regeneration capability via `workflow_dispatch` inputs. - Only archive PNG screenshot files (`**/*.png`) in `release.yml` to prevent outdated markdown files from entering the upload package. - Add new `release-pipeline.md` reference manual under `developer/docs/` with a detailed Mermaid flowchart explaining the CI/CD pipeline. - Lower custom screenshot carousel z-indexes in `home-custom.css` below header defaults to prevent language dropdown overlap. - Add `--force` flag to the `mkdocs gh-deploy` wrapper in `dev.py` to prevent push rejections.
…cons - Add structured GitHub Issue Templates (.github/ISSUE_TEMPLATE/) for bug reports, feature requests, UX ideas, and plugin requests. - Update localized contribution guides (contribute.*.md) to link directly to the new issue templates. - Add localized "Request New Plugin" card-links using Lucide puzzle piece SVG to import, assets, and FX provider lists. - Fix relative image path traversals for CSS Scraper and Scheduled Investment icons in both list cards and detail page headers across all languages. - Ensure cards relative link (../../../community/contribute/) resolves correctly without 404.
…est/docs updates - Fix MWRR double-counting: initial_nav now derived from nav_snapshots[0].nav (aligned with history) - Add mwrr_cumulative + mwrr_annualized metrics across summary and history - GrowthChart % mode now uses mwrr_cumulative (aligned with TWRR/ROI) - BREAKING: removed legacy mwrr_percent (Summary) and mwrr (HistoryPoint) - Remove transaction query limit (was 100) - Scheduler: UTC storage, TZ-aware defaults, frontend selector, modal locked behind edit mode - OpenDateRangeModel: add "min"/"max" sentinels + MAX preset in DateRangePicker - DistributionEditor: auto-fill remaining weight to 100% - Countries endpoint: include_other param - i18n: Liquidity label + allocation chart icon - Allocation & Growth charts: tooltip helpers, safeKey fix, appendToBody, UI/UX improvements - E2E gallery: mock dashboard report API, dynamic date shifting, extended screenshots (desktop/mobile, all tabs/modes) - Docs: fix LaTeX rendering, clean headings, define MWRR/TWRR concepts, verify examples (CAGR, CF sign, exact values)
- Convert GitHub-style alerts (> [!TIP]/[!NOTE]) to standard MkDocs admonitions (!!! note/tip) in timing-effect, mwrr, and twrr docs. - Add required blank line inside admonition blocks to prevent Prettier failures. - Apply precision improvements to Timing Effect descriptions across all 4 languages (EN, IT, ES, FR) based on finance terminology review (clarifying investor gap, simple ROI in portfolio context, and tax/fee handling).
Backend: - Fix MWRR double-counting: use nav_snapshots[0].nav, not total_invested - Add mwrr_annualized/mwrr_cumulative (remove mwrr_percent/mwrr) - Summary metrics now respect date_from (period-rebased ROI/TWRR/MWRR) - Add period P&L breakdown: unrealized_delta, realized_gain_loss (WAC), income (DIVIDEND+INTEREST), fees_taxes (FEE+TAX), other_result - Fix period_nav_start=0 when date_from before first event - Fix realized G/L: exclude SELL from WAC computation (excluded_tx_ids) - Force ROI/TWRR/MWRR first point to 0% unconditionally - Add annualized_to_cumulative() helper in roi_utils Frontend: - 3 specialized KPI cards: Net Worth (bars+markers), P&L (breakdown bars), Returns (timing effect hero + metric bars) - New KpiMetricBar.svelte component with tooltip and triangle marker - GrowthChart: all labels reactive to locale, tooltipPositionSide - All charts migrated from tooltipPositionAboveFinger to Side - DateRangePicker MAX preset translated (All/Tutti/Tout/Todo) - Resolve min/max sentinels in asset/FX detail (fix 422 errors) - Currency formatting via formatCurrencyAmountPlain BREAKING CHANGE: removed mwrr_percent (PortfolioSummary), mwrr (PortfolioHistoryPoint/AssetHistoryPoint). Use mwrr_annualized_percent / mwrr_annualized + mwrr_cumulative_percent / mwrr_cumulative.
BREAKING CHANGE: PortfolioSummary adds total_deposited, total_withdrawn, net_deposited_capital, period_market_value_start, period_fees, period_taxes, net_invested on PortfolioHistoryPoint. Removed fields: none. All additive. MWRR series: - Fix warm-start contamination: guard extreme rates, retry cold-start - Fix initial_nav=0 degeneracy when date_from before portfolio start - Fix CF exclusion on period start date (strict > vs >=) - Add reliability fallback: compare series[-1] vs summary, null-out if divergent, emit MWRR_SERIES_UNRELIABLE DataQuality issue - ROI first point no longer jumps to 6% on deposit day Period P&L: - get_summary() now accepts date_to — income, fees, realized, net_deposited_capital all respect both boundaries - period_net_flows also filtered by date_to - MWRR end_date uses date_to (not always today) Card 1 (Net Worth): - Replace NAV bar with Market Value + start marker - Remove Unrealized G/L row (overlaps P&L card) - Add Net Deposited Capital with diverging bar - Add period scope note at bottom GrowthChart EUR: - Add net_invested field (cumulative deposits - withdrawals) - Tooltip shows P&L = NAV - net_invested - Stack order: book value → cash → in-transit → NAV line Other: - Directa plugin: fix Rit.cedola classified as INTEREST (→ TAX) - Manual assets (no provider): suppress MISSING_PRICE banner - Fees/taxes tooltip: split with emoji + right-aligned HTML table - KpiMetricBar/KpiDivergingFlowBar: add tooltipHtml prop
BrokerInfo missing default_import_plugin: plugin-only brokers showed
dot only; added to type + brokerMap. referrerpolicy="no-referrer" on
all favicon imgs.
Promote false positive: cashAmountsCancel() (exact sum=0) was only in
selectedForPromote — root cause was localSuggestions + bannerSuggestions;
now guarded in all three.
BulkModal: enablePagination=true + alwaysShowPagination + [5,10,25,50]
page sizes (was enablePagination=false).
LIQUIDITY i18n key uppercase; AllocationPieChart type-mode now resolves
$t("asset.types."+name.toUpperCase()) instead of showing raw name.
AssetModal resetForm(): currency ← userSettings.base_currency (was "USD").
AssetModal saveCreate(): full-history sync start=1975-01-01 after provider.
SectorSearchSelect: getSectorEmoji() in label (DistributionEditor was
wrong target). ImportWizard: checkAndPromptIdentifier on oncreated.
Also: DataTable getRowHref + onauxclick middle-click (F),
Tooltip mobile min(maxWidth, 100vw-20px) (I), responsive
thresholds +100px after YTD/ALL (L), KPI tooltips + overlay
icon fallback in DataTableColumnFilter/dashboard (J/A2-A3).
…hart GrowthChart ABS mode restructured around the narrative: P&L = NAV − Deposited Capital - Two-pool daily-stateful cash decomposition in portfolio engine (returns consumed first on BUY, principal returned on SELL) - New stacked areas: Asset Cost / Returns / Capital - Capital Baseline dashed overlay line - Tooltip shows Total P&L with formula hint - 5 new fields in PortfolioHistoryPoint DTO (non-breaking addition) - 9 unit tests covering examples A-F + edge cases The stateless formula was algebraically unable to distinguish deposit residuals from returns when book_asset_like > baseline. Delta-based two-pool model tracks provenance at cost-basis level without euro-per-euro ledger or DB persistence.
Dashboard user guide: - Rewrite user/dashboard/index.en.md as overview - Add kpi-cards.en.md (Net Worth, Period P&L, Returns cards) - Add charts.en.md (Growth Chart ABS/%, Allocation Panel) Financial theory: - Add deposited-capital.en.md with delta-based cash decomposition algorithm, 6 worked examples A–F, and limitations - Extend period-pnl.en.md with Total P&L / Period P&L relationship - Add "Deposited Capital & Total P&L" to performance-metrics index BRIM documentation: - Rewrite generic_csv.md: sign conventions table, per-type guidance, P2P patterns, storno/reversal strategies, LLM tip with prompt - Rewrite architecture.md: full 6-step wizard, plugin contract - providers_list.md: favicon icons, links to user import pages User import pages (generic-csv ×4 languages): - Add column reference table with accepted aliases from HEADER_MAPPINGS - Add info banner linking to technical spec
…n chain - AssetModal: internal ConfirmModals use zIndex+20 instead of hardcoded 70/80; fixes cancel being blocked when opened from ImportWizardModal at zIndex=90 - broker icon fallback chain (icon_url → portal favicon → plugin icon → initial letter) extracted into brokerIconChain.svelte.ts; BrokerIcon and BrokerBadge both use it — single source of truth - BrokerBadge: drops colored-dot fallback, uses initial letter (consistent with BrokerIcon); gains full multi-URL retry on load error - brokerStore: ensureBrokersLoaded + refreshAllBrokers both fire ensurePluginIconsLoaded; fixes brokers/ page showing "R" because plugin cache was empty at render time - brokerHelpers: correct priority order restored (favicon before plugin icon); getBrokerIconCandidates replaces duplicated inline new URL(portal_url).origin+'/favicon.ico' in 4 modal files - ChartSignalsSection: remove local ASSET_TYPE_ICON_MAP, use getAssetTypeIconUrl - resolveValidationMessage: use getAssetTypeIconUrl instead of inline path construction fix(docs): responsive scaling for landing page on narrow mobile - logo+h1 hero row: clamp(2.2rem,9vw,4rem) + proportional logo; prevents overflow on 320px+ viewports - h2 subtitle: clamp(1.1rem,5.5vw,2.2rem) + suppress mobile-break span so text wraps naturally instead of forced at 768px - all landing text elements scale proportionally: badges, buttons, deep-dive h2/p, provider-info, lf-fit cells, quick-install paragraphs - badge gap: clamp(0.5rem,3vw,2rem) - nav cards: grid layout (icon+title row 1 / desc row 2 full-width) replaces flex; card-desc uses grid-area:desc for guaranteed full-width on every viewport
…uy_price Replace N×M compute_wac_iterative DB calls with single-pass inline WAC computation. Restructure engine around per-tx unified loop: - Pre-frame/frame separation (no market eval before t0) - Price fallback: MARKET_PRICE → LAST_BUY_PRICE(V(u)) → MISSING - 3-pool event-driven: read WAC → update K/R → reduce pool - DailyPositionState emitted at t0/t1 + period accumulators - Blob cache fingerprint-keyed (range-aware, reuse if contained) Key fix: SELL now reads WAC before reducing pool, preventing full-sell bug where entire proceeds went to returns (R) instead of splitting capital (K) + gain (R). Adds 20 unit tests validating: inline WAC, last_buy_price chain, 3-pool decomposition, position snapshots, period accumulators, pre-frame/frame separation.
Dashboard charts (Growth, AllocationHistory) use xAxis type:'time'
with namedPoint({name: date, value}) for ECharts shift animation —
shared dates translate vertically, new dates enter, removed exit.
Partial setOption on data-only updates avoids full chart rebuild.
- Centralize animation config in echartsAnimationConfig.ts
- Add TweenedValue component for numeric interpolation (900ms cubicOut)
- Apply TweenedValue to 14 KPI numbers (3 hero + 11 metric bars)
- Persistent DOM containers prevent chart instance destruction
- Stale-while-revalidate: keep old data visible during fetch
- FX page: single bulk HTTP call via ensureFxRangeLoadedBulk()
- Pie chart: notMerge:false for segment morph animation
- LineChart/Candlestick/PriceChartFull: merge-mode animation
- KPI bars: CSS transition duration-700 + marker caret animation
- Added Step 3 (Analysis & Parsing) explanation table for grid emojis in all languages
- Clarified that Step 3 TODO action indicators (orange/red) are not errors but rather missing values to be solved during the bulk revision step
- Added UNIQUE (green) and UNRESOLVED (red) badges and matching rules to duplicate detection tables across all languages
- Translated and aligned Dashboard index.md page for Italian, French, and Spanish
- Fixed Mermaid diagram tab layout indentations in asset create-edit guides
- Fixed missing translation keys for navigation menus in mkdocs.yml ("Create & Edit" and "Events")
Stale-while-revalidate pattern: old data stays visible during fetch, new data animates in when ready. Eliminates blank/loading flicker on period change for repeat visits. - GrowthChart/AllocationHistory: xAxis time + namedPoint shift anim - AllocationPieChart: partial setOption for segment morph - TweenedValue component: 14 KPI numbers interpolate (900ms cubicOut) - KpiMetricBar: CSS transition on bars + markers (duration-700) - Persistent DOM containers prevent chart instance destruction - FX page: single bulk HTTP call via ensureFxRangeLoadedBulk() - Detail page charts (Line/Candle) unchanged: instant render
…stamp command
## Translation pipeline
- Add `translate-stamp` subcommand to translate_docs.py:
- Updates .translate-hashes.json to current MD5 without invoking the LLM
- Supports --file, --lang, --dry-run flags
- Preserves all existing cache metadata (analysis, critique, etc.)
- Available as both `./dev.py mkdocs translate-stamp` and standalone
- Use after manual edits to prevent spurious re-translation on next run
- Stamp 51 already-translated files to re-sync cache after manual edits
## Docs: performance-metrics structural alignment (EN → IT/FR/ES)
- Add "Relationship with Total P&L" section to period-pnl.{it,fr,es}.md
(mirrors existing EN section with LaTeX formulas and Growth Chart reference)
- Add Deposited Capital & Total P&L row to index.{it,fr,es}.md metrics table
- Confirm 381/387 translation files structurally clean (6 intentional minor deltas)
## Docs: missing translation inventory
- Confirmed 4 files with no translations yet:
deposited-capital.en.md, kpi-cards.en.md, charts.en.md, host_installation.en.md
New dedicated page with formal notation for the full engine:
valuation chain, WAC iterative update, portfolio aggregation,
3-pool cash model (K/R/W), period contribution, pre-frame/frame.
Existing metric pages slimmed down to reference engine page.
Fix KaTeX rendering: replace € and {,} in math blocks with
\text{ EUR} and \, (thin space).
Enum filter popovers still consumed `iconUrl`, so broker options fed with `iconCandidates` rendered dot-only fallbacks. Keep tx broker-name hooks on BrokerBadge and add focused regressions for dashboard and transaction broker surfaces.
… ingest new work untill now
Frontend-only feature: two-button dropdown next to Sync builds structured prompt from portfolio report + technical signals, copies Markdown+YAML to clipboard for external AI. - 11 new files in lib/features/ai-export/ - types, builder, renderers (full prompt + data-only) - generic cross-detection engine for signal events - daily→weekly sampling for 3M technical window - EMA20/50/200, RSI14, MACD computed via existing signals - normalized return % from common 3M base date - i18n keys added (EN/IT/FR/ES) - svelte-check: 0 errors, 0 warnings
…chors
- Translated WAC (Weighted Average Cost) and CMP (Coût Moyen Pondéré) to localized equivalents: PMC (Prezzo Medio di Carico) in Italian and PMP (Precio/Prix Moyen Pondéré) in Spanish and French.
- Aligned mathematical formulas in `weighted-average-cost.md` using localized terms (e.g., `PMC_{\text{attuale}}`, `PMP_{\text{nuevo}}`).
- Cleaned up remaining WAC/CMP references across all user guides, transaction forms, and broker import documents.
- Fixed relative paths for transaction icon assets in `portfolio-engine` tables (`../../../static/`).
- Updated cross-file links to point to correct localized section anchors.
- Updated `.translate-hashes.json` cache stamps via `translate-stamp` for modified English files to prevent LLM re-translation.
Bug fixes: - Dropdown outside-click: use closest() instead of === - Replace BrainCircuit icon with Brain Semantic fixes: - Multiply ratio-format *_percent fields by 100 - Add metric_definitions to methodology section - Add allocation_basis + Other/Unallocated if gap >0.5% - Filter closed positions with no period activity - Add is_open flag and valuation_source proxy - Rename "Return %" column to "Return from 3M base %" Noise reduction: - Add epsilon to price/EMA cross detection (~0.1%) - Add minGapDays (3-5) between same-type events - MACD histogram epsilon 0.05 (ignore near-zero) - Limit to 5 events/asset, 40 total - snake_case YAML keys (ema20, macd_histogram, rsi14) - Filter backward-filled (non-trading) prices Prompt improvements: - Add PAC amount absent instruction - Tighten web research scope
Semantic fixes: - Replace deposited_capital with total_invested (lifetime denominator) - Add period_net_deposits (period-scoped, formerly misleading) - Fix metric_definitions to match actual computation - Change allocation_basis to nav_including_cash - Remove closed positions entirely (not relevant for PAC) - Remove is_open field (all exported positions are open) New sections: - technical_summary: compact per-asset overview (return_3m, RSI, MACD, price_vs_ema%) before full tables - pac_context: explicit PAC parameters (amount unavailable, EUR, no sale suggestions, new assets unknown) Prompt improvements: - Analysis request: 3 named PAC scenarios (rebalance, core accumulation, cautious/risk-control) - Explicit "not investment advice" framing Events: max 4/asset (was 5), 30 total (was 40)
Allocation: - by_asset, by_currency, by_broker now include cash to match allocation_basis: nav_including_cash (previously excluded cash, causing sums <100% inconsistent with broker_summary) - by_asset_type/by_sector already included cash via backend Liquidity bucket; by_geography left as-is (cash has no geography) Removed: - valuation_source field from positions (product decision: exported values are already best-estimate, AI shouldn't reason about source) Added: - methodology.technical_context_policy — clarifies 3M technical window is independent from the selected portfolio date range - investor_assumptions section (risk_tolerance, investment_horizon, target_allocation: unavailable) + prompt instruction not to assume user profile - Data-only export now includes methodology (was missing entirely, needed to interpret wac_policy/valuation_policy without prompt text) Reordered sections in both renderers: Methodology → Export Metadata → Snapshot → Allocation → Positions → Broker Summary → PAC Context → Investor Assumptions → Technical Summary → Technical Series → Events → Unavailable → Data Quality Prompt: refined underweight/overweight wording to state assumptions explicitly rather than imply objective thresholds. Kept unchanged per product decision: period_pnl/period_pnl_percent on positions, technical event noise filters (already adequate).
Long lists of sub-1% countries or sectors reduce signal-to-noise for the LLM when the export contains diversified portfolios. Added allocationCompaction.ts: - Static ISO3->continent lookup (~230 codes, 5 continents: Europe, Asia-Pacific, North America, South America, Africa) - compactGeography(): countries >=1% kept individually, <1% grouped into "<Continent> minor countries"; unmapped codes fall into "Other minor countries" - compactSector(): sectors >=1% kept individually, <1% merged into a single "Minor sectors" bucket - Unknown/Liquidity never merged into minor buckets regardless of weight — kept as standalone signals by_geography now also includes cash explicitly as a "Liquidity" line (previously excluded entirely from geography, unlike by_asset_type/by_sector which already had it via backend). methodology.allocation_compaction_policy declares thresholds and grouping rules so the AI knows small exposures are aggregated. Requested Analysis text updated with the same note. by_asset, by_asset_type, by_currency, by_broker intentionally left uncompacted — either already short or needed at full detail for PAC decisions. Validated: svelte-check 0/0, i18n audit 1476/0 incomplete.
- Remove 194 unused/duplicate keys across en/it/fr/es (1670 -> 1476),
verified against frontend literal + template usages, backend
message_i18n_key data refs, and e2e tests
- Merge 52 fully-duplicate key groups into common.* canonicals,
repointing all call sites; keep dynamic-prefix namespaces
(transactions.fields/types/errors, chartSettings.*, assets.types,
etc.) untouched since they're resolved via `$t(prefix.${var})`
- Normalize a handful of incidental translation inconsistencies found
along the way (casing drift, missing accents)
- Fix i18n-audit.py false positives: detect backend-driven
message_i18n_key="ns.key" data refs and camelCase-continuation
dynamic templates (historyDays${day}) that the static scanner missed
- Document accepted-duplicate and protected-namespace rules in the
devpy-i18n skill for future audits
122 duplicate groups remain, all reviewed and intentionally kept
(protected dynamic prefixes, semantic/context differences, or
grammar-dependent casing). Coverage 100% across all 4 languages,
svelte-check clean, 0 orphaned key references.
Root cause: by_type/by_sector already fold cash into their backend denominator (via a "Liquidity" bucket), but by_geography does not — the backend has no geographic classification for cash, so its country percentages already sum to ~100% of market_value alone. Adding a NAV-based Liquidity line on top of that already-complete 100% pushed the section to ~101%, and ensureAllocSums100() then emitted a negative "Other / Unallocated" residual to force the sum back to 100 — invalid, confusing data for the AI advisor. Fix (no rescaling, per product decision): - by_geography no longer gets a Liquidity line added; countries are exported exactly as returned by the backend, on their own market_value_excluding_cash basis - Declared explicitly via methodology.allocation_basis_exceptions so the AI doesn't assume by_geography sums to 100% of NAV like the other sections - ensureAllocSums100() now guards against negative residuals: only adds a positive bucket above +0.5pp tolerance; a negative gap is logged as a console warning and silently omitted, never exported Also added metric_definitions.position_period_pnl_percent to distinguish the position-level P&L percentage (period_pnl / |start_value|) from the technical return_3m_percent shown in the Technical Summary — same name, different meaning, now disambiguated.
…nition
The position_period_pnl_percent metric definition contained a literal
"&" ("P&L"). Any downstream Markdown-to-HTML rendering of the copied
clipboard text (e.g. viewing it through a Markdown-aware tool) would
legitimately re-encode it as "&" per CommonMark/HTML rules, which
could confuse an AI reading the rendered version. Reworded to
"gain/loss" to sidestep the ambiguity entirely — the clipboard writer
itself does no escaping of its own.
Added metric_definitions.simple_roi_percent, previously undocumented:
"(NAV - period_net_deposits) / period_net_deposits" — verified against
calculate_simple_roi() and its call site in portfolio_service.py; the
denominator is the selected period's net deposits (same field already
exported as period_net_deposits in Portfolio Snapshot), not lifetime
total_invested.
No changes to by_geography, allocation values, valuation_source,
technical calculations, or backend/API.
Both flagged as mathematically inconsistent against real exported data — traced to actual backend code, confirmed as genuine errors: simple_roi_percent: Round-6 definition "(NAV - period_net_deposits) / period_net_deposits" gave ~688% with real numbers (nav=51004.25, period_net_deposits=6468.26) vs actual 11.63%. Traced portfolio_service.py: the real denominator is period_nav_start + net cash flows after period start (via a synthetic -period_start_nav cash flow), not period_net_deposits alone. Added period_nav_start to AiPortfolioSnapshot (existing backend field summary.period_nav_start, no backend changes) and reworded the definition as an explicit approximation — not an exact formula, since LibreFolio's ROI calc and period_pnl calc use slightly different period-boundary conventions internally and aren't guaranteed to match to the last decimal. by_geography basis: Round-5 text claimed percentages "are not rescaled to NAV and do not sum to 100%" — contradicted by real data (countries + minor buckets ≈ 100%). Verified portfolio_engine.py: backend excludes cash from by_geo's own denominator before normalizing to 100%, so the section genuinely sums to ~100%, just of invested market value excluding cash (not of NAV like every other allocation section). Corrected the allocation_basis_exceptions text to state this precisely, with the practical inflation effect noted for the AI reader.
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.
AI Portfolio Export, Portfolio Engine Refactor & Dashboard Overhaul
Major backend engine rework (inline WAC, per-broker cash pools), a new
frontend-only AI advisor export feature, MWRR/period P&L fixes with
redesigned KPI cards, and broad chart/UX/docs polish.
Highlights:
New features:
build a structured Markdown+YAML dossier from the portfolio report +
frontend-computed technical signals (EMA/RSI/MACD), for external AI
advisors during the monthly PAC review. Frontend-only, no new backend
endpoints. Includes geography/sector long-tail compaction, PAC context,
investor-assumptions disclaimer, and documented allocation-basis
exceptions
daily-stateful model splits cash into Asset Cost / Returns / Capital,
P&L = NAV − Deposited Capital narrative
stale-while-revalidate — no more blank/loading flicker on period change
Portfolio engine (backend):
loop fixes full-sell bug (proceeds no longer all routed to returns)
pools — K[broker]/R[broker] with correct CASH_TRANSFER handling
→ MISSING; pre-frame/frame separation avoids premature market eval
Dashboard & metrics (BREAKING):
added mwrr_annualized/mwrr_cumulative, removed legacy mwrr_percent/mwrr
income, fees/taxes, other_result — respects date_from/date_to
KpiMetricBar/KpiDivergingFlowBar components
net_deposited_capital, period_market_value_start, period_fees,
period_taxes, net_invested (additive)
Documentation:
chain, WAC, 3-pool per-broker, contribution, pre-frame/frame)
Fixes & cleanup:
initial letter) across BrokerIcon/BrokerBadge/filter panels
bulk modal pagination, asset currency defaults
maintained across EN/IT/FR/ES