Skip to main content

FactFolio

License: MIT Python 3.12+ Local-first Cost PyPI CI

→ pankajads.github.io/factfolio — the pitch, the agent pipeline, and what never leaves your machine, in one page.

Every number, traced. No black box, no guesswork, no fees.

Your broker app tells you what you own. Your advisor charges you to tell you what to do about it. FactFolio is neither — it's a free, open-source, locally-run multi-agent advisory system for Indian equity and mutual fund portfolios that shows its work: BUY / SELL / HOLD / TRIM calls, checked against an explicit investment policy, with every single number traceable back to the exact tool call that produced it.

It never sends your holdings anywhere. It never predicts the future. And it never asks you to trust a number it can't show you the receipt for.

uvx factfolio init               # creates ./factfolio/, prints how to use it
cd factfolio
uvx factfolio report             # → reports/, a full multi-agent portfolio review

No clone, no virtualenv to manage — uv downloads and runs it. Prefer a single file with no Python at all? Grab a standalone executable for your OS from the latest release instead — see Installing below for both paths, including what each one still needs (a claude login, either way — see Authentication).


Why FactFolio

🔍 Fully auditable, by design. Every recommendation the system produces is checked, before you ever see it, by a code-level gate that rejects any claim citing a number not present in that run's actual tool-call log. Not "the model promises to double-check itself" — an independent validator that reads the audit trail directly. If a number's in the report, it's in the log.

🧮 The LLM never computes a number. Weights, returns, tax, correlations, risk — all deterministic Python, same result every time, regardless of what any model feels like saying that day. Agents only reason and call tools; they never do arithmetic.

🤖 Seven specialist agents, not one generalist. A market-analyst, portfolio-auditor, stock-researcher, mf-analyst, tax-strategist, and risk-officer each analyse your portfolio from their own angle — then a devils-advocate agent adversarially reviews every finding before it's allowed into the report.

🔒 Your portfolio never leaves your machine. Holdings, values, and quantities stay local, always — market data providers see ticker symbols only, nothing more. No account to create, no cloud upload, no third party ever sees what you own or what it's worth.

🇮🇳 Built for Indian portfolios specifically. Zerodha CSV import out of the box, STCG/LTCG tax-impact modelling under Indian rules, core-satellite and concentration (HHI) checks, and correlation/overlap analysis across equity and mutual funds together.

📈 No forecasts, no predictions, ever. No tool in this system outputs a price target or a buy/sell prediction. It hands you evidence — analyst consensus, moving-average trend, screener ratios, correlation graphs — and lets a policy and a panel of agents reason about it in the open. What you do with it is still your call, on purpose.

💸 Free. Forever. Yours to run. MIT-licensed, no subscription, no freemium tier, no "upgrade to see the real recommendation." Clone it, run it on your own machine, read every line that touches your money.


Installing

Three ways to get it, in order of how much you want on your machine:

1. uvx / pip — no clone, no dependency management (recommended).

uvx factfolio init          # runs it straight from PyPI, nothing installed persistently
# or: pip install factfolio && factfolio init

init creates a factfolio/ project folder under wherever you ran it — memory, holdings, reports, your own tickers.yaml, everything for this portfolio lives there — and prints the exact cd command plus what to do next. In an interactive terminal it also asks 4 quick questions (target CAGR, risk appetite, horizon, monthly capital) to seed a real starter investment_policy.md instead of pure placeholders — plain text either way, so edit it again anytime your numbers change. Run every other command from inside the folder it creates. Re-running init is always safe: from inside an existing project it just refreshes in place, and it never overwrites an unrelated folder that happens to already be named factfolio (it asks first, or creates factfolio-2 non-interactively).

2. Standalone executable — no Python at all. Download factfolio (or factfolio.exe on Windows) for your OS from the latest release, make it executable, run it:

chmod +x factfolio-macos-arm64 && ./factfolio-macos-arm64 init

Single file, every dependency baked in (~130MB) — nothing else to install. Still needs the claude CLI separately for report/chat — see Authentication; no packaging choice removes that.

Your OS will warn you before running it. These builds aren't code-signed (a paid certificate per platform, ~$70–400/yr Windows, $99/yr Apple — not in place yet), so this is expected, not a sign anything's wrong:

  • macOS: "Apple could not verify … is free of malware" — the dependable fix is Terminal, since a right-click→Open bypass often isn't even offered for this on current macOS:
    xattr -d com.apple.quarantine ./factfolio-macos-arm64
    
    then run it as above. (GUI alternative: System Settings → Privacy & Security → Open Anyway, after one blocked attempt.)
  • Windows: SmartScreen — click More info, then Run anyway.
  • Linux: no equivalent gate — chmod +x above is normally all you need. (A file manager may prompt to "trust" it on double-click; running from a terminal, as shown, skips that.)

Full explanation and the uvx alternative that sidesteps this entirely: wiki FAQ.

3. Clone + dev setup — for contributing or reading/customising the code.

uv venv --python 3.12
uv sync --extra dev
uv run factfolio init      # creates factfolio/ inside the checkout — your data, not the code
cd factfolio

Note: always use uv run … here. The python3 on your PATH is a different interpreter without these dependencies. The CLI command is factfolio (the underlying Python package is mybroker for historical reasons — both uv run factfolio ... and uv run mybroker ... run the identical CLI). uv run still works after the cd — it resolves the checkout via its own project markers, not the current directory.

Whichever you pick, the day-to-day commands below are identical — swap uv run factfolio for uvx factfolio, factfolio (pip-installed), or ./factfolio-<platform> (the executable) as needed.

Full walkthrough — adding your holdings, mapping tickers, customising the policy — in docs/USER_GUIDE.md. Cutting a release yourself (versioning, PyPI, the executables above): docs/RELEASING.md.

Authentication

factfolio report and factfolio chat call the Claude Agent SDK, which shells out to the claude CLI and lets it resolve credentials — this project never sets an API key itself. That means:

  • Default: your local claude login session. If you're already logged in (claude in a terminal, Pro/Max or Console), no setup is needed — every LLM-calling command here just works.
  • Override: export ANTHROPIC_API_KEY=.... Set it and it takes precedence automatically — useful for a different billing account, CI, or a machine with no interactive login.

Every command that calls the LLM prints which one is active (auth: local claude login session / auth: ANTHROPIC_API_KEY (env var override)) so it's never ambiguous which credential a run used. factfolio status/validate/cron/estimate-dates need neither — they're pure deterministic Python.

Usage

FactFolio is a terminal tool, full stop — no browser, no GUI, identical output on macOS/Linux/Windows. report writes the full markdown review to reports/ and prints every recommendation as a table right in your terminal — symbol, action, conviction, and the reasoning behind it — not a wall of text you have to go find it in.

uv run validate-tickers        # must pass before any agent run
uv run pytest                  # verify the maths
uv run factfolio status        # deterministic snapshot — no LLM, instant
uv run factfolio report        # full multi-agent review → reports/, table in your terminal
uv run factfolio chat          # terminal Q&A REPL, one agent
uv run factfolio mcp           # run as an MCP server for other tools/agents (VS Code, Claude Desktop, ...)
uv run factfolio cron          # grade past recommendations — no LLM
uv run factfolio estimate-dates  # tentative purchase-date estimation — no LLM

Integrating with other tools (factfolio mcp)

factfolio mcp runs as a standalone MCP server over stdio — point any MCP-aware client at it (the VS Code Claude extension, Claude Desktop, another agent) the same way you'd point it at any other local MCP server, and it can call portfolio_status, validate_tickers, and run_portfolio_review directly. Same engine, same gate, same ledger as the CLI — just structured output instead of a formatted table.

Holdings input

Drop the standard Zerodha holdings.csv (and optionally holdings_mf.csv) at the project root as before, or drop any broker export — csv, xls, xlsx, pdf, or txt, equity or mutual fund, any filename — into holdings_inbox/. Each file is sniffed and classified automatically; factfolio status / report merge everything found there with the root files.

Unattended grading (factfolio cron)

factfolio cron grades recommendations past their review date against a live price and writes the outcome back to the ledger — pure Python, no LLM call, safe on a schedule. Wire it into cron or launchd, e.g.:

0 9 * * *  cd /path/to/factfolio && uv run factfolio cron >> logs/cron.out 2>&1

Purchase dates

No purchase dates come from the broker exports, so every tax figure defaults to the conservative "assumed short-term" case. factfolio estimate-dates makes a tentative, clearly-labelled estimate instead: for each holding it searches that symbol's own price history, backward from today, for the most recent close near its avg_cost, and saves the result to memory/estimated_purchase_dates.{json,md}. compute_tax_impact uses a confident estimate as a fallback when a sale doesn't supply an explicit purchase date — always flagged purchase_date_source: "estimated" in the response, never presented as verified. This is not a substitute for your actual contract notes — see the note on every estimate for why.

Extra evidence tools

get_analyst_consensus (analyst price targets/rating, 50/200-DMA trend position, via yfinance) and get_screener_ratios (bank Gross/Net NPA %, shareholding pattern, a second independent read on P/E/ROE/ROCE, via a best-effort screener.in scrape — no official API exists) give the agent more evidence to reason with. Neither is a predictor: no tool in this system outputs a buy/sell verdict or a price forecast — see Why FactFolio above.

Privacy

holdings.csv, holdings_inbox/, memory/, reports/, and logs/ are gitignored and never leave the machine. Market data providers (yfinance, screener.in) receive ticker symbols only — never quantities or values. screener.in has no official API; get_screener_ratios scrapes its public company pages (permitted by their robots.txt) and is rate-limited and cached like every other provider.

Documentation

Contributing

FactFolio is free and open source (MIT — see LICENSE) for anyone in India to use, study, or build on. Issues and pull requests are welcome — uv run pytest and uv run ruff check src/ tests/ should both pass clean before opening one; every PR runs the same checks in CI (.github/workflows/ci.yml) and needs a green build before it can merge. Merging itself is maintainer-only — see CONTRIBUTING.md for the full policy and CONTRIBUTORS.md for who that is. If FactFolio is useful to you, a ⭐ on the repo helps other investors find it.

Professional services

FactFolio does deterministic analysis and gives you the evidence — it deliberately doesn't forecast, and it isn't a substitute for a professional who can go deeper than a general-purpose tool can. If you want hands-on deep analysis, market-trend research, or data-driven forecasting for your specific portfolio, you can reach out to Pankaj Negi for professional services: linkedin.com/in/pankajads.

Disclaimer

FactFolio is an educational and personal-use tool, not investment advice. It is not a substitute for a SEBI-registered investment adviser. Nothing it outputs — a recommendation, a tax figure, an estimated purchase date, a piece of "evidence" — is a guarantee of accuracy or of future performance, and every figure should be independently verified before you act on it. Provided as-is, with no warranty, per the MIT license. Market data is sourced from third parties (yfinance, screener.in) that this project does not control and cannot vouch for.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

factfolio-0.3.0.tar.gz (439.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

factfolio-0.3.0-py3-none-any.whl (114.6 kB view details)

Uploaded Python 3

File details

Details for the file factfolio-0.3.0.tar.gz.

File metadata

  • Download URL: factfolio-0.3.0.tar.gz
  • Upload date:
  • Size: 439.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for factfolio-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f41ea45444401a837e26bfb6db080f9f6389e8e246030593f8d6aac93c3c10d5
MD5 900bfdc7be22e42192be444c58798355
BLAKE2b-256 4387f1507e9ca5ca0b7d8b8830695885905c7f7c7154e28b2fdc80c7ac319738

See more details on using hashes here.

Provenance

The following attestation bundles were made for factfolio-0.3.0.tar.gz:

Publisher: release.yml on pankajads/factfolio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file factfolio-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: factfolio-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 114.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for factfolio-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6599264fb91f76a725dbebe2f4b6b1d7ca614ae5e8a14e040ea6b1db46df0e35
MD5 3b1a90d385dc13fcf0205ce30730260d
BLAKE2b-256 209b7d2fe5867f3196317b928b52555dc9573c6fe2db9177d1ee28b2da17e438

See more details on using hashes here.

Provenance

The following attestation bundles were made for factfolio-0.3.0-py3-none-any.whl:

Publisher: release.yml on pankajads/factfolio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.5.0

2 files

0.4.1

2 files

0.4.0

2 files

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page