Portfolio analytics where the AI shows its work.
Faro computes risk metrics — Sharpe, Value-at-Risk, beta, drawdown — from their published formulas, then an AI copilot explains them in plain English or Spanish. A checker compares the numbers in each answer with the engine's results and flags the ones it can't match. It skips everyday values like 1 or 100, and a wrong number very close to a real one can pass. The methodology page lists its limits.
Get it on GitHub See how grounding worksMIT licensed · No bank logins · No cloud required · Educational tool, not investment advice
Real screens, real numbers
Not mockups — the actual app running the seeded demo portfolio.
Serious analytics. Honest AI. Your machine.
Most AI finance tools ask you to trust a chatbot. Faro is built the other way around: deterministic math first, language model second, verification always.
First-principles quant engine
Every metric implemented from the documented formula and unit-tested against independently computed references — Sharpe, Sortino, alpha/beta, historical & parametric VaR, CVaR, max drawdown, correlations, concentration, risk contributions.
A copilot that shows its work
Ask "how risky am I?" or "what if NVDA drops 20%?" The agent is instructed to answer by calling the quant engine's tools. Every figure in its reply is checked against those computations, and numbers it can't trace are flagged.
Truly bilingual
Dashboard, copilot, scenarios, digests — everything works in English and Spanish with one tap. Ask in either language; get answers, number formatting and legal docs in yours.
Scenario lab & daily digest
Stress-test instant price shocks with per-position impact, and generate a one-click daily brief: movers, risk contributors, upcoming earnings — narrated from computed facts only.
Private & replicable
Your data lives in a local database on your machine. Clone → docker compose up → running in 5 minutes. Claude-powered when you add a key; free local model otherwise.
Compliance-aware by design
Educational analytics, not advice. Faro never executes trades, never touches your brokerage, and is instructed to refuse "should I buy?" (a behavior exercised in the public eval) — showing you how to evaluate it yourself instead.
Invented numbers aren't prompted away. They're caught and shown.
The #1 failure mode of LLM finance apps is invented numbers. Faro's answer is architectural — and it's measured, not assumed.
Deterministic engine underneath
Pure numpy/pandas implementations of every formula, documented and cross-checked against independent libraries in 97 tests.
quant/risk.py
historical_var(returns, 0.95)
→ 0.0162 # unit-testedThe engine is the only approved source
The copilot is instructed to take every number from five typed tools that call the same service layer the dashboard uses: one engine, two consumers. Nothing forces it to, which is why the next step exists.
tools: get_metric
get_position_detail
run_price_shock_scenario
compare_to_benchmarkEvery reply is checked
A grounding checker extracts each number from the answer and matches it to this turn's tool results. Anything it can't trace is flagged in the app. It has blind spots, listed on the methodology page, and it's measured by a public two-mode bilingual eval with raw logs in the repo.
grounding_check: every number
in the reply must trace to a
tool result → flagged if not
Honest by two measures, not one flattering number
The eval runs two ways, and the repo publishes both with raw logs. Asked fresh, each answer's numbers trace to that turn's tools. In free-flowing multi-turn chat a small local model will recite earlier figures from memory — and every one is flagged in-app rather than hidden. Whether Claude does better is untested.
From holdings to insight in four steps
No accounts, no brokerage linking — enter what you own and Faro does the math.
Enter your holdings
Tickers, shares, cost basis. Data stays in a local SQLite file on your machine.
Faro computes your risk profile
Free daily market data, cached on disk, feeds the full metrics suite — with graceful offline degradation.
Ask the copilot anything
Streaming answers with visible tool-call chips, in your language, with every number cited from computations.
Read your daily digest
Drivers, risk contributors and upcoming earnings for your holdings — generated on demand.
One engine, two consumers
The dashboard and the copilot read the same service layer, so the charts and the chat can never disagree — and the copilot's replies are grounding-checked on top.
React dashboard
React 18 · TypeScript · Tailwind · Recharts · i18next EN/ESAI copilot
Claude primary ⇄ local Ollama fallback, swapped by one environment variable. Its only source of numbers: five typed tools.grounding checker on every replyFastAPI service layer — the single computation path
One set of services answers both the dashboard's REST calls and the agent's tools.Quant engine
Pure numpy/pandas, every formula documented and unit-tested — no black-box quant libraries.Market data
Free daily bars: yfinance with a Stooq fallback, cached on disk — keeps working from cache when providers are unreachable.How to evaluate this in five minutes
Built as a work sample. Here's where to look, and what each choice is meant to demonstrate.
The quant is from first principles
Every metric implemented from its documented formula in pure numpy/pandas — no black-box libraries — tested against hand-computed references plus independent cross-checks.
Read the engine →The guardrail is code, not vibes
The grounding checker that extracts every number and matches it to a tool result — the mechanism that makes “detected and surfaced” a testable claim.
Read the checker →The eval is public and honest
A two-mode bilingual spot-check with the iteration history (28 → 4 → 2) and raw logs committed — including the fabricated $12,345.67 the checker caught.
See the results →It runs from a clean clone
97 unit tests, mypy-strict, CI green on every push, and clone → docker compose up → running in five minutes. Replication as a design constraint.
Browse the tests →Running in five minutes
git clone https://github.com/CarlosM787/faro && docker compose up
That's the whole install. No API keys required — add ANTHROPIC_API_KEY later to switch the copilot to Claude with zero code changes.