- Live API Reference
- Positions & Risk
- Risk Engine
Risk Engine API: Position Risk Flags, Hedges & VaR
Post your option structures or delta-1 (CFD/shares) positions and get back machine-readable risk flags, sized hedge suggestions, VaR and stress tests - in one synchronous call. You supply only what you hold; the engine resolves spot and implied vol from live FlashAlpha data.
/docs/risk-engine.md.
Endpoint
Authenticate with your API key in the X-Api-Key header (find it on your profile page). The call is stateless: nothing about your positions is stored between calls apart from the beta telemetry noted above. Body limit 256 KB; up to 25 positions, 50 legs per position, 200 legs total, 20 distinct symbols per request.
Quick Start
Analyze a 10-lot short put. Note what is not in this request: no spot, no impliedVol. The engine resolves both from live data, nets your legs, computes dollar greeks and raises flags:
curl -X POST "https://lab.flashalpha.com/v1/risk/analyze" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"positions": [{
"symbol": "SPY",
"legs": [{
"action": "sell", "type": "put", "strike": 440,
"expiry": "2027-12-17", "quantity": 10
}]
}]
}'The response carries flags (stable codes, never prose to parse), hedges, and a portfolio rollup:
{
"status": "OK",
"as_of": "2026-10-30T13:46:42.3254082Z",
"flag_schema": "risk.flags.v1",
"flags": [
{
"code": "uncovered_short_put",
"category": "coverage",
"severity": "high",
"position_id": "position[0]",
"symbol": "SPY",
"message": "Net short put(s) not covered by long puts - large downside obligation (floored at 0).",
"data": {
"uncovered_contracts": 10
}
},
{
"code": "undefined_risk_position",
"category": "structure",
"severity": "high",
"position_id": "position[0]",
"symbol": "SPY",
"message": "Position has at least one naked short leg; maximum loss is not bounded by the legs.",
"data": null
}
],
"hedges": [
{
"ref": "portfolio",
"symbol": "SPY",
"feasible": true,
"action": "sell",
"instrument": "underlying",
"quantity": 38,
"est_cost": -28893.87,
"residual_dollar_delta": -234.861,
"rationale": "Sell 38 SPY to move SPY's net dollar-delta from 28,659 toward 0.",
"basis": "reference"
}
],
"portfolio": {
"by_symbol": [
{
"symbol": "SPY",
"dollar_delta": 28659.01,
"dollar_gamma": -1694.79,
"dollar_vega": -662.2451,
"dollar_theta": 24.5759,
"positions": 1
}
],
"dollar_delta": 28659.01,
"dollar_gamma": -1694.79,
"dollar_vega": -662.2451,
"dollar_theta": 24.5759,
"beta_weighted_dollar_delta": 28659.01,
"gross_dollar_delta": 28659.01
}
}You Only Supply Positions
spot and per-leg impliedVol are optional. Omit them and the engine resolves the live spot for each symbol and the live implied vol for each strike from FlashAlpha's own market data, using your API key so your plan's data entitlements apply. That is the whole point: you describe what you hold, the engine sources everything else.
Supply them explicitly whenever you want to pin a scenario - a what-if, a back-test, a stress at a level that is not the current market - and the engine uses your values untouched. If a value is omitted and cannot be resolved you get a 400 naming exactly which input to provide: spot_unavailable or iv_unavailable.
Prefer clicking to typing? The interactive playground builds a book from live option-chain dropdowns, runs it through the engine, and shows you the exact JSON it sent.
Request Shape
Each position carries a symbol and either option legs or a delta-1 exposure (shares/CFD). Everything else is optional: spot and per-leg impliedVol (resolved live when omitted), today (valuation date, defaults to the current US-Eastern trading date), rate, dividendYield, multiplier (default 100), beta. Optional per request:
thresholds- absolute dollar-greek limits; breaches come back asdelta_breach/gamma_breach/vega_breach/theta_breachflags.mandate.deltaTarget- a book-level target (even 0). Every position's dollar delta is netted and compared once, so one deviation flag is raised for the whole book, not one per position.include- any ofrisks,hedges,portfolio(defaults on) andmetrics(opt-in: VaR, Monte Carlo, stress grid, breakevens, assignment probabilities).
The full field-by-field schema with every validation rule is in the canonical reference, /docs/risk-engine.md.
Request body
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
positions | body | array | required | - | 1 to 25 positions, at most 20 distinct symbols. |
positions[].id | body | string | position[N] | Must be unique across the request. | |
positions[].symbol | body | string | required | - | Underlying symbol. |
positions[].spot | body | number | live spot | Omit to use the live spot. If supplied: finite and greater than 0. | |
positions[].today | body | date | current US-Eastern trading date | Valuation date, yyyy-MM-dd. A malformed value returns 400 invalid_today. | |
positions[].rate | body | number | 0.045 | Risk-free rate, -1 to 1. | |
positions[].dividendYield | body | number | 0.013 | Dividend yield, 0 to 1. | |
positions[].multiplier | body | number | 100 | Contract multiplier, greater than 0. | |
positions[].beta | body | number | 1.0 | Absolute value at most 10. | |
positions[].legs | body | array | - | Option legs. Each position needs legs or exposure. At most 50 per position and 200 per request. | |
positions[].legs[].action | body | enum | required | - | buy / long or sell / short. |
positions[].legs[].type | body | enum | required | - | call / c or put / p. |
positions[].legs[].strike | body | number | required | - | Finite and greater than 0. |
positions[].legs[].expiry | body | date | required | - | yyyy-MM-dd, not before today. |
positions[].legs[].impliedVol | body | number | live IV | Omit to use the live IV for the strike. If supplied: above 0, at most 5. | |
positions[].legs[].quantity | body | integer | required | - | 1 to 1,000,000. |
positions[].exposure | body | object | - | Delta-1 underlying, CFD or shares. | |
positions[].exposure.quantity | body | number | - | Signed; absolute value at most 1e7. | |
positions[].exposure.multiplier | body | number | 1 | Greater than 0. | |
thresholds | body | object | - | Absolute dollar limits, each greater than 0: maxAbsDollarDelta, maxAbsDollarGamma, maxAbsDollarVega, maxAbsDollarTheta. | |
mandate.deltaTarget | body | number | - | Book-level dollar-delta target (0 is a valid target). | |
include | body | array | ["risks","hedges","portfolio"] | Any of risks, hedges, portfolio, metrics. | |
metrics.horizonDays | body | integer | - | 1 to 90. Read only when metrics is included. | |
metrics.confidence | body | number | - | At least 0.5, below 1. | |
metrics.mcPaths | body | integer | - | 100 to 20,000. | |
metrics.mcSeed | body | integer | - | Monte Carlo seed; results are deterministic per seed. | |
metrics.annualVol | body | number | - | Above 0, at most 5. Required for VaR on positions without legs. |
Response Fields
Measured on 2026-10-30 with all four include groups.
| Field | Type | Description |
|---|---|---|
status | string | OK on success |
as_of | string | Timestamp of the analysis (ISO 8601, UTC) |
flag_schema | string | Flag contract version, risk.flags.v1 |
flags | array | Risk flags raised for the request. See Risk Flags |
flags[].code | string | Stable flag code |
flags[].category | string | Flag category, for example greeks or coverage |
flags[].severity | string | info, warn, high or critical |
flags[].position_id | string | The position the flag refers to, or portfolio for the whole book |
flags[].symbol | string | Underlying symbol |
flags[].message | string | Human-readable explanation |
flags[].data | object | null | Numbers behind the flag, for example uncovered_contracts, dollar_gamma, dollar_vega, dollar_theta. Keys depend on the flag; null when it has none |
hedges | array | Hedge suggestions. See Hedge Suggestions |
hedges[].ref | string | What the hedge applies to, for example portfolio |
hedges[].symbol | string | Symbol to trade |
hedges[].feasible | boolean | false when no delta-1 trade can address the problem |
hedges[].action | string | buy or sell |
hedges[].instrument | string | Instrument to trade, for example underlying |
hedges[].quantity | number | Quantity to trade |
hedges[].est_cost | number | Estimated cost in USD; negative when the trade brings in cash |
hedges[].residual_dollar_delta | number | Dollar delta left after the hedge |
hedges[].rationale | string | Why the hedge is proposed |
hedges[].basis | string | Basis used to size the hedge |
metrics | array | Per-position metrics. Only returned when include has metrics. See Metrics |
metrics[].position_id | string | Position identifier |
metrics[].symbol | string | Underlying symbol |
metrics[].model | string | Pricing model used |
metrics[].max_loss | number | null | Maximum loss; null means unbounded |
metrics[].max_profit | number | null | Maximum profit; null means unbounded |
metrics[].breakevens | array of number | Breakeven prices, measured against today's model mark |
metrics[].assignment | array | Risk-neutral assignment probabilities per net-short strike |
metrics[].assignment[].strike | number | Strike price |
metrics[].assignment[].expiry | string | Expiration date (yyyy-MM-dd) |
metrics[].assignment[].kind | string | Option kind |
metrics[].assignment[].prob_itm_at_expiry | number | Probability of finishing in the money at expiry |
metrics[].var | object | Value at risk |
metrics[].var.horizon_days | number | Horizon in days |
metrics[].var.confidence | number | Confidence level |
metrics[].var.value | number | Risk value in USD |
metrics[].var.method | string | Calculation method |
metrics[].mc_var | object | Monte Carlo value at risk |
metrics[].mc_var.horizon_days | number | Horizon in days |
metrics[].mc_var.confidence | number | Confidence level |
metrics[].mc_var.value | number | Risk value in USD |
metrics[].mc_var.method | string | Calculation method |
metrics[].mc_cvar | object | Monte Carlo conditional value at risk |
metrics[].mc_cvar.horizon_days | number | Horizon in days |
metrics[].mc_cvar.confidence | number | Confidence level |
metrics[].mc_cvar.value | number | Risk value in USD |
metrics[].mc_cvar.method | string | Calculation method |
metrics[].stress | array | Stress grid of spot and IV shocks |
metrics[].stress[].spot_pct | number | Spot shock in percent |
metrics[].stress[].iv_pts | number | IV shock in vol points |
metrics[].stress[].pnl | number | Profit or loss in USD under the shock |
portfolio | object | Portfolio rollup. Returned by default; leave portfolio out of include to drop it |
portfolio.by_symbol | array | Rollup per symbol |
portfolio.by_symbol[].symbol | string | Underlying symbol |
portfolio.by_symbol[].dollar_delta | number | Dollar delta |
portfolio.by_symbol[].dollar_gamma | number | Dollar gamma |
portfolio.by_symbol[].dollar_vega | number | Dollar vega |
portfolio.by_symbol[].dollar_theta | number | Dollar theta |
portfolio.by_symbol[].positions | number | Number of positions |
portfolio.dollar_delta | number | Book dollar delta |
portfolio.dollar_gamma | number | Book dollar gamma |
portfolio.dollar_vega | number | Book dollar vega |
portfolio.dollar_theta | number | Book dollar theta |
portfolio.beta_weighted_dollar_delta | number | Book dollar delta weighted by beta |
portfolio.gross_dollar_delta | number | Sum of absolute dollar deltas |
Risk Flags
Flags are stable enum codes under the risk.flags.v1 contract - codes are added over time, never renamed. Severities: info, warn, high, critical. Currently emitted families:
- Coverage -
uncovered_short_call,uncovered_short_put,covered_call,naked_short_underlying,non_coterminal_coverage(a protective long that expires before the short it covers). - Structure -
unbounded_loss,undefined_risk_position,defined_risk_position. - Expiry -
expired_leg_present,expiring_today_position,short_leg_expiring_today,near_expiry_position,multi_expiry_position. - Assignment & pin -
short_strike_through_spot,itm_short_near_expiry,atm_short_near_expiry_pin,pin_risk_short_strike. - Greek posture -
net_short_gamma,net_long_gamma,net_short_vega,net_long_vega,negative_theta,positive_theta,short_gamma_short_vega. - Thresholds & mandate -
delta_breach,gamma_breach,vega_breach,theta_breach,delta_target_deviation.
Hedge Suggestions
A delta-1 underlying hedge is proposed only for delta problems: a posted mandate, or a delta threshold breach (hedged toward flat).
Mandate hedges are book-level. If the whole book is one symbol, you get one concrete trade sized to move the book to the target. If it spans several symbols there is no single delta-1 instrument that closes the gap, so the engine returns an explicit feasible: false entry naming the shortfall rather than a set of per-position trades that would each overshoot the target. Threshold breaches stay per position, because a breach belongs to the position that breached it.
Gamma/vega/theta-only breaches return an explicit feasible: false entry instead of a wrong trade. Expiry-day (0DTE) legs stay live in the greeks rather than dropping to zero.
Metrics (opt-in)
Include "metrics" to get, per position: max loss / max profit (null = unbounded), breakevens, risk-neutral assignment probabilities per net-short strike, quantile VaR (full revaluation across the confidence band, so long-straddle-style interior losses are measured correctly), seeded Monte Carlo VaR/CVaR (deterministic per seed), and a 7×3 spot × IV stress grid. Model: Black-Scholes on your supplied IVs, GBM paths.
Errors
Engine errors use { "status": "ERROR", "error": "<code>", "message": "..." }. A body that is not parseable JSON gets an RFC 7807 problem-details body instead.
| Status | Error | When |
|---|---|---|
400 | spot_unavailable / iv_unavailable | You omitted spot or impliedVol and the engine could not resolve it live. The message names the symbol (and expiry / strike) to supply, for example "No live implied vol for SPY 2026-09-18 440 P. Supply "impliedVol" explicitly for this leg." |
400 | empty_request | No positions posted ("Provide at least one position."). |
400 | too_many_positions / too_many_legs / too_many_symbols / duplicate_position_id | Request-level limits: more than 25 positions, 200 legs (or 50 in one position), 20 distinct symbols, or two positions with the same id. |
400 | invalid_threshold / invalid_mandate / invalid_metrics_options | A threshold, mandate.deltaTarget or a metrics option is out of range. |
400 | invalid_symbol / invalid_spot / invalid_today / invalid_rate / invalid_dividend_yield / invalid_multiplier / invalid_beta / empty_position / invalid_exposure | A position field is invalid. The message names the position id. |
400 | invalid_action / invalid_type / invalid_strike / invalid_iv / invalid_quantity / invalid_expiry / expiry_in_past | A leg field is invalid, for example "position[0].legs[0].action must be 'buy' or 'sell'." The message names the position and leg. |
400 | - | A query value has the wrong type, or a required value is missing. The body is an RFC 7807 problem-details object with errors.<param>. |
401 | missing_api_key / invalid_api_key | No X-Api-Key header, or the key is not valid. |
413 | - | Request body over 256 KB. |
429 | rate_limited | More than 60 requests this minute for your key. Honor Retry-After. |
429 | Quota exceeded | Daily quota used up. Retry-After gives the seconds until the reset at 00:00 UTC. Rejected requests (including 403) count toward the quota. |
500 | internal_error | Unhandled server fault. Retry; contact support if it persists. |
503 | auth_unavailable | Account verification is degraded. Your key was not rejected: retry, do not rotate keys. |
All 24 validation codes with their exact conditions are tabulated in the canonical reference, /docs/risk-engine.md.
Common Use Cases
- Pre-trade checks: catch naked tails, undefined risk, and non-coterminal "protection" before an order goes out
- End-of-day book scan: pin risk and assignment exposure on everything expiring this week
- Delta-mandate monitoring: post a target once, alert on
delta_target_deviation - CFD / delta-1 books: dollar-delta rollups, beta-weighted exposure, stress grids - no option legs required
Unlock DEX, VEX and CHEX with Basic
Everything in Free, plus:
- DEX, VEX and CHEX exposure
- Full max pain
- ETF & index symbols SPY, QQQ, SPX, VIX
Go full-chain with Growth
Everything in Basic, plus:
- Full-chain GEX Every expiration
- 0DTE analytics
- Exposure summary & AI narrative
- CME futures & live screener
Add history and vol surfaces with Alpha
Everything in Growth, plus:
- Historical API replay Since 2017
- SVI vol surfaces
- VRP analytics
- Greeks surfaces Vanna, charm, volga and speed grids