From ffdd5310941941091dbd5a8550c4ecd594410132 Mon Sep 17 00:00:00 2001
From: 31b4 {r.signed?signedAmount(r.value,currency,hidden):amount(r.value,currency,hidden)} {r.note} {r.signed?signedAmount(r.value,currency,hidden):amount(r.value,currency,hidden)} {r.note} {today.boundary} Manual values and stale or missing market inputs are excluded. Return shows unrealized gain and its percentage of remaining cost. Filters affect holdings only.
- Buy / Sell markers use recorded execution prices in {history?.currency ?? 'quote currency'}.
- Unverified or other-currency executions remain in the dated list below.
-
- Current average remaining cost:{' '}
- {currentCost === null
- ? 'Unavailable in this chart currency'
- : costPrice(currentCost, history?.currency ?? '')}
- . Dashed reference is today's remaining basis per unit, not a historical cost series.
- {r.label}
{r.label}
Today coverage
- {signedAmount(p.gainLoss, reportingCurrency, hidden)}{' '} - - total gain · excludes dividends ·{' '} - {hidden - ? '••••' - : p.gainLossPercent === null - ? 'Estimated return unavailable' - : `${percentage(p.gainLossPercent)} estimated`} - + {signedAmount(p.gainLoss, reportingCurrency, hidden)}
{(protectedAccount || (market && freshness.needsAttention) || p.priceFetchError) && ( diff --git a/client/src/components/investments-module/Investments.tsx b/client/src/components/investments-module/Investments.tsx index 03ef440..82bd500 100644 --- a/client/src/components/investments-module/Investments.tsx +++ b/client/src/components/investments-module/Investments.tsx @@ -58,7 +58,6 @@ export function Investments() {This page includes all active holdings. Net-worth exclusions apply in net-worth views. Buy and sell directly with a cash account.{!canTrade&&accounts.length>0?' An unlocked cash account and holding are needed to record a trade.':''}
{data.from} – {data.to} · {data.timezone} · read {new Date(data.as_of).toLocaleString()}{data.points.at(-1)?.provisional?' · today is provisional':''}
-History includes sold and archived holdings. Gain excludes contributions, withdrawals and dividends. Estimated return links daily factors, assuming contributions at the start and withdrawals at the end of each day. Missing inputs leave gaps.
{data.method.price_timing}
{data.method.fx_timing}
{data.method.current_endpoint}
- {summary?.reasons.length!==0&&Range coverage: {summary?.reasons.join(', ').replaceAll('_',' ')}.
} -Unknown legacy history starts at its first supported boundary. Net invested requires known lifetime cash flows; it is not remaining cost basis. All is bounded to the last ten years.
-{data.coverage_ranges.length-30} more coverage intervals in this response.
} -{r.signed?signedAmount(r.value,currency,hidden):amount(r.value,currency,hidden)}
{r.label==='Total gain'?(gainPercent!=null&&{hidden?'••••':`${percentage(gainPercent)} · Gain on net invested`}):r.label==='Today'&&{hidden?'••••':r.percent==null?'Estimated return unavailable':`${percentage(r.percent)} estimated`}}{r.note}
{today.boundary} Manual values and stale or missing market inputs are excluded.
{r.signed?signedAmount(r.value,currency,hidden):amount(r.value,currency,hidden)}
{r.label==='Total gain'?(gainPercent!=null&&{hidden?'••••':`${percentage(gainPercent)} · Gain on net invested`}):r.label==='Today'&&{hidden?'••••':r.percent==null?'Estimated return unavailable':`${percentage(r.percent)} estimated`}}{p.date}{p.provisional?' · provisional':''}
Portfolio value: {money(p.value)}
Net invested: {money(p.net_invested)}
Contributions: {money(p.contribution)} · Withdrawals: {money(p.withdrawal)}
{p.price_as_of_oldest&&Price observations: {p.price_as_of_oldest}{p.price_as_of_latest!==p.price_as_of_oldest?` – ${p.price_as_of_latest}`:''}
}{p.fx_as_of_oldest&&FX observation: {p.fx_as_of_oldest}
}{point.provisional?' · provisional':''}
+Total gain
+{signedAmount(gain,currency,hidden)}
+ {gainPercent!=null&&{percentage(gainPercent,hidden)}
} +Portfolio value
{amount(value,currency,hidden)}
Allocation appears when you add holdings with known values.
:Allocation appears when you add holdings with known values.
:{!complete?'Complete weights unavailable until every holding has a known value. ':''}{view.allocation==='type'?'Select a type to filter holdings.':view.allocation==='currency'?'Quote / valuation currency, not geographic exposure.':'Full portfolio · select a holding for details.'}
{money(displayedValue)}
Range gain {money(summary?.gain)} · {percent(summary?.estimated_return_percent)} estimated return · Excludes dividends
@@ -27,7 +27,7 @@ export function PortfolioHistoryChart({history,hidden,currency,currentValue}:{hi{data?'Showing saved history. Refresh failed.':'Portfolio history could not be loaded.'} {history.errorMessage}
} {loading&&{data?'Refreshing history…':'Loading portfolio history…'}
} -{r.signed?signedAmount(r.value,currency,hidden):amount(r.value,currency,hidden)}
{r.label==='Total gain'?(gainPercent!=null&&{hidden?'••••':`${percentage(gainPercent)} · Gain on net invested`}):r.label==='Today'&&{hidden?'••••':r.percent==null?'Estimated return unavailable':`${percentage(r.percent)} estimated`}}{r.signed?signedAmount(r.value,currency,hidden):amount(r.value,currency,hidden)}
{r.label==='Total gain'?(gainPercent!=null&&{hidden?'••••':`${percentage(gainPercent)} · Gain on net invested`}):r.label==='Today'&&{hidden?'••••':r.percent==null?'Estimated return unavailable':`${percentage(r.percent)} estimated`}}{status.stale?'Saved snapshot':'As of'} {data?.asOf?new Date(data.asOf).toLocaleString(undefined,{month:'short',day:'numeric',hour:'2-digit',minute:'2-digit'}):'unavailable'}
-
{loading ? 'Loading daily observations…' : 'No known daily closes in this range.'}
@@ -262,13 +269,15 @@ export function InvestmentChart({
tickFormatter={(n) => Number(n).toLocaleString(undefined, { maximumFractionDigits: 6 })}
/>
{d} Date only · execution price unavailable in chart currency Daily close: {money(p.close)}