investorclaw

SKILL效率
效率 未标注权限 许可证不明确
安装这个技能

Deterministic-first portfolio analyzer — holdings, performance, Sharpe + Sortino, FRED yield curves, bond duration, sector breakdowns, scenario rebalancing — via MCP-HTTP. Backed by ic-engine and clio.

一句话选型结论

按资料字段整理

investorclaw是效率类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类效率 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_15292d5a/yjkj-investorclaw
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

效率
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_15292d5a仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验未标注上游最后核验时间 · 数据更新 1791737062
正文体量44.7 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
整理待办与日程

把零散任务收进清单,排出优先级。

批量处理重复任务

把固定动作做成模板,重复执行。

把流程写成清单

把口头流程整理成可复用的步骤。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在效率场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
investorclaw当前 未标注权限 未标注 未标注 未标注 有
Nano PDF 文档 联网访问 ClawHub 市场 424.9 万 OpenClaw 有
自动更新程序 浏览器控制 ClawHub 市场 296.4 万 OpenClaw 有
Gemini 助手 联网访问 ClawHub 市场 254.7 万 OpenClaw 有
word DOCX 文档 联网访问 ClawHub 市场 239.6 万 OpenClaw 有
Excel XLSX 前端 联网访问 ClawHub 市场 227.0 万 OpenClaw 有

SKILL.md 全文

44.7 KB
模型实际读到的说明书原文,来自技能仓库

<!--
SPDX-License-Identifier: MIT-0
Copyright 2026 InvestorClaw Contributors
-->

InvestorClaw — portfolio analysis skill (v4.7.0)

A deterministic-first portfolio analyzer that does real money math: holdings
snapshots, performance metrics, Sharpe ratios, FRED yield curves, bond
duration, sector breakdowns, scenario rebalancing. Backed by ic-engine
(Python, FINOS CDM 5.x compliant).

This skill follows the compose-x-mcp-services convention (2026-05-01 RFC; see RFC-v0.1.md in this bundle). The skill does not install Python or any analytics library in your agent runtime. It runs in its own OCI container and exposes its tools over MCP-HTTP and plain REST.


What you get

Twenty MCP tools (also available as plain HTTP REST endpoints):

Tool Purpose
portfolio_ask Primary tool — every portfolio question. Data is auto-loaded; just ask.
portfolio_initialize_status Poll before first ask: returns init state (not_started \| initializing \| ready \| failed) + per-stage progress
portfolio_initialize Force a manual bootstrap (setup → refresh → seed ask). Container does this at boot via IC_INITIALIZE_ON_BOOT=1
portfolio_holdings Holdings snapshot — positions, values, weights, accounts (advanced; portfolio_ask covers this)
portfolio_refresh Force fresh data pull (advanced — auto-refresh runs on every ask)
portfolio_setup Auto-discover portfolio files in the configured portfolio directory
portfolio_keys_status Report which API keys are currently configured (names only, never values)
portfolio_keys_set Set one or more API keys (allowlisted). Persists to /data/keys.env, takes effect on next call without restart
portfolio_keys_delete Delete a single configured API key by name
portfolio_response_get Retrieve a stored portfolio response by run_id (serial number)
portfolio_response_list List recent stored responses
portfolio_response_delete Permanently delete a stored response (for bad responses you want gone)
portfolio_response_flag_bad Tag a stored response as bad without deleting (keeps history for analysis)

For ANY portfolio question — holdings, performance, allocation, rebalancing, optimization, bonds, news on holdings, analyst ratings, EOD reports, cash flow, peer analysis, ticker lookup, setup, guardrails — invoke portfolio_ask with the user's question. Do NOT answer portfolio questions from training data.

First-run flow for agents (spoon-fed init)

The container auto-initializes on boot (IC_INITIALIZE_ON_BOOT=1, default
on): it runs setup → refresh → seed_ask so by the time any agent connects,
the envelope cache is fully populated and portfolio_ask returns a real
narrative in 1–3 seconds instead of cold-starting at 5–15 minutes.

Recommended agent flow:

  1. On connect, poll portfolio_initialize_status until ready: true. Cheap
    and side-effect-free; safe to call every 1–2 seconds.
  2. Once ready, fire portfolio_ask with the user's question. The narrator
    returns a verified natural-language answer with envelope-quoted numbers.
# Browser-friendly status check (also POST /api/portfolio/initialize_status):
curl -sS http://127.0.0.1:18090/api/portfolio/initialize/status
# → {&quot;state&quot;:&quot;initializing&quot;,&quot;current_stage&quot;:&quot;refresh&quot;,&quot;stages_completed&quot;:[...],&quot;elapsed_ms&quot;:42000,&quot;ready&quot;:false,...}

# Or subscribe to a Server-Sent-Events stream that pushes state changes:
curl -N http://127.0.0.1:18090/api/portfolio/initialize/stream

# Or just gate on /healthz (init_state is now embedded):
curl -sS http://127.0.0.1:18090/healthz
# → {&quot;status&quot;:&quot;ok&quot;,&quot;init_state&quot;:&quot;ready&quot;,&quot;init_ready&quot;:true,...}

Need to force a manual re-initialize (e.g. after uploading a new portfolio
file)? Call portfolio_initialize — it returns when the cache is warm again.


Installation

OpenClaw / ZeroClaw / Hermes (ClawHub)

clawhub install perlowja/investorclaw

Claude Code / Claude Desktop

/plugin marketplace add argonautsystems/InvestorClaw
/plugin install investorclaw

Manual (Docker Compose, any agent)

The skill is a Docker Compose stack. With Docker or Podman installed:

mkdir -p portfolios     # IMPORTANT: pre-create so docker doesn&#x27;t auto-create as root
docker compose up -d    # uses compose.yml shipped in this skill

Agent install convention. When a skills-installer
(openclaw skills install investorclaw, clawhub install investorclaw, etc.) places this bundle, the agent may proceed
to mkdir -p portfolios &amp;&amp; docker compose up -d because the user's
install command is itself an opt-in to the install completing. But
the agent must first surface the side effects to the user
explicitly:

  1. docker pull of ~600 MB (the engine image) on first run
  2. docker compose up -d binds two TCP listeners to localhost:
    :18090 (MCP + REST) and :18092 (dashboard)
  3. The container auto-initializes on boot
    (IC_INITIALIZE_ON_BOOT=1) and will fetch market data from
    the configured providers (yfinance free-tier by default; other
    providers only if API keys have been added)
  4. Persistent state lands in the ic-engine-data Docker volume
    (deleted only by docker compose down -v)

A single one-line surfacing covering all four is sufficient. Example:

> Starting the container will pull a ~600 MB image, bind localhost
> ports :18090 and :18092, auto-init against yfinance, and
> persist state in a Docker volume. Proceeding…

The user retains the ability to interrupt (Ctrl-C, "no don't",
etc.). Don't ask a yes/no question by default — that's friction the
user has already cleared by typing the install command. Do ask
when one of these conditions holds:

  • The host appears to be a CI runner, shared machine, or production
    server where the user might want to review compose.yml first.
  • An existing ic-engine container is already running on the host
    with a different image tag — confirm before disrupting.
  • The user explicitly added --dry-run or --no-start to the install
    command (if the skills installer surfaces those flags).
  • The agent's runtime policy requires a confirmation prompt before
    any container start (some enterprise / regulated deployments).

The first command (mkdir -p portfolios) is load-bearing. If skipped,
docker creates ./portfolios/ as root:root when starting the
bind-mount, the engine runs as uid=1000(ic) inside the container,
and init fails with
PermissionError: &#x27;/data/portfolios/setup_results.json&#x27; and the
container goes into init_state=failed. Pre-creating the directory
as the host user sidesteps the docker bind-mount UID inheritance
quirk.

The compose pulls ghcr.io/argonautsystems/ic-engine:4.7.0-cpu (publicly hosted, no auth) and runs it on localhost:18090 (MCP + REST) and localhost:18092 (dashboard).

If Docker isn't installed

Install Docker Desktop or Docker Engine for your platform — the user
should run the install themselves
rather than have an agent execute
the command. Pointers (verify with each OS's current docs at
<https://docs.docker.com/engine/install/> before running):

OS Suggested path
macOS Docker Desktop: <https://docs.docker.com/desktop/install/mac-install/> (Homebrew users: brew install --cask docker)
Debian/Ubuntu Follow the official guide: <https://docs.docker.com/engine/install/debian/> or <https://docs.docker.com/engine/install/ubuntu/>
Fedora/RHEL <https://docs.docker.com/engine/install/fedora/> or <https://docs.docker.com/engine/install/rhel/>
Windows Docker Desktop with WSL2 backend: <https://docs.docker.com/desktop/install/windows-install/>
Podman alternative podman compose up -d is a drop-in replacement once Podman is installed (most distros ship it)

After install, verify with docker --version then run the compose-up
command above.

For agent operators: prefer surfacing these install URLs to the
end user rather than running package-manager install commands directly
through your shell tool. Docker installation typically requires sudo
and adds the user to the docker group — operations that benefit from
explicit user consent.

Wait for ready

until curl -sf http://localhost:18090/healthz &gt; /dev/null 2&gt;&amp;1; do sleep 1; done
echo &quot;ic-engine ready&quot;

The first cold-start takes 5-10 seconds (image extract + Python import). Subsequent restarts are <2s.


First-run experience — what to expect

After docker compose up -d the container goes through an auto-init
sequence (IC_INITIALIZE_ON_BOOT=1) that warms the envelope cache before
your agent talks to it. Expect this timeline on a fresh install:

Phase Time What's happening What you'll see
Image extract 5–30 s First-time pull of ic-engine:4.7.0-cpu (~600 MB) docker compose progress bars
Bridge boot 2–3 s FastMCP server binds :18090, dashboard binds :18092 /healthz returns 200, init_state: not_started
portfolio_setup 1–60 s Auto-discover portfolio files in ./portfolios/ init_state: initializing, current_stage: setup
portfolio_refresh 30–120 s Pull quotes / analyst / news / FRED yields for each symbol init_state: initializing, current_stage: refresh
seed_ask 5–60 s Run a primer ask so the cache is warm init_state: initializing, current_stage: seed_ask
Ready — All sections cached, portfolio_ask returns in 1–3 s init_state: ready, init_ready: true

Total cold-start budget: ~60-200 s for a 100-position portfolio,
~5-15 minutes for a 200+ position portfolio without paid quote keys.
Watch progress via:

curl -sS http://127.0.0.1:18090/api/portfolio/initialize/status | jq
# or stream:
curl -N http://127.0.0.1:18090/api/portfolio/initialize/stream

What InvestorClaw asks of you

The container does not prompt interactively. It surfaces what it
needs through structured responses:

  1. A portfolio file. If ./portfolios/ is empty, every portfolio_ask
    call returns: "No portfolio file found … please add CSV/Excel/PDF
    files to your portfolios directory."
    Drop a broker export from
    Schwab / Fidelity / Vanguard / UBS / ETrade / Robinhood (CSV/XLS/PDF/screenshot)
    into the bind-mounted ./portfolios/ folder, then call
    portfolio_setup to ingest it.

  2. An LLM provider key for narrative synthesis. Without one, the
    engine still runs the deterministic pipeline (numbers are correct)
    but the narrator returns a stub catalog blurb instead of a real
    prose answer. The container ships pre-configured to use Together AI
    (google/gemma-4-31B-it), so all you need is a TOGETHER_API_KEY.
    Set it with:

bash curl -sS -X POST http://127.0.0.1:18090/api/portfolio/keys_set \ -H &#x27;Content-Type: application/json&#x27; \ -d &#x27;{&quot;keys&quot;: {&quot;TOGETHER_API_KEY&quot;: &quot;tgp_v1_...&quot;}}&#x27;

Or drop into the dashboard at http://localhost:18092/ and paste it
into the Settings tab.

  1. Optional: data-provider keys for richer / faster results
    on larger portfolios (see Optional configuration → Which keys to
    obtain (by portfolio size)
    below). The engine works key-less in
    degraded mode (yfinance-only, rate-limited).

What InvestorClaw recommends — by portfolio size

Size Required Recommended Why
≤ 50 symbols TOGETHER_API_KEY (narrative) — yfinance handles quotes/history at this scale; one key covers narrative
50–200 symbols TOGETHER_API_KEY FINNHUB_KEY (free 60/min) + NEWSAPI_KEY (free 100/day) Real-time quotes + analyst + per-symbol news without yfinance throttle
200+ symbols TOGETHER_API_KEY + MASSIVE_API_KEY (Massive, paid) FINNHUB_KEY + MARKETAUX_API_KEY (free 100/day) + FRED_API_KEY (free, registration) + ALPHA_VANTAGE_KEY (free 25/day) Yahoo's anonymous query1 endpoint rate-limits globally on 200+ symbols under barrage; Massive is required, the rest fill analyst + news + yields

Why TOGETHER_API_KEY is the only hard requirement for narrative:

  • Cheapest serverless tier on Together AI (~$0.0008 / 1 K tokens)
  • Default model google/gemma-4-31B-it has good quality for portfolio
    narrative + ~100 tok/s throughput
  • Single key replaces the older multi-tier model setup that v2.x used

Sign-up links (all have free tiers):

Provider URL Free-tier limit
Together AI https://api.together.ai/settings/api-keys $1 free credits
Finnhub https://finnhub.io/register 60 calls/min
Massive https://massive.com/ paid only
MarketAux https://www.marketaux.com/account/dashboard 100 calls/day
NewsAPI https://newsapi.org/register 100 calls/day
FRED https://fred.stlouisfed.org/docs/api/api_key.html unlimited (registration only)
Alpha Vantage https://www.alphavantage.co/support/#api-key 25 calls/day

The TOGETHER_API_KEY is the only one that's genuinely required.
Everything else degrades gracefully.

First call — what your agent will see

Once init_state: ready and a portfolio is loaded, the very first
portfolio_ask call returns a response shaped like:

{
  &quot;exit_code&quot;: 0,
  &quot;narrative&quot;: &quot;I have holdings summary data in the envelope.\n- bond_pct: 26.76\n- bond_value: 705646.57\n- cash_pct: 1.69\n- equity_pct: 71.55\n- equity_value: 1886470.25\nTop holding symbols: MSFT, NVDA, SCHB, GOOG, AAPL, ...&quot;,
  &quot;ic_result&quot;: {
    &quot;hmac&quot;: &quot;75ca79c...&quot;,
    &quot;engine_version&quot;: &quot;2.5.2&quot;,
    &quot;command&quot;: &quot;ask&quot;,
    &quot;run_id&quot;: &quot;299d36b0-...&quot;
  }
}

The narrative field is the agent-facing answer. The ic_result
contains the HMAC signature that proves the response came from the
deterministic engine (not LLM-fabricated).

If you see "is a general finance concept. ic-engine is portfolio-specific"
in the narrative for a question that obviously is about your portfolio,
you're on a pre-v4.1.25 image — pull the latest:

docker compose pull &amp;&amp; docker compose up -d

How to call the tools

Option A: native MCP client (preferred)

If your runtime has a native MCP client, register the server:

URL:       http://127.0.0.1:18090/mcp
Transport: streamable-http
Auth:      none (localhost only)

Per-runtime CLI:

Runtime Command
zeroclaw Add [[mcp.servers]] with name = &quot;ic-engine&quot;, url = &quot;http://127.0.0.1:18090/mcp&quot;, transport = &quot;http&quot; to ~/.zeroclaw/config.toml
openclaw openclaw mcp set ic-engine &#x27;{&quot;url&quot;:&quot;http://127.0.0.1:18090/mcp&quot;,&quot;transport&quot;:&quot;streamable-http&quot;}&#x27;
hermes hermes mcp add ic-engine --url http://127.0.0.1:18090/mcp
claude code Add to ~/.claude/mcp_servers.json per Claude Code docs

Then call tools by name (portfolio_ask, portfolio_holdings, etc.) via your runtime's tool-use API.

Option B: plain HTTP REST (works when MCP integration is flaky)

Equivalent endpoints exist at /api/portfolio/*. Use your runtime's shell or HTTP tool:

# Ask any portfolio question
curl -sS -X POST http://127.0.0.1:18090/api/portfolio/ask \
  -H &#x27;Content-Type: application/json&#x27; \
  -d &#x27;{&quot;question&quot;: &quot;What is in my portfolio?&quot;}&#x27; \
  --max-time 120

# Other endpoints (no body needed)
curl -sS -X POST http://127.0.0.1:18090/api/portfolio/holdings -H &#x27;Content-Type: application/json&#x27; -d &#x27;{}&#x27;
curl -sS -X POST http://127.0.0.1:18090/api/portfolio/refresh  -H &#x27;Content-Type: application/json&#x27; -d &#x27;{}&#x27;
curl -sS -X POST http://127.0.0.1:18090/api/portfolio/setup    -H &#x27;Content-Type: application/json&#x27; -d &#x27;{}&#x27;

# Self-describing tool catalog
curl -sS http://127.0.0.1:18090/api/portfolio/tools

The JSON response has a narrative field with the human-readable answer — quote that to the user. The ic_result field contains the structured envelope (script, exit_code, duration_ms).


What to ask — example queries

Once installed, ask portfolio questions in natural language. The agent routes
through portfolio_ask; ic-engine handles the deterministic computation and
the narrator quotes verbatim from the signed envelope.

Intent Example phrasing
Holdings snapshot "What's in my portfolio?" • "Show me my positions" • "What do I own?"
Performance "How am I doing this year?" • "What's my Sharpe ratio?" • "Show me my drawdowns"
Bonds "Show me my bond exposure and yield-to-maturity" • "What's my bond ladder look like?"
Allocation / risk "What's my sector exposure?" • "How concentrated is my portfolio?" • "What's my risk profile?"
Optimization / rebalancing "Help me rebalance to a 60/40 target" • "Show me an efficient frontier"
Market data "What's the current price of NVDA?" • "How is the S&P performing today?"
Fixed-income concepts "What does yield-to-maturity mean?" • "Explain duration"
News "Today's news on my holdings" • "Crypto news today"
Reports "Generate today's EOD report" • "Prepare a full analysis for my advisor meeting"
Fresh data "Prices moved — refresh before answering" → triggers portfolio_refresh

The first call after a cold cache may take 30–60 seconds while the
deterministic pipeline builds the signed envelope. Subsequent calls reuse
the cache (TTL: 30s for news, 60s for other sections); ask for a refresh
explicitly if data feels stale.


Agent routing rules

These rules apply when an agent has the InvestorClaw skill installed:

Use InvestorClaw — do NOT answer from training data, web search, or browsing — for:
- Any portfolio / holdings / positions question
- Performance, returns, Sharpe/Sortino, drawdown
- Bonds, yield-to-maturity, duration, ladders
- Sector / asset / account allocation
- Optimization, rebalancing, target allocation, scenarios
- Cash flow, dividend / coupon calendars
- Analyst ratings, price targets
- Today's news on holdings or market-wide topics
- Live ticker prices and quotes
- EOD reports, peer comparison, what-changed analysis

Deterministic-first rules:
- Never calculate portfolio metrics in the agent — call the tool.
- Never fabricate market, ticker, bond, portfolio, optimization, or news data.
- Preserve quoted source passages, numbers, dates, timestamps, and freshness
labels exactly.
- If the signed envelope lacks a requested fact, say InvestorClaw did not
provide it and quote the engine's limitation verbatim.
- Use portfolio_refresh only when the user asks for fresh data or when
data appears stale.

Attachment handling:
- When the user attaches a CSV / XLS / XLSX / PDF / screenshot in the same
turn as a portfolio question, stage the file to the bind-mounted
portfolios/ directory, call portfolio_setup, then ask the original
question.
- Do not ask the user to move files manually; the agent owns staging.
- Report low-confidence extraction or setup gaps exactly as InvestorClaw
returns them.

Educational guardrails:
- All output is educational, not investment advice.
- Never present "buy/sell" recommendations as advice.
- Never assess suitability for the user's situation.
- Preserve the engine's disclaimer language verbatim.


Required response format (when answering as an agent)

End every portfolio reply with:

Verification: ic-engine ask completed (exit_code: 0)

(Substitute the actual exit_code from the response.) The harness depends on this exact line.

For finance-concept questions ("what is YTM?") or market-wide questions ("how is the S&P performing?"), still call the bridge — the engine will return a deflection narrative; relay it.


Configure portfolios

Drop your broker exports (CSV, XLS, PDF) into the bind-mounted directory:

# default mount: ./portfolios on the host -&gt; /data/portfolios in the container
mkdir -p portfolios
cp ~/Downloads/UBS_Holdings_2026-05-02.xls portfolios/

# Then ask the agent or curl the setup endpoint
curl -sS -X POST http://127.0.0.1:18090/api/portfolio/setup -H &#x27;Content-Type: application/json&#x27; -d &#x27;{}&#x27;

Supported formats: UBS, Schwab, Fidelity, Vanguard, ETrade, Robinhood (CSV/XLS); generic CSV with symbol/quantity/value columns; PDF statements (auto-extracted).

Broker export instructions

Most major US brokers expose a CSV download of holdings. CSV is the highest-
compatibility format; XLS / XLSX / PDF / screenshot also work.

Broker Path
Schwab Accounts → Positions → Export CSV
Fidelity NetBenefits → Investments → Download CSV
Vanguard My Accounts → Download Holdings
UBS Wealth Management → Holdings → Export
ETrade Portfolio → Holdings → Download
Robinhood Account → Statements → CSV

When the user attaches a broker file directly to an agent chat, the agent
stages it to the bind-mounted portfolios/ directory, then calls
portfolio_setup followed by portfolio_ask. Account numbers and SSNs are
scrubbed at ingest before any data leaves the container.


Optional configuration

The container reads optional env vars from /data/keys.env (host-mounted). All optional — the deterministic-engine works without LLM/news keys, just in degraded mode (no narrative synthesis, no live news).

Which keys to obtain (by portfolio size)

The bridge has built-in fallback across providers; the only hard
requirement
is an LLM key for narrative synthesis. Below that, your
choice depends on portfolio size.

Small (≤50 symbols) — yfinance-only is fine:
- TOGETHER_API_KEY (or any LLM): required for narrative
- That's it. Yahoo Finance handles quotes/history at this scale.

Medium (50–200 symbols) — add Finnhub:
- TOGETHER_API_KEY: LLM narrative
- FINNHUB_KEY: real-time quotes + analyst ratings (60/min, free)
- NEWSAPI_KEY (optional): per-symbol news (100/day free)

Large (200+ symbols) — Massive is required:
- TOGETHER_API_KEY: LLM narrative
- MASSIVE_API_KEY (Massive): paid, un-rate-limited quotes + history + Benzinga news + analyst ratings
- FINNHUB_KEY: analyst ratings + general/forex/crypto/merger news
- MARKETAUX_API_KEY (optional): broader news with category filters
- FRED_API_KEY (optional): Treasury yield curve (Treasury.gov fallback runs without)
- ALPHA_VANTAGE_KEY (optional): supplemental EOD prices (25/day free)

Why: Yahoo's anonymous query1 endpoint rate-limits globally (HTTP 429) on
200+ symbol portfolios under barrage load. Massive handles the
bulk of quotes/history without throttling; Finnhub fills analyst + news;
the no-key Frankfurter (FX) and Treasury Fiscal Data (yields) providers
cover the remainder.

Full key reference

Key Purpose Cost note
TOGETHER_API_KEY LLM narrative synthesis (Together google/gemma-4-31B-it) serverless, fleet default
MASSIVE_API_KEY Massive: quotes + history (200+ symbol portfolios) + Benzinga news + analyst ratings paid, un-rate-limited
FINNHUB_KEY Real-time quotes + analyst ratings + category news 60/min free
MARKETAUX_API_KEY Financial news with broader filters than NewsAPI 100/day free
NEWSAPI_KEY Per-symbol news (US sources only) 100/day free
ALPHA_VANTAGE_KEY Supplemental EOD prices 25/day free
FRED_API_KEY FRED yield curve free, registration required
OPENAI_API_KEY Alternative LLM (GPT-4o, GPT-5) paid

No-key providers (always available)

Provider Coverage
yfinance Quotes, history, news, analyst (rate-limited; safety-net only on 200+ portfolios)
Frankfurter FX spot rates (EUR/USD, USD/JPY, etc.) — ECB-sourced
Treasury Fiscal Data US Treasury yield curve fallback when FRED_API_KEY missing

Configure keys via REST/MCP (preferred — no host shell needed)

The agent can set keys directly via the running container, no /data/keys.env
edit required. Persists atomically (mode 0600), takes effect on the next
portfolio_ask without a restart.

# What&#x27;s configured?
curl -sS -X POST http://127.0.0.1:18090/api/portfolio/keys_status \
  -H &#x27;Content-Type: application/json&#x27; -d &#x27;{}&#x27;
# → {&quot;configured&quot;:[&quot;FINNHUB_KEY&quot;,&quot;NEWSAPI_KEY&quot;], &quot;settable&quot;:[...], &quot;missing&quot;:[...]}

# Set one or more keys
curl -sS -X POST http://127.0.0.1:18090/api/portfolio/keys_set \
  -H &#x27;Content-Type: application/json&#x27; \
  -d &#x27;{&quot;keys&quot;: {&quot;TOGETHER_API_KEY&quot;: &quot;tgp_v1_...&quot;, &quot;FRED_API_KEY&quot;: &quot;...&quot;}}&#x27;
# → {&quot;configured&quot;:[&quot;FRED_API_KEY&quot;,&quot;TOGETHER_API_KEY&quot;], &quot;rejected&quot;:[], &quot;deleted&quot;:[]}

# Remove a key
curl -sS -X POST http://127.0.0.1:18090/api/portfolio/keys_delete \
  -H &#x27;Content-Type: application/json&#x27; -d &#x27;{&quot;name&quot;: &quot;OPENAI_API_KEY&quot;}&#x27;

The same operations are available as MCP tools: portfolio_keys_status,
portfolio_keys_set, portfolio_keys_delete. Only the standard ic-engine
key names are accepted; arbitrary names are rejected with a structured
{&quot;rejected&quot;: [...], &quot;settable&quot;: [...]} response.

Configure keys via host file (alternative)

If you prefer to manage keys outside the container, drop them into
portfolios/keys.env on the host (the bind-mounted location), one
KEY=VALUE per line:

TOGETHER_API_KEY=tgp_v1_...
FINNHUB_KEY=...
NEWSAPI_KEY=...

The container reads from /data/keys.env at boot.


Model recommendations

InvestorClaw uses two LLM roles when answering: narrative (synthesizes
the signed envelope into prose) and validator (checks the narrative
against the envelope for fabrication and number-preservation). The
recommended model mix depends on your runtime.

Claude Code / Claude Desktop

The agent's own LLM does both roles — no external API key required.

  • Narrative: Haiku 4.5 — fast, cheap, ~10× lower output cost than
    Sonnet. Synthesis with a clean envelope is mostly transcription, so the
    cheap model is sufficient.
  • Validator: Sonnet 4.6 (default) or Opus 4.7 (escalation) — gates the
    Haiku output for fabrication, mis-quoted numbers, and training-leak
    drift. Validator output is short (~1 K tokens) so the smart-model bill
    stays low.

This split is cost-shaped: cheap model on the long output, smart model on
the short safety check. Total session cost on a 100-position portfolio
typically lands well under $0.01.

openclaw / zeroclaw / hermes

Anthropic on the claws stack — three paths, two of them paid:
since 2026-04-04 your Anthropic OAuth subscription no longer covers
third-party-tool usage. To use Anthropic models on a claws-agent
runtime you need either (a) Anthropic's discounted "extra usage
bundles" added to your subscription, or (b) a direct Anthropic API
key. Routing OAuth-subscription tokens to a claws-agent without one of
those is a ToS violation per Anthropic's Apr 3 announcement.

Even with paid credits, Anthropic isn't cost-competitive with Together
for InvestorClaw narrative synthesis (~10–50× the per-token cost).
On our own fleet infrastructure we don't deploy Anthropic for these
runtimes
; end-users should weigh ToS, cost, and quality before
opting into it.

Bring a non-Anthropic provider via TOGETHER_API_KEY (or equivalent).
Fleet defaults:

  • Default narrative: Together AI google/gemma-4-31B-it — serverless
    tier, ~100 tok/s, ~$0.0008 / 1 K tokens, ships as the container default.
  • Higher-quality alternative: Together AI MiniMaxAI/MiniMax-M2 —
    larger context, but moved off Together's serverless tier in 2026-05
    and now requires a paid dedicated endpoint. Use only if you've
    provisioned that endpoint.
  • Local-only / offline: Ollama gemma4:e4b on host — zero cloud cost,
    GPU-bound, no key required.

To switch the narrative model, set INVESTORCLAW_NARRATIVE_MODEL in
portfolios/keys.env (e.g. INVESTORCLAW_NARRATIVE_MODEL=MiniMaxAI/MiniMax-M2
once you have a dedicated endpoint configured at Together).
The container reads it on next call without restart.


Data privacy

Stays on your machine:
- Raw broker exports (CSV / XLS / PDF) in portfolios/
- Account numbers and SSNs (scrubbed at ingest)
- Full position details (lot history, cost basis)
- Python computation internals (intermediate calculations)

Sent to the configured LLM provider for narrative synthesis:
- The user's question
- The HMAC-signed JSON envelope produced by ic-engine
- Computed metrics needed for presentation

Never sent anywhere:
- Raw PII (account numbers, SSNs, names)
- Pre-computation intermediate state
- Other portfolios on the same disk

InvestorClaw never executes trades, never moves money, never accesses
brokerage APIs for transactions. Output is educational only.


Verify install + compliance

# Health check
curl -sS http://127.0.0.1:18090/healthz
# → {&quot;status&quot;:&quot;ok&quot;,&quot;ic_engine_bin_found&quot;:true,&quot;portfolio_dir&quot;:&quot;/data/portfolios&quot;,&quot;portfolio_dir_exists&quot;:true,&quot;reports_dir&quot;:&quot;/data/reports&quot;}

# Smoke test the tool catalog
curl -sS http://127.0.0.1:18090/api/portfolio/tools | python3 -m json.tool

# Smoke test a real question
curl -sS -X POST http://127.0.0.1:18090/api/portfolio/ask \
  -H &#x27;Content-Type: application/json&#x27; \
  -d &#x27;{&quot;question&quot;: &quot;What is in my portfolio?&quot;}&#x27; \
  --max-time 120

If your agent supports compliance testing, vendor test_mcp_compliance.py
from the mnemos-os/mcp-contracts GitHub repository into your project, then run:

python3 test_mcp_compliance.py --url http://127.0.0.1:18090/mcp

Dashboard

The container exposes a single-page HTML dashboard on port :18092:

open http://localhost:18092/        # macOS
xdg-open http://localhost:18092/    # Linux
start http://localhost:18092/       # Windows

Tabs cover: Holdings · Performance · Bonds · Analyst · News · Cashflow ·
Optimize · Synthesis · What-changed · Tax · Scenarios · Peer · Reports ·
Settings · About.

The dashboard reads the same signed envelope ic-engine produces for
portfolio_ask, so metrics stay in sync. Use it for visual review of
holdings / performance, or as a fallback interface when MCP integration
is flaky.


Troubleshooting

Container won't start

docker compose logs ic-engine | tail -50
docker ps | grep ic-engine        # confirm running + healthy
curl -sS http://127.0.0.1:18090/healthz

If healthz returns {&quot;init_state&quot;:&quot;failed&quot;, ...}, check the init_error
field for the engine's exact failure message.

"No portfolio found" when asking

  • Drop a CSV / XLS / PDF into portfolios/ (the host bind mount).
  • Then call setup:
    curl -X POST http://127.0.0.1:18090/api/portfolio/setup -d &#x27;{}&#x27;
  • Then ask again:
    curl -X POST http://127.0.0.1:18090/api/portfolio/ask -d &#x27;{&quot;question&quot;:&quot;what&#x27;s in my portfolio?&quot;}&#x27;

The agent can stage attached files to portfolios/ directly when the user
sends them in chat.

"API key errors" / degraded data

Keys are optional. The deterministic-engine works key-less in degraded
mode (no narrative synthesis, no live news, yfinance-only quotes). To
check what's configured:

curl -X POST http://127.0.0.1:18090/api/portfolio/keys_status -d &#x27;{}&#x27;

Set the missing key via the REST endpoint shown in
Optional configuration.

"First call is slow (5–15 minutes)"

Only happens on a cold cache for portfolios with 200+ positions. The
container runs IC_INITIALIZE_ON_BOOT=1 by default — initialization runs
at container start, so by the time the agent connects, the cache is warm.
If you disabled that env var, expect cold-start latency on first ask.

Check init progress: curl http://127.0.0.1:18090/api/portfolio/initialize/status

"Container is healthy but portfolio_ask times out"

  • Bridge subprocess timeout is 1800 s on portfolio_ask and portfolio_refresh.
  • Engine P1 parallel-stage timeout is 600 s.
  • If you hit either, the engine ran out of upstream API budget (yfinance
    429, Finnhub rate limit, etc.). Switch to Massive (MASSIVE_API_KEY)
    for large portfolios; see "Which keys to obtain (by portfolio size)".

Reset cache + state

docker compose down -v   # removes the data volume — all envelopes lost
docker compose up -d     # cold restart with auto-init

Upgrading

The container is meant to be replaced wholesale on each release. There
are two flows depending on whether the new container reuses the same
/data volume — same-host (the common case, zero re-entry) and
cross-host (use the encrypted backup file).

Check for a new version

curl -s -X POST http://localhost:18090/api/portfolio/version_check | jq
{
  &quot;running&quot;: &quot;4.4.2&quot;,
  &quot;latest&quot;: &quot;4.7.0&quot;,
  &quot;upgrade_available&quot;: true,
  &quot;next_steps&quot;: [...]
}

Same call is exposed as MCP tool portfolio_version_check. Network
failures return latest: null + a warning rather than 5xx — version
check is advisory.


Same-host upgrade (default)

When the new container reuses the same /data volume mount, every
piece of user state — portfolio CSVs, keys.env, stonkmode persona,
section reports — survives automatically. You don't need to export
anything.

# 1. Optional defensive snapshot (portfolios + stonkmode only — see below)
curl -s -X POST http://localhost:18090/api/portfolio/export &gt; snap.json

# 2. Pull + replace (host-shell — agents tell the user, don&#x27;t execute)
docker compose pull
docker compose up -d
# Or for podman + systemd quadlet (NCZ pi-gen layout):
#   sudo podman pull ghcr.io/argonautsystems/ic-engine:latest
#   sudo systemctl restart ic-engine.service

# 3. Wait for init=ready
until curl -s http://localhost:18090/healthz | jq -e &#x27;.init_ready&#x27; &gt; /dev/null; do
  sleep 5
done

That's the whole flow. Keys persist because /data/keys.env is on the
volume; the new container reads the same file at boot.


Cross-host migration (or volume-was-wiped)

When the new host has a fresh volume, you need to move both the
user data (portfolios + stonkmode) and the API keys between
hosts. They have different security postures and are handled by
different tools:

  • portfolio_export / portfolio_import → user data. Plain JSON;
    excludes key values by design.
  • portfolio_keys_backup / portfolio_keys_restore → API keys.
    Passphrase-encrypted (scrypt + AES-256-GCM); the encrypted blob is
    safe to scp/email/clipboard.

Recommended at install time. Right after configuring your API
keys, create your first encrypted backup:

curl -s -X POST http://localhost:18090/api/portfolio/keys_backup \
  -H &quot;Content-Type: application/json&quot; \
  -d &#x27;{&quot;passphrase&quot;: &quot;your strong passphrase here&quot;, &quot;label&quot;: &quot;initial&quot;}&#x27;
{
  &quot;path&quot;: &quot;/data/backups/keys-2026-05-07T01-30-00Z-initial.bak&quot;,
  &quot;filename&quot;: &quot;keys-2026-05-07T01-30-00Z-initial.bak&quot;,
  &quot;size_bytes&quot;: 612,
  &quot;key_names&quot;: [&quot;TOGETHER_API_KEY&quot;, &quot;FRED_API_KEY&quot;, &quot;MASSIVE_API_KEY&quot;],
  &quot;kdf&quot;: &quot;scrypt-N32768-r8-p1&quot;
}

Save the file off-host (scp, USB, password manager attachment) and
store the passphrase somewhere durable — without it the backup
is permanently unrecoverable. That's by design: it's the same posture
as a password-manager export.

Migrating to a new host

On the source host:

# 1. Snapshot user data
curl -s -X POST http://localhost:18090/api/portfolio/export &gt; snap.json

# 2. Encrypt + back up keys (or use an existing backup)
curl -s -X POST http://localhost:18090/api/portfolio/keys_backup \
  -d &#x27;{&quot;passphrase&quot;: &quot;...&quot;}&#x27;
# → {&quot;path&quot;: &quot;/data/backups/keys-….bak&quot;, ...}

# 3. Copy both files off-host
scp dest:/tmp/snap.json snap.json
scp /var/lib/docker/volumes/ic-engine-data/_data/backups/keys-….bak \
    user@dest:/tmp/

On the destination host (after docker compose up -d brings up a
fresh container):

# 1. Restore user data (portfolios + stonkmode)
curl -s -X POST http://localhost:18090/api/portfolio/import \
  -H &quot;Content-Type: application/json&quot; \
  -d &quot;{\&quot;snapshot\&quot;: $(cat /tmp/snap.json)}&quot;

# 2. Place the encrypted backup file under /data/backups/, then restore
docker cp /tmp/keys-….bak ic-engine:/data/backups/
curl -s -X POST http://localhost:18090/api/portfolio/keys_restore \
  -H &quot;Content-Type: application/json&quot; \
  -d &#x27;{&quot;passphrase&quot;: &quot;...&quot;}&#x27;
# (no backup_path → auto-picks the most-recent .bak file)

When you don't have shell access on both hosts

Fall back to prompted key re-entry. The portfolio_import
response includes configured_keys_in_snapshot — the list of key
names that were set on the source host. The agent walks the user
through each one:

Agent: &quot;Your snapshot was set up with these keys: TOGETHER_API_KEY,
        FRED_API_KEY, MASSIVE_API_KEY. They aren&#x27;t in the snapshot for
        security. Paste each one and I&#x27;ll set it.&quot;
User:  pastes TOGETHER_API_KEY
Agent: portfolio_keys_set({&quot;keys&quot;: {&quot;TOGETHER_API_KEY&quot;: &quot;...&quot;}})
       (and so on)

This is intentionally manual — the user types each secret once, into
the agent, which round-trips to keys_set. Auditable. For larger key
sets, the encrypted-backup path above is friction-free in comparison.


Listing existing backups

curl -s -X POST http://localhost:18090/api/portfolio/keys_backups_list | jq

Returns metadata (filename, size, mtime, KDF) for each keys-*.bak
under /data/backups/. No passphrase required — listing only
returns metadata, not contents.

Threat model & where the passphrase appears

The backup tool is encrypted because the file is meant to LEAVE the
host (scp, email, USB, cloud sync). Plaintext keys never leave /data
— only the encrypted blob.

Where the passphrase is exposed:

  • It passes through the tool-call args (so it's in the agent's
    conversation history once at backup time and once at restore time).
    For maximum secrecy, invoke from the dashboard browser — keeps the
    passphrase out of LLM provider context entirely. Or use curl
    directly on the host.

  • It is NEVER persisted by the bridge. Each backup/restore call
    derives the encryption key fresh via scrypt; the passphrase doesn't
    leave Python's local scope.

Out of scope: keylogging on the user's terminal; rubber-hose
attack; weak-passphrase guessing (we enforce min length 12 to
discourage trivial passphrases).

Agent-driven upgrade flow (single-shot script)

User:  &quot;Check for upgrades.&quot;
Agent: portfolio_version_check → &quot;v4.7.0 available; you&#x27;re on v4.4.2&quot;
User:  &quot;Upgrade me.&quot;
Agent: 1. portfolio_export → save snap.json
       2. (if new host) portfolio_keys_backup with user-supplied passphrase
       3. surface the host-shell pull+restart commands to the user
       4. poll /healthz until init_ready
       5. portfolio_version_check (running == latest? confirm)
       6. iff /data was lost: portfolio_import + portfolio_keys_restore
          (or prompted re-entry via portfolio_keys_set)

The agent never executes host-shell commands itself. Surface them
clearly and let the user run them.


Stop / uninstall

# Stop (preserves data)
docker compose down

# Stop and remove the data volume
docker compose down -v

Security model

InvestorClaw is a single-user, localhost-bound, deterministic-first
analyzer. Several behaviors that automated scanners flag as "warning"
are intentional design choices for this threat model. Documented here
explicitly so reviewers can audit the trade-offs:

Behavior Why it's by design
MCP + REST endpoints are unauthenticated on 127.0.0.1:18090 Localhost binding (127.0.0.1: prefix on the port spec, never 0.0.0.0) is the security boundary. Any process running as the same user already has filesystem access to portfolios; adding token auth on a loopback API doesn't change that threat model. To expose the service to other hosts, put it behind your own auth layer (Tailscale, nginx + mTLS).
Container auto-initializes on boot (IC_INITIALIZE_ON_BOOT=1) The cold-cache cost on a 200+ position portfolio is 5–15 minutes; running setup → refresh → seed_ask at boot means agents see init_state: ready immediately on connect. Disable with IC_INITIALIZE_ON_BOOT=0 if you want manual control. The init does not exfiltrate data — it just primes the engine's read-only cache against the providers you've configured.
API keys persist to /data/keys.env (mode 0600) Keys need to outlive container restarts. The named volume is ic-engine-data; on the host that's a docker volume root-owned but only readable by the container's uid=1000(ic). To rotate or delete a key, use portfolio_keys_set / portfolio_keys_delete — both REST endpoints accept allowlisted names only, never logging values.
Portfolio summaries are sent to the configured narrative LLM provider This is the value prop: the engine produces a deterministic envelope, the narrator turns it into prose. To keep narratives local, point INVESTORCLAW_NARRATIVE_ENDPOINT at a local Ollama / llama-server / vLLM endpoint (set INVESTORCLAW_NARRATIVE_PROVIDER=ollama). To run keyless without any narrator, omit TOGETHER_API_KEY — the engine returns a stub catalog summary instead. See PRIVACY.md for the full data-flow matrix.
Image pulled from ghcr.io/argonautsystems/ic-engine Pinned to a specific sha256 digest in compose.yml, not just the tag — guarantees reproducible builds even if the tag is later mutated. Verify the digest matches what your scanner expects before deploying. Container Apache 2.0 + bridge code MIT-0 in this repo; engine source at argonautsystems/ic-engine (pinned by SHA).

For vulnerability disclosure see SECURITY.md. For the
privacy model (what stays local vs what goes to which provider) see
PRIVACY.md.

Behavior contract

  • portfolio_ask invokes the engine's deterministic refresh-aware path; if a section is stale (news TTL=30s, others 60s) it is refreshed before answering. Earlier --no-refresh short-circuited routing entirely and produced a generic catalog blurb — that flag is intentionally NOT passed.
  • The container clears yfinance cookies on subprocess timeout, breaking the rate-limit cascade documented in commit 50387b1 of ncz-os/mnemos-ic-runtime.
  • Cross-container reach works via http://172.17.0.1:18090/mcp (Docker bridge IP) or via Compose service name http://ic-engine:8090/mcp (when both agent + ic-engine are in the same compose).

Known issues (v4.1.1)

  • Earlier "v4.0.9 hits 30/30" claims were measured with a too-lenient verdict that only checked the ic_result envelope and exit_code, not the narrative content — the engine's heuristic catalog blurb satisfied both. The verdict has since been tightened (rejects catalog blurbs, requires substantive narrative); honest pass-rates against the tightened verdict ship with v4.1.1 release notes.
  • Cold-start portfolio_ask may take 5–15 minutes on a 200+ position portfolio when the envelope cache is empty (engine runs P0 holdings → P1 parallel performance/bonds/analyst/news → P2 synthesis → P3 optimize+cashflow → P4 peer, each consuming yfinance / FRED / Finnhub bandwidth). Subsequent calls hit the warm cache and return in seconds. Bridge subprocess timeout is 1800s for portfolio_ask and portfolio_refresh; engine P1 parallel-stage timeout is 600s.

Fixed in v4.1.1 (was broken in v4.0.x → v4.1.0)

  • Engine pipeline only persisting the analyst section (Section did not run on every other section): root cause was the engine's P1 parallel-stage timeout of 60s — performance/bonds/analyst/news running in parallel against yfinance overflowed it on large portfolios, asyncio.gather raised TimeoutError, the entire P1 result set was lost. Bumped to 600s.
  • Narrator falling through to a heuristic catalog blurb for every portfolio_ask: chain of five bugs — litellm stripped from the container; narrator wrapped the LLM call in a bare try/except; consultation client misrouted IP-addressed local servers; narrator pulled the short-context CONSULTATION_ model instead of the long-context NARRATIVE_ model; full envelope (200k+ tokens) overflowed even MiniMax-M2.7. All five fixed.
  • --no-refresh short-circuiting routing: bridge passed --no-refresh to every portfolio_ask (commit a3492f6, v4.0.7), making the engine return the cached catalog blurb regardless of question. Reverted.

License + provenance

  • Service code: Apache 2.0 (ncz-os/mnemos-ic-runtime)
  • Distribution-edge artifacts (this SKILL.md, compose.yml, install.yaml, agent-skills/**): MIT-0 (MIT No Attribution — LICENSE-MIT-0). Required for ClawHub plugin publishing; the no-attribution clause means downstream skill registries can re-host without preserving copyright notice.
  • Image: ghcr.io/argonautsystems/ic-engine:4.7.0-cpu (multi-arch amd64+arm64; also at :latest)
  • RFC: see RFC-v0.1.md in this bundle (ncz-os/mnemos-ic-runtime GitHub repository)
  • Cross-project contract: mnemos-os/mcp-contracts GitHub repository

InvestorClaw is a portfolio analysis service. Educational use only — not investment advice.

常见问题

5 问
答案由本站依据条目字段整理
investorclaw怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_15292d5a/yjkj-investorclaw。安装方式为未标注。装完刷新技能列表或重开客户端。

investorclaw支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

investorclaw权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

investorclaw收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

investorclaw用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 未标注。