Skip to main content
Glama
simoneb

ibkr-risk-mcp

by simoneb

stress_curve

Read-onlyIdempotent

Plot portfolio P&L across volatility scenarios in a single call, comparing constant-volatility and vol-coordinated assumptions to expose the shock that breaks the book.

Instructions

The portfolio P&L curve under several volatility regimes at once — the data behind a risk graph, for plotting rather than for reading point by point.

Risk Navigator draws two curves: a constant-volatility line and one from its own implied-volatility model, which is not documented and cannot be reproduced. This returns as many as you ask for, and the volatility assumption behind each is a number in the output rather than a black box: volSlopeDown is volatility points per 1% fall.

Read the slope-0 curve first. It is the constant-volatility case and the only one with an external check — it should sit close to Risk Navigator's blue line. If it does not, the volatility lookup is wrong and no other scenario in the result means anything.

Check volSurfaceUsed. It lists every quote the repricing actually read, as (underlying, tenor, strike, iv). Empty under sticky_moneyness means no expiry held three strikes, so no smile could be built and every option silently fell back to sticky_strike — the result looks perfectly normal and is not the model you asked for. fetch_skew=true fixes it at the cost of extra market data requests.

How each curve is built, and where it is weakest:

  • Every scenario reprices one loading of the portfolio and one surface, so the curves differ by assumption alone. Calling the single-curve tool three times could not promise that: the book moves between calls.

  • The starting volatility is IB's own, per contract, out of a model that prices American exercise. The surface is used only for the change in volatility as a strike slides to new moneyness, which keeps IB's better number as the anchor and keeps every curve exactly zero at zero shock.

  • vol_coord reproduces IB's own model: volatility is multiplied, not shifted — a fall of X moves it by 10X relatively, a rise by -X, damped across tenors. Being relative is what makes the surface steepen by itself, since a wing already quoted at 41% takes more points than a 31% at-the-money out of the same scenario. The asymmetry is IB's documented one; the damping is fitted here and is not published, so vol_coord_decay is an input you should refit against your own Risk Navigator.

  • The additive volSlopeDown alternative is a parallel shift, flat across tenors. It cannot steepen at any value, and on a ratio book that is the difference between a curve that keeps falling and one that turns back up. Prefer vol_coord unless you specifically want a flat regime.

  • Equities move by the shock times their beta, futures and options by their own underlying's beta-scaled move. Bonds are flat unless bond_rate_shift_bp is set. FX is off the axis by default and reported under excluded with its market value — not held flat in silence.

  • Options IB would not model are repriced from a locally implied volatility where a mark price exists, flagged per position and in warnings, and held flat only when even that fails.

  • date_offsets=[0, 3] (or valuation_dates) crosses the scenarios with a family of valuation dates, so "today against Monday, when the August wings expire" is one call rather than two that the market moves between. Each entry under curves carries its own valuationDate and dateOffsetDays; name stays the scenario's and label distinguishes them. Time is the only thing that moves — today's spot and today's volatilities with the clock advanced, which is decay and not a forecast.

  • breakdown='expiry' puts pnl_by_expiry on every point and troughByExpiry on every curve, keyed on the option's settlement date. On a book running one root across many expiries that is the only way to see which expiry owns the trough; pnl_by_symbol shows one "ES" number for all of them.

pnl_pct_of_nlv is on every point, and netLiquidation at the top. Quote the fraction rather than the amount when comparing two dates or two accounts. Check reconciled before quoting any of it.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
betasNoPer-symbol share of the PRICE shock — unrelated to a scenario's volatility slope. Scales the move of that position's own underlying, options and futures included.
scopeNoWhich underlyings are on the shock axis. 'equity' excludes FX, rates and the rest outright and lists them under `excluded`; 'all' shocks everything by the same percentage, which off the equity axis is meaningless.equity
shocksNoUnderlying moves as fractions: -0.20 is a 20% fall. Defaults to -0.40 to +0.10 in 2% steps, which is wide enough on the downside that a short-gamma trough falls inside the window rather than on its edge.
vol_modeNosticky_strike — the default — pins each strike to the volatility it holds today. This is what Risk Navigator's blue curve does, and it is the only setting under which the slope-0 curve can be checked against it: measured on a live index ratio book the two agree to within 1-3% at every shock from 0 to -30%. sticky_moneyness instead rereads each strike's volatility at the moneyness it lands on after the shock, off the portfolio's own surface, interpolated across strike and expiry — a defensible model, but a different one, and on that same book it deepened the trough by a factor of 1.8. Do not compare it to Risk Navigator.sticky_strike
breakdownNoWhich per-point P&L breakdowns to return. 'symbol' — the default and what this server has always returned — groups by root, which on an options book collapses every ES expiry under one 'ES' key. 'expiry' groups by the option's SETTLEMENT date instead ('ES 2026-10-30'), which is the breakdown that answers 'which expiry is holding the trough down, and which short do I buy back'. 'both' returns the two of them and 'none' neither. Positions with no expiry get a key naming their class ('ES (future)', 'AAPL (equity)') so the breakdown still sums to the point's total and can be checked against it. Responses are large: a book on nine expiries pays for the second dictionary at every one of twenty-six shocks, so ask for 'both' only when you want both, and 'none' when you only want the curve.symbol
fetch_skewNoLet the surface pull neighbouring strikes from IB for expiries the portfolio holds too thinly. Costs extra market data requests, and is what to reach for when `volSurfaceUsed` comes back thin or empty.
risk_groupsNoOverride a symbol's risk group, e.g. {'TLT': 'rates'}. IB publishes no asset class for a bond or gold ETF quoted as a stock.
date_offsetsNoA FAMILY of valuation dates in one call, as day offsets: [0, 3] is today and three days out. Every scenario is run at every offset, and all of them come out of ONE loading of the positions and prices — which is what makes the comparison mean anything, since calling this tool twice lets the book and the market move between the two answers. Mutually exclusive with date_offset_days and valuation_dates.
default_betaNo
vol_scenariosNoOne curve per volatility regime. Defaults to the two curves Risk Navigator itself draws: 'const' (no volatility response, its blue line) and 'vol_coord' (IB's own volatility-coordinated model). Always keep a const curve in the set — it is the one that can be checked against Risk Navigator, and if it does not line up nothing else in the result is worth reading. Additive slopes are still there for a regime you want to state by hand, but prefer vol_coord: a slope shifts the surface in parallel, which on a book that is short the middle and long both wings is the wrong shape and not merely the wrong size.
valuation_datesNoThe same family, given as ISO dates: ['2026-08-28', '2026-08-31']. Mutually exclusive with the offset forms. No calendar magic — the date is the date, weekend or not.
vol_coord_decayNoTerm damping of the vol_coord model: VR(t) = exp(-decay * t), so a front-month contract takes nearly the whole shock and a back month a fraction. IB documents that this function exists and is decreasing but not what it is, so this number is FITTED, not published. Left unset it uses your own stored calibration if calibrate_vol_coord has ever been run, and otherwise the factory fit of 4.736 — one number calibrated on one book, which has no claim on yours. `assumptions.volCoordDecaySource` says which of the three you got.
date_offset_daysNoRoll the valuation date forward this many days (time decay).
bond_rate_shift_bpNo
bond_duration_yearsNo
vol_coord_calibrated_to_yearsNoHow far out in tenor `vol_coord_decay` was actually constrained. Defaults alongside the decay: your calibration's reach if you have one, and otherwise 0.345, the four months the shipped fit was constrained over. An exponential extrapolates to zero, which would price a one-year option as carrying no volatility risk at all in a crash, so positions past this are priced anyway and named in `warnings` rather than passing in silence.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Install Server

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, open-world, and non-destructive behavior, and the description adds substantial beyond-annotation detail: silent fallback from sticky_moneyness to sticky_strike, fitted unpublished decay parameters, bonds held flat unless a shift is set, FX reported under excluded rather than silently ignored, and the explicit warning to check reconciled before quoting results. No contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but every section earns its place: it front-loads the core purpose, then organizes verification, silent fallbacks, curve construction, valuation-date families, and breakdowns under clear bolded lead-ins. The depth is proportional to a 16-parameter analytical tool, and there is no tautology or padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description does not need to enumerate return fields, yet it still covers the critical ones: curves, valuationDate, dateOffsetDays, pnl_by_expiry, excluded, warnings, netLiquidation, and reconciled. It also explains verification, model provenance, and calibration state, making it complete for safe invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is high at 81%, but the description still adds real meaning: volSlopeDown is volatility points per 1% fall, vol_coord is multiplicative rather than shifted, date_offsets creates one consistent family of valuations, and breakdown='expiry' keys on settlement date. It turns parameter names into decision-relevant concepts rather than mere labels.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific deliverable: the portfolio P&L curve under several volatility regimes, positioned as the data behind a risk graph for plotting. It distinguishes itself from the single-curve sibling by emphasizing that this tool guarantees one loading of the portfolio across all scenarios.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit operational guidance: read the slope-0 curve first as the external check, prefer vol_coord unless a flat regime is specifically wanted, use fetch_skew when volSurfaceUsed is thin, and use breakdown='expiry' to see which expiry drives the trough. It also names alternatives and failure conditions, leaving little to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/simoneb/ibkr-risk-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server