-
Notifications
You must be signed in to change notification settings - Fork 1
features portfolio
The portfolio feature manages investment holdings, supports CSV import, and enables portfolio-level research. It lives in frontend/src/features/portfolio/ (3 files).
graph TD
A[PortfolioPage] --> B{selectedPortfolio?}
B -->|No| C[EmptyCreate]
B -->|Yes| D[PortfolioView]
D --> E[PortfolioInsights]
D --> F[Holdings Table]
D --> G[CSV Import]
D --> H[Portfolio Analysis]
D --> I[Linked Analyses]
A --> J[useRunAnalysis]
A --> K[useImportPortfolioCsv]
A --> L[useCreatePortfolio]
A --> M[useRenamePortfolio]
A --> N[useDeletePortfolio]
frontend/src/features/portfolio/PortfolioPage.tsx (1012 lines) is the main portfolio management page. It renders one of two states:
When no portfolio is selected, the page shows a creation screen with:
- A hero section with title "Create a portfolio." and description.
- A base currency selector (USD, EUR, GBP, CHF, JPY, CAD, AUD, SEK, NOK, VND).
- A "Create a portfolio" button that calls
createPortfoliovia Tauri IPC. - Feature badges: Portfolio tracking, Holdings snapshot.
When a portfolio is selected, PortfolioView renders:
- Header — editable portfolio name (click to rename, Enter to commit, Escape to cancel), base currency, last import date, and a dropdown menu with rename/delete options.
-
Snapshot import area — a textarea for pasting CSV data plus a file upload button. The "Update snapshot" button parses the CSV via
parsePortfolioCsv()and imports it viaimportPortfolioCsv(). - PortfolioInsights — computed portfolio-level metrics.
- Holdings table — a detailed table of all positions.
- Portfolio analysis — a "Run portfolio analysis" button that creates a portfolio-scoped analysis and launches an agent run.
- Linked analyses — previous analyses created from this portfolio.
sequenceDiagram
participant U as User
participant PP as PortfolioPage
participant CMD as commands.ts
participant BE as Rust Backend
U->>PP: Paste CSV or upload file
U->>PP: Click "Update snapshot"
PP->>CMD: parsePortfolioCsv(text)
CMD->>BE: Tauri IPC: parse_portfolio_csv
BE-->>CMD: PortfolioCsvRow[]
CMD-->>PP: Parsed rows
PP->>CMD: importPortfolioCsv(input)
CMD->>BE: Tauri IPC: import_portfolio_csv
BE-->>CMD: PortfolioImportResult
CMD-->>PP: Result with warnings
PP->>PP: Refresh portfolio detail
PP->>U: Toast with import summary
The PortfolioCsvImportInput includes the portfolio ID, account info, base currency, import kind (positions or transactions), and the parsed rows. The backend returns an PortfolioImportResult with imported_count, review_count, and warnings for rows that need manual review.
When the user clicks "Run portfolio analysis":
- Picks an agent and optional model override from a dropdown.
- Calls
createPortfolioAnalysis(portfolioId, null)to create an analysis scoped to the portfolio. - Calls
startWithAnalysisId()fromuseRunAnalysisto launch the agent. - The agent receives the portfolio context and generates portfolio-specific report sections (holding reviews, allocation, risk, rebalancing).
frontend/src/features/portfolio/PortfolioInsights.tsx computes and displays portfolio-level metrics in a grid of cards:
| Metric | Key | Description |
|---|---|---|
| Positions | portfolio:position_count |
Total number of holdings |
| Top 5 weight | portfolio:concentration_top5 |
Combined weight of 5 largest positions (emphasized if >70%) |
| Top 3 weight | portfolio:concentration_top3 |
Combined weight of 3 largest positions |
| Largest position | portfolio:largest_position |
Weight of single largest holding (emphasized if >15%) |
| Currencies | portfolio:currency_exposure |
Number of distinct currencies |
| Markets | portfolio:market_exposure |
Number of distinct markets (if market data available) |
| Unrealized P/L | portfolio:unrealized_pnl |
Gain/loss from cost basis (emphasized if <-10%) |
Each metric card supports metric explanation tooltips. The explanations are generated by getPortfolioExplanations().
frontend/src/features/portfolio/portfolio-explanations.ts generates static MetricExplanation objects for portfolio metrics. It provides:
| Column | Explanation |
|---|---|
| Portfolio Weight | Percentage of total portfolio value; warns if single position >10-15% |
| Market Value | Current total value (quantity × price) |
| Quantity | Number of shares/units owned |
| Price | Last known market price per unit |
| 30-Day Price Change | Recent price momentum |
| Metric | Definition | Good Threshold |
|---|---|---|
| Concentration (Top 5) | Combined weight of 5 largest holdings | <50% diversified, 50-70% moderate, >70% concentrated |
| Concentration (Top 3) | Combined weight of 3 largest holdings | <35% diversified, 35-55% moderate, >55% concentrated |
| Largest Position | Weight of single largest holding | <5% conservative, 5-10% common, >15% high conviction |
| Position Count | Total distinct holdings | 1-10 concentrated, 15-30 typical active, 50+ index-like |
| Currency Exposures | Distinct currencies across holdings | Single = simple, multi = diversification + FX risk |
| Unrealized P/L | Gain/loss from cost basis | Context-dependent |
The computePortfolioSummary() function calculates derived values (top-5 weight, largest weight, unrealized P/L, etc.) from the raw holdings array.
The portfolio frontend communicates with src/domain/portfolio.rs and src/infra/db/ through Tauri IPC commands:
| Command | Purpose |
|---|---|
create_portfolio |
Create a new portfolio with name and base currency |
get_portfolios |
List all portfolio summaries |
get_portfolio_detail |
Get full portfolio with holdings, positions, transactions |
import_portfolio_csv |
Import CSV data into a portfolio |
parse_portfolio_csv |
Parse CSV text into structured rows (client-side preview) |
rename_portfolio |
Update portfolio name |
delete_portfolio |
Remove portfolio and all associated data |
create_analysis |
Create a portfolio-scoped analysis (with portfolioId parameter) |
| File | Lines | Purpose |
|---|---|---|
frontend/src/features/portfolio/PortfolioPage.tsx |
1012 | Main portfolio management page |
frontend/src/features/portfolio/PortfolioInsights.tsx |
118 | Portfolio-level metrics display |
frontend/src/features/portfolio/portfolio-explanations.ts |
286 | Static metric explanations for portfolio metrics |
- Frontend Architecture — state management and navigation
- Report Viewer — portfolio-specific report sections (holdings, allocation, risk, rebalancing)
- Run Analysis — the analysis execution flow used by portfolio analysis
- Settings — data source configuration that affects portfolio analysis