Help us improve
Share bugs, ideas, or general feedback.
How this skill is triggered — by the user, by Claude, or both
Slash command
/vulcan:vulcan-portfolio-intelThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use this skill when the user asks any of:
Lists, closes, reduces positions and manages TP/SL on existing positions via the Vulcan CLI. Useful for monitoring PnL and liquidation prices.
Analyzes CDCX trading portfolios via CLI tools: fetches balances, positions with P&L, sub-accounts, fee rates, transaction history. Activates on balance, holdings, PnL queries or reports.
Analyzes any crypto wallet by address using GMGN API on Solana, BSC, Base, or Ethereum. Returns holdings, P&L, win rate, trading history, and tokens created by a developer wallet.
Share bugs, ideas, or general feedback.
Use this skill when the user asks any of:
Always load this skill first for portfolio questions — do not improvise the layout.
The snapshot reflects exactly one wallet at a time, resolved in this priority:
ctx.session_wallet — the MCP session wallet unlocked at server start (VULCAN_WALLET_NAME, falling back to the configured default).--wallet <name> override (CLI only).vulcan wallet set-default.Within that wallet, the snapshot covers cross-margin (subaccount 0) and every isolated subaccount. If the user has multiple wallets, the active one is whatever the MCP server was started with; call vulcan_status if you need to confirm wallet.source and wallet.public_key.
Prefer the combined snapshot. It returns margin (cross), positions (all subaccounts), resting orders (cross), isolated subaccount summaries, and account totals in one call:
vulcan_portfolio → {}
Use granular calls only for a single section or symbol-level filtering:
vulcan_margin_status → {} # cross-margin only
vulcan_position_list → {} # all subaccounts; includes uPnL % and initial margin per position
vulcan_trade_orders → { symbol? }
When the user asks for daily, weekly, or historical performance — not for every portfolio check — pull realized PnL history:
vulcan_history → { type: "pnl", limit: 50 }
Sum fills since the cutoff (24h or 7d) to report realized PnL. If history is empty or the call fails, say so explicitly; do not invent a number. Open-position uPnL is not daily/weekly performance — keep them separate.
For agent-session activity, use:
vulcan://agent/position-report
vulcan://agent/session-summary
State the basis for any "win rate" figure — currently open-position win rate from unrealized PnL, not realized closed-trade history.
vulcan_portfolio returns:
margin (cross subaccount 0):
collateral_balance — USDC parked in cross.effective_collateral — collateral + discounted uPnL + unsettled funding.portfolio_value — collateral + uPnL (cross only).unrealized_pnl, initial_margin, maintenance_margin.risk_state (Safe / AtRisk / Cancellable / Liquidatable / BackstopLiquidatable / HighRisk).risk_tier.available_to_withdraw.num_positions, num_open_orders.totals (cross + every isolated):
total_collateral, total_account_value, total_unrealized_pnl, num_subaccounts.total_account_value over cross-only portfolio_value when reporting "account value" — otherwise collateral parked in isolated subaccounts is invisible.isolated_subaccounts[]:
subaccount_index, symbol, collateral_balance, effective_collateral, portfolio_value, unrealized_pnl, initial_margin, maintenance_margin.positions[]:
symbol (suffix [iso] for isolated), side, size, entry_price, mark_price.unrealized_pnl, unrealized_pnl_pct — already computed using the phoenix-v2-frontend formula (see below).initial_margin, maintenance_margin, liquidation_price.subaccount_index, subaccount_collateral — present only for isolated.orders[] — resting limit orders plus conditional TP/SL trigger legs.The field is precomputed; trust unrealized_pnl_pct. For reference, the formula is:
uPnL / subaccount_collateral.uPnL / entry_initial_margin, where entry_initial_margin = initial_margin * entry_price / mark_price (rebases current initial margin back to entry).Returned as a signed percent string, e.g. +1.45%, -3.20%, or — when the denominator is zero / missing.
Use this exact layout. Adapt only when sections are empty (skip them). Use the listed emojis; do not substitute.
📊 Portfolio Snapshot — <wallet name or short pubkey>
🏦 Account
- Risk: <risk_state> / <risk_tier> [🟢 Safe • 🟡 AtRisk/Cancellable • 🔴 Liquidatable/HighRisk]
- Total account value: $<total_account_value> (cross + isolated)
- Total collateral: $<total_collateral>
- Total uPnL: <signed $total_unrealized_pnl>
- Free to withdraw: $<available_to_withdraw> (cross)
- Cross initial / maintenance margin: $<initial_margin> / $<maintenance_margin>
📈 Positions (<n>)
| Market | Side | Size | Entry | Mark | uPnL | uPnL % | Liq |
| ... | ... | ... | ... | ... | ... | ... | ... |
For each isolated row also note: `iso collateral $X · init margin $Y` underneath the table or in a follow-up bullet.
🧾 Open Orders (<n>) — group by symbol
- <symbol>: <side> <size> @ <price> (<type>) ← regular limit
- <symbol>: TP / SL <side> <size> @ <price> (reduce-only) ← conditional trigger
💸 Funding (only when a position has non-trivial funding exposure)
- <symbol>: <rate>%/8h — <"longs pay shorts" or "shorts pay longs"> · costs/credits you ~$X/day at current size
📅 Performance (only when user asked for daily/weekly, or when realized PnL > 0 was observed this session)
- 24h realized PnL: <$value> (from vulcan_history type=pnl)
- 7d realized PnL: <$value>
🛡️ Notes
- Flag missing TP/SL on positions where the user has not opted out.
- Flag tight liquidation distance (< 5% from mark).
- Do **not** flag laddered TP/SL whose sizes sum to ≤ position size — that is intentional.
Rules:
totals.total_account_value, not margin.portfolio_value. The cross portfolio_value is misleading when isolated subaccounts hold collateral.uPnL % next to uPnL in the positions table.subaccount_collateral and initial_margin — those values explain the liquidation price and the cross/total gap.|funding_rate| < 0.001 AND there's no large exposure. Use vulcan_market_ticker per held symbol when including funding.Map risk_state to one indicator emoji:
Safe → 🟢AtRisk / Cancellable → 🟡Liquidatable / BackstopLiquidatable / HighRisk → 🔴Use the same emoji once next to the risk line; do not pepper it through the rest of the snapshot.
Multiple reduce-only TP or SL orders on the same position are almost always a laddered exit, not a bug:
A long 2.00 SOL with two reduce-only SL sells of 1.00 each → sums to 2.00 → exact match → valid laddered SL, do not warn.
vulcan-position-management (confirm first, orderbook check for large closes).vulcan-margin-operations.vulcan-trade-execution + vulcan-risk-management.