> For the complete documentation index, see [llms.txt](https://gotts.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gotts.gitbook.io/docs/gotts-safe-mcp-server/mcp-server/03b-tools-portfolio-pnl.md).

# Portfolio and P\&L Tools

> **Package**: `packages/safe/` | **Prerequisites**: [02-architecture.md](/docs/gotts-safe-mcp-server/mcp-server/02-architecture.md)
>
> Portfolio analytics and profit & loss tools (Phase 3–4 extension). 10 read-only tools. For other tool categories, see the [README](/docs/gotts-safe-mcp-server/mcp-server.md).

***

## Overview

This category adds historical balance tracking and unified P\&L accounting — the two capabilities required for an agent to autonomously assess its own performance and course-correct.

**Profile assignments:**

| Profile  | Tools included                                                             |
| -------- | -------------------------------------------------------------------------- |
| `data`   | All 10                                                                     |
| `lp`     | All 10                                                                     |
| `full`   | All 10 (via `data`)                                                        |
| `dev`    | All 10 (via `full`)                                                        |
| `trader` | `get_account_balance`, `get_realized_pnl`, `get_transaction_cost_analysis` |
| `vault`  | `get_account_balance`, `get_pnl_report`                                    |

**Autonomous self-assessment loop**: After computing `get_performance_metrics`, the vault-manager uses `vault_submit_yield_feedback` to post the result on-chain. The vault-strategist reads `vault_get_yield_leaderboard` and adjusts strategy accordingly. This loop runs without human intervention:

```
get_performance_metrics / get_pnl_report   (measure)
        ↓
vault_submit_yield_feedback                (record on-chain)
        ↓
vault_get_yield_leaderboard                (compare vs peers)
        ↓
vault-strategist course corrects           (adjust)
```

**Write operations**: 0 (all tools are read-only)

**Data sources**: The Graph subgraph (Transfer/Mint/Burn/Collect events), on-chain RPC via viem multicall, historical OHLCV from `get_token_price_history`.

***

## Portfolio and P\&L Tools

***

### `get_account_balance`

Get the current token balances for a wallet across one or all supported chains. Returns native and ERC-20 balances, USD valuations, LP position values, and change since a configurable lookback period.

**Parameters**:

| Name                   | Type      | Required | Description                                                           |
| ---------------------- | --------- | -------- | --------------------------------------------------------------------- |
| `wallet`               | `string`  | No       | Wallet address. Default: configured agent wallet.                     |
| `chain`                | `string`  | No       | Chain name or ID. If omitted, returns all supported chains.           |
| `includeSmallBalances` | `boolean` | No       | Include tokens with USD value < $1. Default: `false`.                 |
| `lookbackHours`        | `number`  | No       | Hours to look back for change delta. Default: `24`.                   |
| `includeLP`            | `boolean` | No       | Include the underlying value of active LP positions. Default: `true`. |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "timestamp": "2026-02-19T12:00:00Z",
  "totalValueUsd": 48230.56,
  "change24hUsd": 1245.32,
  "change24hPct": 2.65,
  "chains": [
    {
      "chain": "base",
      "chainId": 8453,
      "totalValueUsd": 32100.0,
      "nativeBalance": {
        "symbol": "ETH",
        "amount": "5.23",
        "usdValue": 16991.35
      },
      "tokens": [
        {
          "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
          "symbol": "USDC",
          "amount": "15000.000000",
          "usdValue": 15000.0,
          "priceUsd": 1.0001,
          "change24hPct": 0.01
        }
      ],
      "lpPositions": [
        {
          "positionId": "456790",
          "pool": "USDC/WETH 0.05%",
          "totalValueUsd": 108.65,
          "inRange": true
        }
      ]
    }
  ],
  "topHoldings": [
    { "symbol": "USDC", "totalUsd": 24200.0, "pct": 50.2 },
    { "symbol": "ETH", "totalUsd": 23809.45, "pct": 49.4 }
  ]
}
```

**Error Cases**:

* `WALLET_NOT_FOUND`: Address is not a valid EVM address
* `CHAIN_NOT_SUPPORTED`: Specified chain is not in the supported list
* `DATA_SOURCE_ERROR`: RPC or subgraph unavailable

***

### `get_wallet_balance_history`

Get the historical balance of a wallet over time as a time series. Returns per-token and total USD value at each interval. Computed by replaying on-chain transaction history against historical prices.

**Parameters**:

| Name             | Type      | Required | Description                                                      |
| ---------------- | --------- | -------- | ---------------------------------------------------------------- |
| `wallet`         | `string`  | No       | Wallet address. Default: configured agent wallet.                |
| `chain`          | `string`  | No       | Chain filter. If omitted, returns aggregated cross-chain totals. |
| `token`          | `string`  | No       | Filter to a specific token symbol or address.                    |
| `interval`       | `string`  | No       | Aggregation interval: `"1h"`, `"1d"`, `"1w"`. Default: `"1d"`.   |
| `startTime`      | `string`  | No       | ISO 8601 start time. Default: 30 days ago.                       |
| `endTime`        | `string`  | No       | ISO 8601 end time. Default: now.                                 |
| `includeLpValue` | `boolean` | No       | Include LP position value in total. Default: `true`.             |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "interval": "1d",
  "chain": "all",
  "token": null,
  "series": [
    {
      "timestamp": "2026-01-20T00:00:00Z",
      "totalUsd": 40120.34,
      "breakdown": {
        "ETH": { "amount": "6.00", "usdValue": 19440.0 },
        "USDC": { "amount": "19800.00", "usdValue": 19800.0 },
        "lpPositions": { "usdValue": 880.34 }
      }
    }
  ],
  "summary": {
    "startValueUsd": 40120.34,
    "endValueUsd": 48230.56,
    "changeUsd": 8110.22,
    "changePct": 20.21,
    "highUsd": 52100.0,
    "lowUsd": 38900.0,
    "averageUsd": 44850.0
  },
  "source": "subgraph+rpc",
  "note": "Balance history is reconstructed from on-chain transaction events. Values reflect prices at each timestamp using historical OHLCV data."
}
```

**Implementation note**: Balance history is computed via event replay — fetching Transfer events from The Graph, replaying Mint/Burn/Collect events for LP positions, and pricing each token at each interval using `get_token_price_history` close prices. Results are cached per `PORTFOLIO_CACHE_TTL_SECONDS`.

**Error Cases**:

* `INSUFFICIENT_HISTORY`: Wallet has fewer than 2 on-chain transactions in the requested period
* `PRICE_DATA_UNAVAILABLE`: Historical price data unavailable for one or more tokens (partial result returned, affected tokens flagged)

***

### `get_portfolio_snapshot`

Get the complete portfolio state of a wallet at a specific point in time. Useful for historical audit, tax reporting, and period-start cost basis.

**Parameters**:

| Name        | Type      | Required | Description                                                        |
| ----------- | --------- | -------- | ------------------------------------------------------------------ |
| `wallet`    | `string`  | No       | Wallet address. Default: configured agent wallet.                  |
| `timestamp` | `string`  | Yes      | ISO 8601 datetime for the snapshot.                                |
| `chain`     | `string`  | No       | Chain filter. If omitted, returns all chains.                      |
| `includeLP` | `boolean` | No       | Include LP positions at their value at that time. Default: `true`. |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "snapshotTime": "2026-01-31T23:59:59Z",
  "totalValueUsd": 45890.0,
  "tokens": [
    {
      "chain": "base",
      "symbol": "ETH",
      "address": "native",
      "amount": "5.80",
      "priceAtSnapshot": 3250.0,
      "usdValue": 18850.0
    }
  ],
  "lpPositions": [
    {
      "positionId": "456790",
      "chain": "base",
      "pool": "USDC/WETH 0.05%",
      "version": "v3",
      "token0Amount": "2500.00",
      "token1Amount": "0.769",
      "totalValueUsd": 5040.0,
      "inRange": true,
      "unclaimedFeesUsd": 45.2
    }
  ],
  "note": "Snapshot reconstructed from block closest to requested timestamp. Block: 18234567 (Base)."
}
```

***

### `get_realized_pnl`

Calculate realized profit and loss from completed trades (swaps) and closed LP positions for a wallet over a time period. Uses FIFO cost basis by default.

**Parameters**:

| Name              | Type      | Required | Description                                             |
| ----------------- | --------- | -------- | ------------------------------------------------------- |
| `wallet`          | `string`  | No       | Wallet address. Default: configured agent wallet.       |
| `chain`           | `string`  | No       | Chain filter. If omitted, aggregates across all chains. |
| `startTime`       | `string`  | No       | ISO 8601 start time. Default: 30 days ago.              |
| `endTime`         | `string`  | No       | ISO 8601 end time. Default: now.                        |
| `costBasisMethod` | `string`  | No       | `"fifo"` (default), `"hifo"`, `"lifo"`.                 |
| `groupBy`         | `string`  | No       | `"token"` (default), `"pool"`, `"day"`, `"week"`.       |
| `includeGas`      | `boolean` | No       | Include gas costs in P\&L. Default: `true`.             |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "period": { "start": "2026-01-20T00:00:00Z", "end": "2026-02-19T12:00:00Z" },
  "costBasisMethod": "fifo",
  "summary": {
    "totalRealizedPnlUsd": 3245.67,
    "tradingPnlUsd": 2890.12,
    "lpExitPnlUsd": 823.45,
    "feeRevenueUsd": 312.5,
    "gasSpentUsd": -780.4,
    "netPnlUsd": 3245.67
  },
  "byToken": [
    {
      "token": "ETH",
      "totalSold": "3.20 ETH",
      "averageCostBasis": 3100.0,
      "averageSalePrice": 3248.5,
      "realizedPnlUsd": 474.08,
      "transactionCount": 4
    }
  ],
  "lpExits": [
    {
      "positionId": "445123",
      "pool": "ETH/USDC 0.05% (v3, Base)",
      "openedAt": "2025-12-15T10:00:00Z",
      "closedAt": "2026-01-28T14:30:00Z",
      "capitalDeployed": 10000.0,
      "proceeds": 10823.45,
      "feesEarned": 312.5,
      "impermanentLoss": -289.05,
      "netGain": 823.45
    }
  ]
}
```

**Implementation notes**:

* Realized P\&L on swaps = `proceeds - costBasis` (USD value paid for tokens sold)
* LP exit P\&L = `(proceedsToken0Usd + proceedsToken1Usd + feesCollected) - capitalDeployed`
* Gas costs are tracked separately and optionally netted into the total
* Tokens received from external sources with unknown cost basis are flagged with `"basis": "unknown"`

***

### `get_unrealized_pnl`

Calculate unrealized profit and loss on open LP positions and held token balances relative to their cost basis.

**Parameters**:

| Name                 | Type      | Required | Description                                                       |
| -------------------- | --------- | -------- | ----------------------------------------------------------------- |
| `wallet`             | `string`  | No       | Wallet address. Default: configured agent wallet.                 |
| `chain`              | `string`  | No       | Chain filter. If omitted, all chains.                             |
| `costBasisMethod`    | `string`  | No       | `"fifo"` (default), `"hifo"`, `"lifo"`.                           |
| `includeHeldTokens`  | `boolean` | No       | Include unrealized P\&L on held (non-LP) tokens. Default: `true`. |
| `includeLpPositions` | `boolean` | No       | Include open LP positions. Default: `true`.                       |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "timestamp": "2026-02-19T12:00:00Z",
  "costBasisMethod": "fifo",
  "summary": {
    "totalUnrealizedPnlUsd": 5820.34,
    "heldTokenPnlUsd": 4900.0,
    "lpPositionPnlUsd": 1232.84,
    "lpImpermanentLossUsd": -312.5,
    "lpUnclaimedFeesUsd": 920.34
  },
  "heldTokens": [
    {
      "token": "ETH",
      "chain": "base",
      "amount": "5.23",
      "averageCostBasis": 3100.0,
      "currentPrice": 3248.5,
      "costBasisTotalUsd": 16213.0,
      "currentValueUsd": 16991.35,
      "unrealizedPnlUsd": 778.35,
      "unrealizedPnlPct": 4.8
    }
  ],
  "lpPositions": [
    {
      "positionId": "456790",
      "pool": "USDC/WETH 0.05% (v3, Base)",
      "version": "v3",
      "openedAt": "2026-01-15T10:00:00Z",
      "capitalDeployedUsd": 10000.0,
      "currentValueUsd": 10920.34,
      "unclaimedFeesUsd": 89.05,
      "impermanentLossUsd": -168.71,
      "netUnrealizedPnlUsd": 920.34,
      "netUnrealizedPnlPct": 9.2,
      "inRange": true,
      "daysOpen": 35
    }
  ]
}
```

**IL calculation (V3 concentrated liquidity)**:

```
IL = (currentValue - holdValue) / holdValue

Where:
  holdValue    = token0_at_entry * currentPrice0 + token1_at_entry * currentPrice1
  currentValue = current LP position value (both tokens at current prices)
  netGain      = feesEarned + currentValue - entryValue
```

***

### `get_fee_earnings_history`

Get the history of LP fee earnings for a wallet across all positions and pools, with breakdown by pool and time period.

**Parameters**:

| Name               | Type      | Required | Description                                                      |
| ------------------ | --------- | -------- | ---------------------------------------------------------------- |
| `wallet`           | `string`  | No       | Wallet address. Default: configured agent wallet.                |
| `chain`            | `string`  | No       | Chain filter. If omitted, all chains.                            |
| `startTime`        | `string`  | No       | ISO 8601 start time. Default: 90 days ago.                       |
| `endTime`          | `string`  | No       | ISO 8601 end time. Default: now.                                 |
| `interval`         | `string`  | No       | Grouping interval: `"1d"`, `"1w"`, `"1M"`. Default: `"1d"`.      |
| `includeUnclaimed` | `boolean` | No       | Include currently accrued but uncollected fees. Default: `true`. |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "period": { "start": "2025-11-20T00:00:00Z", "end": "2026-02-19T12:00:00Z" },
  "summary": {
    "totalFeesEarnedUsd": 1240.5,
    "collectedFeesUsd": 1151.45,
    "unclaimedFeesUsd": 89.05,
    "annualizedFeeYieldPct": 12.4,
    "bestSingleDayUsd": 45.2,
    "averageDailyUsd": 13.78
  },
  "byPool": [
    {
      "pool": "USDC/WETH 0.05%",
      "chain": "base",
      "version": "v3",
      "positionIds": ["456790"],
      "totalFeesEarnedUsd": 890.5,
      "collectedFeesUsd": 801.45,
      "unclaimedFeesUsd": 89.05,
      "annualizedYieldPct": 10.8,
      "dayCount": 90
    }
  ],
  "timeSeries": [
    {
      "date": "2026-02-18",
      "feesEarnedUsd": 18.3,
      "byPool": [{ "pool": "USDC/WETH 0.05% (Base)", "feesUsd": 18.3 }]
    }
  ]
}
```

**Data source**: Subgraph `Collect` events (realized fees) + `position.tokensOwed0/1` RPC reads (unclaimed fees).

***

### `get_transaction_cost_analysis`

Analyze the gas and slippage costs of all Uniswap transactions executed by a wallet in a period. Helps agents understand the total overhead of their operations and identify cost-reduction opportunities.

**Parameters**:

| Name        | Type     | Required | Description                                       |
| ----------- | -------- | -------- | ------------------------------------------------- |
| `wallet`    | `string` | No       | Wallet address. Default: configured agent wallet. |
| `chain`     | `string` | No       | Chain filter. If omitted, all chains.             |
| `startTime` | `string` | No       | ISO 8601 start time. Default: 30 days ago.        |
| `endTime`   | `string` | No       | ISO 8601 end time. Default: now.                  |
| `groupBy`   | `string` | No       | `"type"` (default), `"day"`, `"chain"`, `"pool"`. |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "period": { "start": "2026-01-20T00:00:00Z", "end": "2026-02-19T12:00:00Z" },
  "summary": {
    "totalTransactions": 47,
    "totalGasSpentUsd": 312.45,
    "totalSlippageCostUsd": 89.2,
    "totalApprovalGasUsd": 24.1,
    "totalCostUsd": 401.65,
    "averageGasPerTxUsd": 6.65,
    "mostExpensiveOperationType": "add_liquidity",
    "cheapestChain": "base"
  },
  "byType": [
    {
      "type": "swap",
      "count": 30,
      "gasSpentUsd": 155.0,
      "slippageCostUsd": 42.3,
      "avgGasUsd": 5.17
    },
    {
      "type": "add_liquidity",
      "count": 8,
      "gasSpentUsd": 98.45,
      "slippageCostUsd": 38.9,
      "avgGasUsd": 12.31
    }
  ],
  "byChain": [
    {
      "chain": "base",
      "gasSpentUsd": 18.45,
      "transactionCount": 35,
      "avgGasUsd": 0.53
    },
    {
      "chain": "ethereum",
      "gasSpentUsd": 294.0,
      "transactionCount": 12,
      "avgGasUsd": 24.5
    }
  ],
  "optimization": {
    "estimatedSavingsIfBaseOnly": 276.0,
    "highCostTransactions": [
      {
        "txHash": "0xDEAD...",
        "type": "add_liquidity",
        "gasUsd": 48.2,
        "chain": "ethereum",
        "recommendation": "Consider executing this operation on Base (estimated cost: $1.20)"
      }
    ]
  }
}
```

**Gas attribution**: `gasUsed * effectiveGasPrice` in native token, converted to USD at block timestamp price. Operation type attributed from transaction method signature decoding (`execute`, `mint`, `burn`, `collect`, `exactInputSingle`, etc.).

***

### `get_performance_metrics`

Compute risk-adjusted performance metrics for a wallet's Uniswap activity over a period. Returns Sharpe ratio, Sortino ratio, max drawdown, time-weighted return, and attribution breakdown.

**Parameters**:

| Name           | Type     | Required | Description                                                                    |
| -------------- | -------- | -------- | ------------------------------------------------------------------------------ |
| `wallet`       | `string` | No       | Wallet address. Default: configured agent wallet.                              |
| `chain`        | `string` | No       | Chain filter. If omitted, cross-chain aggregate.                               |
| `startTime`    | `string` | No       | ISO 8601 start time. Default: 90 days ago.                                     |
| `endTime`      | `string` | No       | ISO 8601 end time. Default: now.                                               |
| `benchmark`    | `string` | No       | `"eth"`, `"btc"`, `"usdc"`, `"none"` (default: `PORTFOLIO_BENCHMARK` config).  |
| `riskFreeRate` | `number` | No       | Annual risk-free rate for Sharpe (%). Default: `PORTFOLIO_RISK_FREE_RATE_PCT`. |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "period": {
    "start": "2025-11-20T00:00:00Z",
    "end": "2026-02-19T12:00:00Z",
    "days": 91
  },
  "returns": {
    "totalReturnUsd": 8234.22,
    "totalReturnPct": 20.52,
    "annualizedReturnPct": 82.37,
    "timeWeightedReturnPct": 19.88
  },
  "riskMetrics": {
    "sharpeRatio": 1.84,
    "sortinoRatio": 2.41,
    "maxDrawdownPct": -12.3,
    "maxDrawdownPeriod": {
      "start": "2025-12-20T00:00:00Z",
      "end": "2026-01-05T00:00:00Z"
    },
    "volatilityAnnualized": 42.1,
    "calmarRatio": 6.7
  },
  "attribution": {
    "tradingPnlPct": 7.22,
    "lpFeeYieldPct": 3.1,
    "priceAppreciationPct": 12.45,
    "gasCostDragPct": -0.78,
    "impermanentLossDragPct": -1.47
  },
  "benchmark": {
    "asset": "eth",
    "returnPct": 18.2,
    "alpha": 2.32,
    "beta": 0.78,
    "correlationToPortfolio": 0.82
  },
  "bestMonth": { "month": "2026-01", "returnPct": 14.2 },
  "worstMonth": { "month": "2025-12", "returnPct": -6.8 }
}
```

**Computation notes**:

* Sharpe ratio: daily return series annualized with factor √252
* Sortino ratio: only negative-return days in denominator
* Max drawdown: computed from daily portfolio value series
* Attribution splits total return into: LP fee income, realized trading gains/losses, price appreciation, gas drag, and IL drag

**Usage in autonomous loop**: The output of this tool feeds directly into `vault_submit_yield_feedback` (`yieldBps` field) to post performance on-chain, and can be compared against `vault_get_yield_leaderboard` to assess competitive positioning.

***

### `compare_portfolio_periods`

Compare portfolio performance across two distinct time windows. Answers "how did I do this month vs last month?" or "Q4 2025 vs Q1 2026?" queries.

**Parameters**:

| Name      | Type       | Required | Description                                                      |
| --------- | ---------- | -------- | ---------------------------------------------------------------- |
| `wallet`  | `string`   | No       | Wallet address. Default: configured agent wallet.                |
| `periodA` | `object`   | Yes      | `{ start: ISO8601, end: ISO8601 }` — first (baseline) period.    |
| `periodB` | `object`   | Yes      | `{ start: ISO8601, end: ISO8601 }` — second (comparison) period. |
| `chain`   | `string`   | No       | Chain filter. If omitted, cross-chain.                           |
| `metrics` | `string[]` | No       | Subset of metrics to include. Default: all.                      |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "periodA": {
    "label": "Jan 2026",
    "start": "2026-01-01T00:00:00Z",
    "end": "2026-01-31T23:59:59Z",
    "totalReturnPct": 14.2,
    "totalReturnUsd": 4850.0,
    "feesEarnedUsd": 420.1,
    "gasSpentUsd": 155.0,
    "transactionCount": 22,
    "sharpeRatio": 2.1,
    "maxDrawdownPct": -5.2
  },
  "periodB": {
    "label": "Feb 2026 (partial)",
    "start": "2026-02-01T00:00:00Z",
    "end": "2026-02-19T12:00:00Z",
    "totalReturnPct": 6.31,
    "totalReturnUsd": 2680.0,
    "feesEarnedUsd": 180.4,
    "gasSpentUsd": 80.0,
    "transactionCount": 14,
    "sharpeRatio": 1.42,
    "maxDrawdownPct": -3.1
  },
  "delta": {
    "returnPctDelta": -7.89,
    "feesEarnedDelta": -239.7,
    "gasEfficiencyDelta": "+12% (fewer transactions, lower gas per tx)",
    "sharpeDelta": -0.68
  },
  "interpretation": "January outperformed February on an absolute and risk-adjusted basis, primarily driven by higher LP fee earnings ($420 vs $180) and stronger price appreciation. February shows improved gas efficiency."
}
```

***

### `get_pnl_report`

Generate a complete, unified P\&L report combining realized gains, unrealized positions, fee income, gas costs, and performance metrics. The single-tool comprehensive equivalent of calling `get_realized_pnl` + `get_unrealized_pnl` + `get_fee_earnings_history` + `get_transaction_cost_analysis` + `get_performance_metrics` in sequence.

**Parameters**:

| Name                     | Type      | Required | Description                                                 |
| ------------------------ | --------- | -------- | ----------------------------------------------------------- |
| `wallet`                 | `string`  | No       | Wallet address. Default: configured agent wallet.           |
| `chain`                  | `string`  | No       | Chain filter. If omitted, all chains.                       |
| `startTime`              | `string`  | No       | ISO 8601 start time. Default: 30 days ago.                  |
| `endTime`                | `string`  | No       | ISO 8601 end time. Default: now.                            |
| `costBasisMethod`        | `string`  | No       | `"fifo"` (default), `"hifo"`, `"lifo"`.                     |
| `includeTransactionList` | `boolean` | No       | Include full transaction-level breakdown. Default: `false`. |
| `format`                 | `string`  | No       | `"summary"` (default) or `"detailed"`.                      |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "period": { "start": "2026-01-20T00:00:00Z", "end": "2026-02-19T12:00:00Z" },
  "costBasisMethod": "fifo",
  "headline": {
    "netPnlUsd": 3245.67,
    "netPnlPct": 8.09,
    "totalReturnAnnualized": 96.8,
    "sharpeRatio": 1.84
  },
  "income": {
    "realizedTradingPnlUsd": 2890.12,
    "feesCollectedUsd": 312.5,
    "totalIncomeUsd": 3202.62
  },
  "costs": {
    "gasSpentUsd": -312.45,
    "slippageCostUsd": -89.2,
    "impermanentLossRealizedUsd": -289.05,
    "totalCostsUsd": -690.7
  },
  "unrealized": {
    "openLpPositionPnlUsd": 920.34,
    "openLpUnclaimedFeesUsd": 89.05,
    "heldTokenUnrealizedPnlUsd": 778.35,
    "totalUnrealizedUsd": 1787.74
  },
  "netIncludingUnrealized": 5033.41,
  "positionSummary": {
    "activePositions": 1,
    "closedPositions": 1,
    "totalSwaps": 30,
    "avgHoldPeriodDays": 35
  },
  "topPerformers": [
    {
      "type": "lp_position",
      "pool": "USDC/WETH 0.05% (Base)",
      "pnlUsd": 920.34
    }
  ],
  "worstPerformers": [
    { "type": "swap", "description": "UNI->ETH (Jan 5)", "pnlUsd": -45.2 }
  ],
  "recommendations": [
    "Gas costs ($312) are 9.6% of gross income. Consider batching operations on Base instead of Ethereum.",
    "Open LP position is performing well (9.2% gain in 35 days). Monitor: out-of-range risk increases if ETH moves above $3,600.",
    "Fee yield of 12.4% APY on LP capital is above the 90-day pool median of 10.8%."
  ]
}
```

***

### `stress_test_portfolio`

Run DeFi-specific stress scenarios against the current portfolio. Models the impact of price crashes, stablecoin depegs, gas spikes, and smart contract failures on all open positions. Uses Historical Simulation VaR with EWMA weighting. All computation is local — no external APIs.

**Parameters**:

| Name              | Type     | Required | Description                                                                     |
| ----------------- | -------- | -------- | ------------------------------------------------------------------------------- |
| `wallet`          | `string` | No       | Wallet address. Default: configured agent wallet.                               |
| `chain`           | `string` | No       | Chain filter. If omitted, all chains.                                           |
| `scenarios`       | `string` | No       | JSON array of custom scenarios. If omitted, runs the default DeFi scenario set. |
| `confidenceLevel` | `number` | No       | VaR confidence level (0.90, 0.95, 0.99). Default: `0.95`.                       |
| `lookbackDays`    | `number` | No       | Historical data lookback for VaR calculation. Default: `90`.                    |

**Default scenarios** (when `scenarios` is omitted):

| Scenario              | Description                                             |
| --------------------- | ------------------------------------------------------- |
| ETH -30%              | Moderate crash — IL explosion on LP positions           |
| ETH -50%              | Severe crash — tests liquidation proximity              |
| Stablecoin depeg (5%) | USDC or USDT depegs 5% — correlated pair disruption     |
| Gas spike (10x)       | Emergency withdrawal cost estimation at 10x current gas |
| Correlation breakdown | ETH/stETH or similar correlated pair breaks correlation |

**Returns**:

```json
{
  "wallet": "0x1234...",
  "timestamp": "2026-02-19T12:00:00Z",
  "currentPortfolioValueUsd": 48230.56,
  "var": {
    "confidenceLevel": 0.95,
    "lookbackDays": 90,
    "dailyVarUsd": -2890.0,
    "dailyVarPct": -5.99,
    "weeklyVarUsd": -6460.0,
    "weeklyVarPct": -13.4,
    "method": "historical-simulation-ewma"
  },
  "scenarios": [
    {
      "name": "ETH -30%",
      "portfolioValueUsd": 35200.0,
      "lossUsd": -13030.56,
      "lossPct": -27.0,
      "positionImpacts": [
        {
          "type": "held_token",
          "asset": "ETH",
          "lossUsd": -5097.4,
          "note": "Direct price exposure"
        },
        {
          "type": "lp_position",
          "pool": "USDC/WETH 0.05% (Base)",
          "positionId": "456790",
          "lossUsd": -2840.0,
          "ilIncreasePct": -8.5,
          "inRange": false,
          "note": "Position goes out of range. IL accelerates."
        }
      ],
      "emergencyExitCostUsd": 0.8
    },
    {
      "name": "Gas spike (10x)",
      "portfolioValueUsd": 48230.56,
      "lossUsd": 0,
      "emergencyExitCostUsd": 8.0,
      "note": "On Base, even 10x gas is manageable ($8 total exit cost). On Ethereum mainnet this would be ~$480."
    }
  ],
  "worstCase": {
    "scenario": "ETH -50%",
    "portfolioValueUsd": 27100.0,
    "lossPct": -43.8
  },
  "recommendations": [
    "LP position 456790 has significant IL risk in a >30% ETH drawdown. Consider widening range or reducing position size.",
    "Portfolio is 49% ETH-exposed. Diversification into stablecoins would reduce crash scenario impact."
  ]
}
```

**Implementation**: Fetches current portfolio state via `get_account_balance` and `get_positions_by_owner`. For VaR, uses daily return series from `get_wallet_balance_history` with EWMA decay (lambda=0.94). For scenario analysis, reprices each position using the V3 concentrated liquidity math (`LiquidityAmounts.getAmountsForLiquidity`) at stressed prices. Emergency exit cost estimated from current gas price scaled by scenario multiplier.

**Error Cases**:

* `INSUFFICIENT_HISTORY`: Less than 30 days of balance history for VaR calculation
* `NO_POSITIONS`: Wallet has no open positions to stress test
* `INVALID_SCENARIO`: Malformed custom scenario JSON

***

## Success Metrics (Phase 3–4 Rollout)

| Metric                                                            | Target                   |
| ----------------------------------------------------------------- | ------------------------ |
| `get_account_balance` p95 latency                                 | < 2 seconds (all chains) |
| `get_wallet_balance_history` p95 latency (30-day, daily)          | < 8 seconds              |
| `get_pnl_report` (summary mode) p95 latency                       | < 5 seconds              |
| Balance reconstruction accuracy vs known ground truth             | > 99.5% (test suite)     |
| IL calculation accuracy vs reference implementation               | ±0.1%                    |
| Agent eval: `pnl-analyst` correctly identifies cost basis method  | > 95% on eval suite      |
| Agent eval: `pnl-analyst` REFUSES to make trading recommendations | 100%                     |

## Rollout Phases

| Phase                                    | Deliverables                                                                                                                          |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Phase 3 (Trading & LP, extended)**     | `get_account_balance`, `get_wallet_balance_history`, `get_portfolio_snapshot`, `get_realized_pnl`, `get_unrealized_pnl`               |
| **Phase 4 (Streaming & Fees, extended)** | `get_fee_earnings_history`, `get_transaction_cost_analysis`, `get_performance_metrics`, `compare_portfolio_periods`, `get_pnl_report` |
| **Phase 5+ (Agent Capital Markets)**     | Integration with `treasury-manager` (`revenue-report`), `vault_submit_yield_feedback` feedback loop                                   |
| **Phase 7 (Intelligence & DX)**          | `stress_test_portfolio` (DeFi-specific VaR + scenario analysis)                                                                       |
