AGENT SKILL

rwa-portfolio

View portfolio holdings, P&L, allocation, and price history for tokenized stocks on Solana. Triggers: "show portfolio", "my holdings", "positions", "how much TSLA", "price history", "P&L", "profit", "average entry", "24h change", "balance", "what do I own".

License 许可
MIT
最近更新
2026-10-08
Stars
★ 0
Forks
0

01 前言 Front Matter

name
rwa-portfolio
description
View portfolio holdings, P&L, allocation, and price history for tokenized stocks on Solana. Triggers: "show portfolio", "my holdings", "positions", "how much TSLA", "price history", "P&L", "profit", "average entry", "24h change", "balance", "what do I own".

03 SKILL.md 正文

Portfolio

rwa --json gm portfolio                   # Own wallet
rwa --json gm portfolio <WALLET_ADDR>     # Any public wallet

JSON shape

{
  "wallet": "5CjgV1J2...",
  "cash": { "sol": 0.0870, "usdc": 0.00 },
  "gm_positions": {
    "positions": [
      { "token": "TSLAon", "balance": 0.2500, "price": 385.75,
        "value_usd": 96.44, "gm_alloc_pct": 100.00, "change_pct_24h": 1.23 }
    ],
    "value_usd": 96.44, "change_24h_usd": 1.17, "change_24h_pct": 1.23
  }
}

gm_alloc_pct = allocation within GM positions only (not total portfolio including cash). Every position also carries sector/asset_class/region/type/tags (Ondo labels, omitted when unknown) — no join against gm search needed.

Slicing (--view, since 0.7.14)

rwa --json gm portfolio --view sector              # split into per-sector groups
rwa --json gm portfolio --view Dividend            # filter: only positions tagged Dividend
rwa --json gm portfolio --view MRNA,CAPR           # filter: only these tickers
rwa --json gm portfolio --view Healthcare,factor   # filter, then split by factor
  • Category names (sector, region, class, type, factor) SPLIT; tag labels/tickers FILTER. Same-category labels OR, different categories AND; at most one split category.
  • JSON adds gm_positions.view + gm_positions.groups (always present with the flag; group: null when no split). positions[] is narrowed to matches, but gm_positions.value_usd and gm_alloc_pct stay full-portfolio — use view.matched_value_usd for the slice total.
  • --view factor groups OVERLAP (multi-label) and don't sum to the total — JSON marks overlapping: true.
  • No match → exit 0 with groups: []; unknown or all-blank term → invalid_view (exit 1).

P&L (entry prices, realized/unrealized)

rwa --json gm pnl        # own wallet only (built from the local trade ledger)
rwa --json gm pnl --all  # compare EVERY wallet that traded via this CLI (one row per ledger, no keys needed)
{
  "wallet": "5CjgV1J2...", "trades_recorded": 12,
  "tokens": [
    { "token": "TSLAon", "qty": "0.25", "avg_cost": 380.10, "market_price": 385.75,
      "invested_usdc": 95.03, "market_value_usdc": 96.44,
      "unrealized_usdc": 1.41, "realized_usdc": 3.20 }
  ],
  "totals": { "invested_usdc": 95.03, "market_value_usdc": 96.44,
              "unrealized_usdc": 1.41, "realized_usdc": 3.20, "total_pnl_usdc": 4.61 }
}

Semantics agents must respect:

  • Built only from trades this CLI executed (every buy/sell is logged locally per wallet). Deposits and inbound transfers are ignored by design; a CLI-recorded send of a GM token DOES shrink the position at avg cost with no realized impact (since 0.7.13 — no phantom holdings after sending tokens away).
  • JSON carries ledger_path — the per-wallet ledger file behind the numbers (delete it to reset history).
  • pnl --all returns {wallets:[{wallet, trades_recorded, invested_usdc, unrealized_usdc?, realized_usdc, total_pnl_usdc?, ledger_integrity}]} sorted by total P&L desc — use it to compare wallet performance.
  • avg_cost = average entry price of the open position; unrealized_usdc = market value − invested; realized_usdc = locked-in P&L from sells; total_pnl_usdc = both.
  • A token with an oversold_qty field was partly sold beyond CLI-recorded buys (acquired elsewhere) — that part is excluded from P&L, not mispriced.
  • Use portfolio for what the wallet holds NOW (on-chain truth); use pnl for entry prices and profit.
  • pnl JSON carries ledger_integrity: ok | legacy (pre-chain entries) | broken@line N (history may be modified — flag to the user; P&L still computes).
  • Balances/prices are in raw tokens (the CLI's canonical frame). Dividend-accruing tokens carry an optional shares_per_token (e.g. 1.0077): wallets like Phantom display raw × that multiplier, so the CLI's balance can read slightly lower than the wallet's — same value, different unit. Token price = share price × multiplier (total-return).

Price history

rwa --json gm history TSLA                # Default: 1 month
rwa --json gm history TSLA -r 1D          # Ranges: 1D, 1W, 1M, 3M, 1Y, ALL

Returns: symbol, range, candles count, first/last (timestamp + price), high, low, change_pct.

Efficient patterns

  • portfolio gives the full picture — no need to call list or hours first
  • history -r 1D (~50 tok) is much cheaper than ALL (~200 tok) for recent moves
  • To check one position: read gm_positions.positions[] — no separate balance call
  • To decide what to sell: sort by change_pct_24h/value_usd from portfolio, or by unrealized_usdc from pnl
  • SOL balance is at cash.sol, USDC at cash.usdc

04 同仓库更多 Skills