Skip to main content
ClaudeWave
disin7c9 avatar
disin7c9

asset-management

View on GitHub

Drawdown-first portfolio tool with a read-only MCP addon for Claude — a deterministic core computes every number; the AI is fenced out of arithmetic.

MCP ServersOfficial Registry1 stars0 forksPythonAGPL-3.0Updated today
Install in Claude Code / Claude Desktop
Method: UVX (Python) · --from
Claude Code CLI
claude mcp add asset-management -- uvx --from
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "asset-management": {
      "command": "uvx",
      "args": ["--from"],
      "env": {
        "TIINGO_API_KEY": "<tiingo_api_key>"
      }
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
Detected environment variables
TIINGO_API_KEY
Use cases

MCP Servers overview

# asset-management

[![gate](https://github.com/disin7c9/asset-management/actions/workflows/ci.yml/badge.svg)](https://github.com/disin7c9/asset-management/actions/workflows/ci.yml) [![asset-management MCP server](https://glama.ai/mcp/servers/disin7c9/asset-management/badges/score.svg)](https://glama.ai/mcp/servers/disin7c9/asset-management)

**TL;DR:** `uvx --from git+https://github.com/disin7c9/asset-management asset-management --demo` — a drawdown-first portfolio brief on a bundled example book, one command, no setup. USD-only, long-only stock/ETF; you keep your own transaction log.

**Track a personal stock/ETF portfolio and get suggestions you can audit. Python computes every number; the optional AI narrates — and is structurally unable to write a figure of its own.**

## 🔢 The number fence

Many AI finance tools let the model produce the numbers. Here the model may only place `{{token}}` placeholders: a deterministic renderer substitutes figures from the validated core and **refuses the entire narration if the model typed even one digit itself**:

```text
 the model wrote                             │  the reader gets
─────────────────────────────────────────────┼─────────────────────────────────────────────
 "Your deepest stretch fell                  │  "Your deepest stretch fell -9.84% from
  {{max_drawdown}} from its peak, and an     │   its peak, and an ulcer index of 2.38%
  ulcer index of {{ulcer}} says the ride     │   says the ride stayed shallow."
  stayed shallow."                           │  ✔ every figure substituted from the
                                             │    validated core
─────────────────────────────────────────────┼─────────────────────────────────────────────
 "Your portfolio fell 12% but recovered      │  (no summary at all)
  nicely — don't worry."                     │  ✘ REFUSED — one model-typed digit voids
                                             │    the entire note; the brief prints
                                             │    without it
```

Run both sides yourself — it drives the real production fence, no API key needed: `uv run python scripts/demo_fence.py`

## 🎁 What you get

- A **drawdown-first brief** of your real holdings — how far you fell from your peak, how long underwater, what came back — with a bootstrap confidence band on every sampled risk statistic (returns are accounting identities, so they honestly carry none).
- **Deterministic buy/sell suggestions** toward a target you choose, each line paired to the **named rule** that produced it — you learn the rule rather than trust a bot.
- Optional, fenced **AI narration**, and a read-only **Claude Desktop addon** ("chat with your portfolio") over the same validated core.

Holdings are *derived* from an append-only transaction log (date, ticker, action, quantity, price, fee per row) — never stored — so the same input always produces the same output. Prices are fetched with a provider fallback (Yahoo Finance primary; Tiingo secondary, via a free API key) and an on-disk cache; every displayed number is traceable to its source, and figures that can't be computed honestly (too short a window, no real solution) print `n/a` rather than a fabricated number. **Stock splits are adjusted automatically** (share counts are reconciled with the split-adjusted price history), so a split during your holding period doesn't distort the returns.

## 📑 Contents

- [🚀 Start here](#-start-here)
  - [⚡ Try it in 60 seconds (bundled fake portfolio, no setup)](#-try-it-in-60-seconds-bundled-fake-portfolio-no-setup)
  - [💵 Use it with your own money — four steps](#-use-it-with-your-own-money--four-steps)
- [🔍 Why you can trust the numbers](#-why-you-can-trust-the-numbers)
  - [🚫 Not financial advice — structurally, not as fine print](#-not-financial-advice--structurally-not-as-fine-print)
  - [✅ Correctness is a claim you can check](#-correctness-is-a-claim-you-can-check)
  - [🔬 Validation — reconciled against two independent tools](#-validation--reconciled-against-two-independent-tools)
- [💬 Chat with your portfolio — the Claude Desktop addon (read-only MCP)](#-chat-with-your-portfolio--the-claude-desktop-addon-read-only-mcp)
  - [🛟 If something goes wrong](#-if-something-goes-wrong)
- [📖 Reference](#-reference)
  - [💻 Core brief](#-core-brief)
  - [🔁 Rebalance modes](#-rebalance-modes)
  - [📈 Backtest details](#-backtest-details)
  - [🔭 Discovery & the curated universe](#-discovery--the-curated-universe)
  - [🔍 Screen a candidate](#-screen-a-candidate)
  - [📝 Narration (optional plain-language summary)](#-narration-optional-plain-language-summary)
  - [🔑 Configuration — every key in one place](#-configuration--every-key-in-one-place)
- [🔧 Project](#-project)
  - [🧪 Develop](#-develop)
  - [📁 Layout](#-layout)
- [🔒 Privacy Policy](#-privacy-policy)
- [📜 License](#-license)

## 🚀 Start here

### ⚡ Try it in 60 seconds (bundled fake portfolio, no setup)

```bash
uvx --from git+https://github.com/disin7c9/asset-management asset-management --demo
```

or from a clone: `uv sync && uv run python -m app --demo` (needs Python 3.12 and [uv](https://docs.astral.sh/uv/)).

**The full tour** (still the bundled book, ~a minute online) — the two commands below show the tool's characteristic features end to end: a preset target is *proposed*, then *validated* against a known 60-40 reference with a walk-forward held-out verdict, and threshold-band rebalance suggestions are laid out with the named rule behind every line, plus per-fund facts:

```bash
uvx --from git+https://github.com/disin7c9/asset-management asset-management --demo --allocate moderate --allocate-out demo_target.csv
uvx --from git+https://github.com/disin7c9/asset-management asset-management --demo --backtest --target demo_target.csv --benchmark 60-40 --rebalance bands --metadata
```

Note what it *doesn't* say: the verdict reads like "no clear drawdown difference from 60-40; the paired bootstrap does not confirm the gap" when the evidence is thin — never "beats the benchmark". When the output earns your trust, the four steps below point it at your own money.

### 💵 Use it with your own money — four steps

#### Step 1 — your book (the input)

Everything is derived from one transaction log. The CSV format is **Ghostfolio's own CSV-import schema** (so a book you keep here imports straight into Ghostfolio too) — columns `Date, Code, DataSource, Currency, Price, Quantity, Action, Fee, Note`. `Action` is one of `buy`, `sell`, `dividend`, `fee`, `interest`, `deposit`, `withdraw`. Cash flows (`deposit`/`withdraw`) use a `CASH` code and put the amount in the `Price` column. **This tool is USD-only** (long-only stock/ETF): `Currency` must be `USD` — a non-USD row is refused with an error naming the row, never silently booked as dollars 1:1. Empty cells in numeric columns are treated as zero. Non-ISO dates are rejected with a clear error. UTF-8 BOM is tolerated. The bundled example ([data/sample_data/transactions.csv](data/sample_data/transactions.csv)) shows every row type.

**Already use [Ghostfolio](https://ghostfol.io)?** Point the input straight at a Ghostfolio **JSON** export (Portfolio → Activities → ⋯ → Export) — the loader detects it and reads it directly, no conversion step. It reads the activities (a dividend's cash = `quantity × unitPrice`; Ghostfolio's UTC timestamps are rounded back to your local date) and skips non-USD, crypto, and non-security (`ITEM`/`LIABILITY`) rows with a warning (USD-only, long-only equity/ETF for now). Brokers without a native Ghostfolio account can run a community converter such as [Export-To-Ghostfolio](https://github.com/dickwolff/Export-To-Ghostfolio) (26 brokers → a Ghostfolio JSON) first.

```bash
uv run python -m app --book your.csv                     # or ghostfolio-export.json — auto-detected
uv run python -m app --book your.csv --dry-run           # preview an import BEFORE trusting it:
                                                         # format, events, skipped rows with reasons,
                                                         # derived holdings — fetches nothing
```

**Set your default once** in a gitignored `.env` at the repo root — `ASSET_BOOK=path/to/your.csv` (and optionally `ASSET_TARGET=path/to/target.csv`) — and a bare `python -m app` becomes your brief. Explicit flags always win. There is **no silent built-in default**: without `--book` or `ASSET_BOOK`, a book-dependent action errors out and a bare run prints a hint — the bundled example is opt-in (`--demo`), never assumed.

#### Step 2 — warm the cache (once)

The core is offline-first: prices come from an on-disk cache, refreshed when you run online. After a fresh clone, fill it once:

```bash
uv run python -m app --book your.csv --warm        # your tickers + the benchmark references
uv run python -m app --book your.csv --warm full   # + the ~375-ETF discovery universe (slow) —
                                                   # only needed for offline --discover
```

After that, `--offline` runs and the Claude Desktop addon serve entirely from this cache (`--cache-dir` / `ASSET_CACHE_DIR` override the location).

**Optional but recommended:** add a free [Tiingo](https://www.tiingo.com) API key to `.env` — `TIINGO_API_KEY=...` — to enable the second price source. Yahoo Finance throttles bursts of requests now and then; with a key the fetch falls back to Tiingo instead of reporting tickers missing. Without one, the tool fetches from Yahoo only.

#### Step 3 — choose a target

Most of the decision features (`--rebalance`, `--backtest`, the walk-forward checks) work toward a **target allocation** — a small CSV (`Ticker,Weight`) that *you* own and edit. Three ways to get one, by where you're starting from:

- **You already hold a portfolio** → `--dump-target target.csv` writes your **current** allocation; edit it toward the mix you want. (A target is a *complete spec* — see [Rebalance modes](#-rebalance-modes) for the exit seman
backtestingclaudeclaude-desktopdrawdownetfmcpmodel-context-protocolpersonal-financeportfolio-managementpythonrisk-management

What people ask about asset-management

What is disin7c9/asset-management?

+

disin7c9/asset-management is mcp servers for the Claude AI ecosystem. Drawdown-first portfolio tool with a read-only MCP addon for Claude — a deterministic core computes every number; the AI is fenced out of arithmetic. It has 1 GitHub stars and was last updated today.

How do I install asset-management?

+

You can install asset-management by cloning the repository (https://github.com/disin7c9/asset-management) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is disin7c9/asset-management safe to use?

+

disin7c9/asset-management has not been audited yet by our security agent. Review the original repository on GitHub before using it in production.

Who maintains disin7c9/asset-management?

+

disin7c9/asset-management is maintained by disin7c9. The last recorded GitHub activity is from today, with 0 open issues.

Are there alternatives to asset-management?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy asset-management to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: disin7c9/asset-management
[![Featured on ClaudeWave](https://claudewave.com/api/badge/disin7c9-asset-management)](https://claudewave.com/repo/disin7c9-asset-management)
<a href="https://claudewave.com/repo/disin7c9-asset-management"><img src="https://claudewave.com/api/badge/disin7c9-asset-management" alt="Featured on ClaudeWave: disin7c9/asset-management" width="320" height="64" /></a>

More MCP Servers

asset-management alternatives