Building a Sovereign Portfolio Risk Calculator: Why We Ditched the Backend
Client-side financial modeling. React risk calculator. TypeScript finance tooling.
This post is about why we deliberately killed the backend for portfolio risk analysis — and why that decision matters if you care about privacy, performance, and ownership.
The Problem: Risk Analysis Behind Paywalls
Most portfolio risk tools follow the same playbook:
- Mandatory signups
- Server-side data processing
- Cloud databases full of sensitive financial history
- Monthly subscriptions for basic metrics
We wanted the opposite.
We wanted a tool that:
- Works instantly with no login
- Runs entirely via sovereign computation
- Processes data locally in the browser
- Provides real, actionable risk metrics
- Acts as a public preview of our core engine ahead of launch
This post breaks down how we built the Portfolio Risk Calculator, a zero-login, privacy-first tool that computes portfolio Beta entirely client-side.
Try it live:
Portfolio Risk Calculator →
⏳ Launch note: We are going live in 24 hours. This calculator is a public preview of the engine behind Pocket Portfolio.
Sovereign Computation (The Core Idea)
This tool is built around a single principle:
The logic travels to the data — the data never travels to the logic.
Your browser is the compute boundary.
There is:
- No backend portfolio processing
- No server-side storage
- No account system
- No tracking
This is not “client-heavy.”
This is sovereign computation.
Architecture Overview
The Risk Calculator is a pure client-side React component that:
- Accepts comma-separated ticker symbols
- Fetches public asset metadata only (Beta, sector, industry)
- Computes portfolio Beta locally using TypeScript
- Classifies risk visually
- Discards everything on refresh
Nothing is persisted. Nothing is uploaded.
Tech Stack
- Next.js 15 (App Router)
- TypeScript
- Client-side computation only
- Public market metadata APIs
- No backend portfolio logic
API Privacy (Pre-Empting the Smart Question)
“If you call an API with my tickers, doesn’t the provider know my portfolio?”
Good question. Here’s the precise answer.
What we send:
- Batched ticker symbols only (e.g. 20–30 at a time)
What we never send:
- Position sizes
- Trade history
- Net worth
- Identity
- Portfolio composition
Batching introduces anonymity-through-noise.
Even the API provider cannot infer who you are or what you own.
This is fundamentally different from server-side portfolio tracking.
Core Implementation
1. The Client Component
The calculator is a 'use client' page — intentionally.
'use client';
import { useState } from 'react';
import { fetchAssetProfiles } from '../../services/enrichmentService';
import { AssetProfile } from '../../types/analytics';
export default function RiskCalculatorPage() {
const [input, setInput] = useState('');
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<{
score: number;
label: string;
profiles: AssetProfile[];
} | null>(null);
const [error, setError] = useState<string | null>(null);
}
Why client-side?
- Immediate feedback
- Zero trust assumptions
- No global state required
- No backend failure modes
2. Risk Analysis Logic
const analyzeRisk = async () => {
const tickers = input
.split(',')
.map(t => t.trim().toUpperCase())
.filter(Boolean);
const profiles = await fetchAssetProfiles(tickers);
const validProfiles = Object.values(profiles)
.filter(p => p.beta !== 0 && p.ticker !== 'CASH');
const totalBeta = validProfiles.reduce(
(sum, p) => sum + (p.beta ?? 1),
0
);
const avgBeta = totalBeta / validProfiles.length;
let label = '⚖️ Balanced Growth';
if (avgBeta > 1.3) label = ' High Risk / Aggressive';
if (avgBeta < 0.8) label = '️ Low Risk / Defensive';
setResult({ score: avgBeta, label, profiles: validProfiles });
};
Why Equal Weight?
This tool is a snapshot, not a full portfolio engine.
- Users may not know position sizes
- Simplicity beats false precision
- Zero-friction entry point
Important bridge:
The full Pocket Portfolio app runs the same privacy-first engine, but applies weighted Beta math using your actual holdings — still entirely local.
Data Fetching with Fallback Strategy
export async function fetchAssetProfiles(
tickers: string[]
): Promise<Record<string, AssetProfile>> {
const results: Record<string, AssetProfile> = { ...PROFILE_CACHE };
const uncached = tickers
.map(t => t.split('.')[0])
.filter(t => !results[t]);
if (uncached.length && FMP_KEY) {
await Promise.all(
chunkArray(uncached, 30).map(async batch => {
try {
const res = await fetch(
`${BASE_URL}/profile/${batch.join(',')}?apikey=${FMP_KEY}`
);
if (!res.ok) return;
const data = await res.json();
data.forEach((item: any) => {
results[item.symbol] = {
ticker: item.symbol,
name: item.companyName ?? item.symbol,
sector: item.sector ?? 'Other',
industry: item.industry ?? 'Other',
beta: item.beta ?? 1,
geo: item.currency ?? 'US',
};
});
} catch {}
})
);
}
return results;
}
Why this matters:
- Cache-first
- Offline-tolerant
- API failures don’t break UX
- Always returns a result
Beta Math (Quick Refresher)
Equal Weight Formula
Portfolio Beta = (B₁ + B₂ + … + Bₙ) / n
Example
- NVDA (1.7)
- TSLA (2.3)
- AAPL (1.2)
Average = 1.73 → High Risk
Privacy-First by Construction
What we do NOT do
- ❌ No tracking
- ❌ No cookies
- ❌ No storage
- ❌ No user accounts
What we DO
- ✅ Local computation only
- ✅ Public metadata only
- ✅ Zero persistence
- ✅ GDPR-safe by default
Data Flow
User Input
→ Client Parsing
→ Public Metadata Fetch
→ Local Calculation
→ Display Result
→ Memory Cleared
Why This Exists (The Wedge)
Most developers don’t wake up wanting a portfolio tracker.
They wake up angry that:
- Their exports are messy
- Their scripts break
- Their data is hostage
This calculator solves that problem.
And once you trust the engine, the next step is obvious.
Launch Call to Action
We are launching tomorrow.
If you believe finance software should:
- Respect user sovereignty
- Avoid data hoarding
- Run locally by default
Support the launch on Product Hunt:
Product Hunt → Pocket Portfolio
Use the free tool:
Risk Calculator →
Key Takeaways
- Client-side finance is viable
- Sovereign computation scales
- Privacy is an architectural choice
- Free tools can still be honest
- Infrastructure beats dashboards
Next Steps
Developers
- Clone the repo
- Inspect
/app/tools/risk-calculator/page.tsx
- Submit PRs
Users
- Try the calculator
- Join the Founders Club
- Own your data
About Pocket Portfolio
Pocket Portfolio is a local-first portfolio tracker that turns Google Drive into your personal database.
No servers.
No signups.
No lock-in.
Try it free →