-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Two mechanisms do the actual work of making a recommendation trustworthy:
the agent pipeline that produces it, and the privacy boundary that decides
what any of them are allowed to see outside your machine. This page covers
both at the level that matters for deciding whether to trust the output —
for the full module-by-module breakdown, see
docs/ARCHITECTURE.md
in the repository.
flowchart TD
H["holdings.csv + investment_policy.md"] --> A1[market-analyst]
H --> A2[portfolio-auditor]
H --> A3[stock-researcher]
H --> A4[mf-analyst]
H --> A5[tax-strategist]
H --> A6[risk-officer]
A1 --> D["devil's-advocate<br/>adversarial review"]
A2 --> D
A3 --> D
A4 --> D
A5 --> D
A6 --> D
D --> G{"validator gate<br/>cites a real tool call?"}
G -- yes --> R["reports/*.md"]
G -- no --> X[rejected]
-
Six specialists run in parallel, each with its own tools and its own
angle on the same portfolio —
market-analyst(consensus, trend),portfolio-auditor(policy breaches),stock-researcher(fundamentals),mf-analyst(mutual funds),tax-strategist(STCG/LTCG impact), andrisk-officer(concentration, correlation). -
devil's-advocatereviews every finding adversarially before any of it is allowed near the report — this is the step that catches a specialist's own overconfidence, not just factual errors. - The validator gate is deterministic code, not a model. It reads the actual tool-call log from that run and rejects any claim citing a number that isn't in it. A recommendation that survives adversarial review can still be rejected here if it can't produce a receipt.
-
The LLM never computes a number. Weights, returns, tax, correlations,
risk — all deterministic Python (
mybroker/portfolio/), same result every time. Agents reason and call tools; they never do arithmetic.
flowchart LR
subgraph M["Your machine"]
HC["holdings.csv"]
POL["investment_policy.md"]
MEM["memory/ + reports/"]
FF["factfolio process"]
HC --> FF
POL --> FF
FF --> MEM
end
subgraph E["External services"]
MD["NSE / BSE / yfinance"]
CL["claude CLI<br/>(report / chat only)"]
end
FF -- "ticker symbol only" --> MD
MD -- "prices, fundamentals" --> FF
FF -- "question + evidence" --> CL
CL -- "analysis" --> FF
Only two things ever cross the boundary:
- Ticker symbols out, prices/fundamentals back — to NSE/BSE/yfinance, for every command that touches market data.
-
A question plus its supporting evidence out, analysis back — to the
claudeCLI you already control, and only when you explicitly runreportorchat.
Your holdings, quantities, and ₹ values never appear in either of those. No
packaging choice, install method, or command changes that — it's enforced
by what the data provider clients are given (mybroker/data/*_provider.py),
not a policy anyone has to remember to follow.
The standalone builds (factfolio-macos-arm64, factfolio-windows-x86_64.exe,
factfolio-linux-x86_64) bundle the Python interpreter and every
dependency — nothing else to install. They do not remove the need for
the separate claude CLI (claude login or ANTHROPIC_API_KEY) for
report/chat — no packaging choice changes that, since factfolio shells
out to it rather than embedding it. See FAQ for what that CLI itself
does and doesn't see.
MIT licensed · not investment advice · pankajads.github.io/factfolio · repository