PRISM-INSIGHT
These are 13 specialized AI agents that analyze Korean and US stocks in real-time, and this is open source and free to use.
AI translation
把台股、美股、加密貨幣與現金折成台幣,畫在同一張圖上。XIRR、TWR、回撤與配置都寫明算法,資料不夠時顯示「—」。
Translation pending
FinanceTypeScript · PLpgSQLGitHub @wppypewoOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
StackWorth:美股 ETF、台股、加密貨幣跨帳戶的個人投資組合追蹤,TWD 計價,XIRR/TWR。Next.js + Supabase
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗English | 繁體中文
A personal portfolio tracker for a long-term investor holding US ETFs, Taiwan stocks, crypto, and manual assets across multiple accounts — everything in one TWD-denominated dashboard.
Live app: https://portfolio-tracker-two-rho.vercel.app · Public demo (no login): https://portfolio-tracker-two-rho.vercel.app/demo · Full reference: docs/REFERENCE.md
Personal finance tool. Not investment advice, not affiliated with any institution, not a commercial product. The interface is in Traditional Chinese.
Public demo, generated data. Light and dark themes follow your GitHub setting.
Holding assets across markets and currencies means brokerage apps only ever show fragments. Spreadsheets can't pull live prices or keep a clean contribution history. What I wanted did not exist in one place: XIRR and TWR side by side, computed with correct sign conventions, scoped to the portfolio I actually hold today, in my own base currency.
One computation pipeline, two callers. All dashboard math lives in buildDashboardData, a pure function with no I/O. The production page feeds it Supabase rows; the public /demo route feeds it deterministically generated data. The demo is therefore not a mockup — XIRR, TWR, Sharpe, and drawdown on the demo page are computed by the exact code that runs on my real portfolio.
XIRR and TWR use opposite cashflow conventions, on purpose. XIRR follows the investor's wallet (investment = negative, terminal portfolio value appended as positive); TWR follows the portfolio (contribution = positive, terminal value excluded because it is already embedded in the last snapshot — including it would zero out the final sub-period). The sign flip happens once, at one documented point, with regression tests pinning the terminal-value misuse case.
The XIRR solver validates its residual before returning a rate. Every exit path of the Newton-Raphson loop checks |NPV(rate)| against a scale-relative tolerance; oscillation, flat derivatives, and hitting the iteration cap all return null instead of a residual value.
Dashboard scope is the active portfolio. Summary values, the trend curve, performance metrics, income stats, and allocation share one active-account boundary. Showing archived accounts only expands the holdings ledger; it cannot change the dashboard totals or appear as a value drop in TWR.
Risk metrics preserve cashflow and time boundaries. Max drawdown is calculated from the cashflow-adjusted TWR index, so withdrawals do not look like market losses. Sharpe converts irregular snapshot intervals to equivalent daily returns and annualizes on calendar days because the portfolio includes assets that trade on weekends.
Recurring execution is ledger-backed and idempotent. Cron and manual execution fetch the latest quote, then call one Postgres RPC. The function locks the plan and account, derives the quantity increment from current database values, writes the transaction and snapshot, records the scheduled run, and advances the plan in one transaction. A unique (plan_id, scheduled_date) key makes retries and double clicks harmless.
Failure states are explicit. Benchmark fetchers return empty on failure and the chart bridges gaps with a dashed segment; enabled comparison lines share one start date before they are normalized to 100; CoinGecko's history cap renders BTC as a late-starting series; the service worker caches only an offline page, since showing stale financial numbers is worse than failing to load; a data-health card in settings turns red when the price cron misses a run.
Decision context is write-once. A decision stores the price, FX rate, position, allocation, cost, unrealized P&L, and portfolio value seen at creation. Database triggers reject later edits to that context while still allowing the thesis, review date, and other user-authored fields to be corrected.
Historical pages never borrow today's quote. Replay uses the latest snapshot available on or before the selected date, labels carried-forward values with their source date, and exposes missing data. The attribution equation keeps a visible scale-relative residual instead of hiding an incomplete split.
/decisions, optionally link it to an activity transaction, preserve the original context, schedule a review, and record outcome and process separately./history to inspect holdings, archived boundaries, price dates, allocation, currency exposure, and a reconciling change breakdown./whatif to combine price and FX shocks, then model an external proposed purchase without writing to the ledger./reports/monthly, review returns, attribution, allocation, decisions, gaps, and data health, then use the browser's print-to-PDF flow.Asia/Taipei explicitly; Vercel runs in UTC, and a one-day shift in snapshot dates corrupts day-change and TWR.https://portfolio-tracker-two-rho.vercel.app/demo — no account needed.
Generated data: an 18-month DCA history with a seeded pseudo-random walk, a planted correction regime, one realized loss, dividends and interest. Deterministic per day, so reviewers see the same numbers on revisit. The production dashboard holds personal financial data, so every screenshot in this repository comes from the demo.
| Historical replay and attribution | Stress test and anti-FOMO check |
|---|---|
The demo flows are /demo/decisions, /demo/history, /demo/whatif, and /demo/report. They use deterministic fixtures only and never query an authenticated user's portfolio.
Amount masking remains available in the authenticated app. Printed monthly reports state whether amounts were visible when the report was generated; check that state before saving a PDF on a shared device.
git clone https://github.com/wppypewo/portfolio-tracker
cd portfolio-tracker
npm install
cp .env.local.example .env.local # fill in; see docs/REFERENCE.md for the variable table
npm run dev
Gates: npm run lint / npm run typecheck / npm run test:unit / TEST_DATABASE_URL=... npm run test:integration / npm run build.
Running in production (Vercel + Supabase, single user). CI runs lint / typecheck / unit tests / Postgres integration / build on every push to main. The current release is v1.3.0 (2026-10-25): tiered DCA amounts, cost-basis correction, the public /about page, MFA enforced at the database layer, and a set of Asia/Taipei date fixes. Each release lists the SQL migrations it needs; the full order is in supabase/README.md.
Known limits: replay and reports use bounded snapshot queries and surface truncation or missing prices; review performance depends on stored daily snapshots; browser printing is the PDF path; authenticated create/review flows require a configured Supabase project. See docs/REFERENCE.md and CHANGELOG.md.
Built by @wppypewo as a daily-use tool for a multi-asset, multi-currency portfolio.
MIT.