Skip to content

Mark investments from Alpaca between Plaid syncs - #14

Open
x0ba wants to merge 7 commits into
mainfrom
cursor/investments-alpaca-market-data-98ce
Open

Mark investments from Alpaca between Plaid syncs#14
x0ba wants to merge 7 commits into
mainfrom
cursor/investments-alpaca-market-data-98ce

Conversation

@x0ba

@x0ba x0ba commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Investments already record a daily trend from Plaid snapshots. Between those syncs the book sat on yesterday’s brokerage print.

This keeps Plaid as the source of truth for quantity and cost, and marks the book from Alpaca Market Data in between. When a brokerage account resyncs, the gap versus the prior mark is recorded on the holding. Position history prefers the snapshot series from #15; daily bars are only a fallback when that series is empty.

After #15

Rebased onto main after “Let people see how their investments have moved.” The page keeps that PR’s trend chart, account/position filter, and snapshot history. Alpaca supplies live marks, day P&L, bar backfill, and reconcile-on-Plaid-sync. Daily snapshots are now written at mark value so the chart matches the live book.

Setup

npx convex env set ALPACA_API_KEY ...
npx convex env set ALPACA_API_SECRET ...
# optional — IEX is the free feed
npx convex env set ALPACA_FEED iex

Paper keys work. Without them the rest of the app is unchanged.

Checks

  • pnpm test — 14 passing (convex/lib/market.test.ts)
  • pnpm typecheck — clean
Open in Web Open in Cursor 

Note

Add Alpaca market data integration to mark investment holdings between Plaid syncs

  • Fetches live quotes and daily OHLCV bars from Alpaca for all user holdings, storing them in new securities, securityBars, and holdingReconciles schema tables.
  • Adds a 15-minute cron (crons.ts) that refreshes quotes for all users with holdings; Plaid syncs also trigger an immediate backfill via alpacaActions.ts.
  • The Investments page now displays live marks, day P&L, quote freshness, and a manual refresh button; holdings are sorted by marked value instead of institution value.
  • Snapshots in lib/investmentSnapshots.ts now use mark-to-market values instead of institution values, affecting portfolio totals and breakdowns.
  • Risk: existing snapshot history values will change retroactively for any user whose holdings have live mark prices available.

Macroscope summarized 81d34b6.

@vercel

vercel Bot commented Aug 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bud Ready Ready Preview Aug 15, 2026 8:25am

Comment thread src/routes/app/investments.tsx Outdated
Comment thread convex/lib/alpaca.ts Outdated
Comment thread convex/alpacaActions.ts Outdated
Comment thread src/components/portfolio-chart.tsx
Comment thread convex/lib/market.ts Outdated
Comment thread convex/lib/market.ts Outdated
Comment thread src/routes/app/investments.tsx Outdated
Comment thread convex/lib/market.ts
Comment thread convex/alpacaMutations.ts
Comment thread convex/alpacaMutations.ts Outdated
@greptile-apps

greptile-apps Bot commented Aug 15, 2026

Copy link
Copy Markdown

Greptile Summary

This change adds Alpaca-backed investment marks, daily price history, scheduled refreshes, and investment snapshots while retaining Plaid as the source of truth for holdings. Focused execution confirms that when Plaid restates a security ticker, stale quote and history fields are cleared and reconciliation continues to use the mark displayed before the ticker replacement.

Confidence Score: 5/5

No blocking failure remains.

Focused ticker-restatement execution, the market regression suite, and TypeScript type checking confirm the corrected market-state reset and reconciliation behavior.

T-Rex T-Rex Logs

What T-Rex did

  • Ran a focused TypeScript harness to compare ticker restatement behavior before and after the change; before the change the old live mark remained 125 and history persisted after replacement, while after the change seven market-derived fields were cleared, the replacement close mark was 50, the prior reconciliation mark value was 1250, and the value delta was 0; the repository market test suite ran and all 14 market tests passed and type checking succeeded.
  • Inspected the pre-fix overwrite and post-fix capture logic by locating code references in convex/lib/market.ts:15-39 and convex/plaidMutations.ts:565-589 and 624-639.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (4): Last reviewed commit: "Address Macroscope findings after the #1..." | Re-trigger Greptile

Comment thread convex/plaidMutations.ts
@macroscopeapp

macroscopeapp Bot commented Aug 15, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

This PR introduces a new Alpaca integration feature with external API calls, new database schema (tables and fields), a 15-minute cron job, and changes to how portfolio values are calculated. New features of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Comment thread convex/plaidMutations.ts
cursoragent and others added 5 commits August 15, 2026 08:16
Brokerage snapshots stay on Plaid's cadence. Between those syncs, Investments now pulls live marks and daily history from Alpaca so the portfolio can move without another Link refresh. When Plaid does come back, quantity and cost basis are restated and the gap versus the market mark is recorded.

Co-authored-by: danielxu0307 <danielxu0307@gmail.com>
Keep quote timestamps aligned with the price source, isolate backfill failures from committed marks, chunk bar writes, and stop emitting a partial portfolio before every ticker has a close. Also clamp month-end ranges, recover from a failed auto-refresh, and drop a stale holding filter.

Co-authored-by: danielxu0307 <danielxu0307@gmail.com>
A renamed instrument kept the old live price and history flags, so the
portfolio could mark META with FB's quote until the next refresh.

Co-authored-by: danielxu0307 <danielxu0307@gmail.com>
Clearing live price on a ticker rename happened before previousMarkValue
was computed, so the gap was measured against the new close instead of
the book we actually showed.

Co-authored-by: danielxu0307 <danielxu0307@gmail.com>
Daily snapshots now store mark values so the chart matches the live book, and a quote refresh rewrites today's point. Drop the unused PortfolioChart now that the page uses TrendLineChart.

Co-authored-by: danielxu0307 <danielxu0307@gmail.com>
@cursor
cursor Bot force-pushed the cursor/investments-alpaca-market-data-98ce branch from a5993d8 to 4ebba0a Compare August 15, 2026 08:18
CI eslint rejects inline type specifiers on the investment history import.

Co-authored-by: danielxu0307 <danielxu0307@gmail.com>
Comment thread convex/alpacaMutations.ts
Comment thread convex/investments.ts
Comment thread convex/investments.ts
Comment thread convex/investments.ts
Comment thread convex/investments.ts
Comment thread src/routes/app/investments.tsx
Comment thread convex/alpacaMutations.ts Outdated
Keep prior close/open when a quote omits them, show day P&L only when every quoteable holding is covered, treat the oldest quote as freshness, and prefer snapshot history over bars reconstructed from today's quantity.

Co-authored-by: danielxu0307 <danielxu0307@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants