Portfolio Risk
curl --request POST \
--url https://api.chicago.global/v1/portfolio/risk \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"valuation_date": "2023-12-25",
"currency": "<string>",
"nav": 123,
"positions": [
{
"id": "<string>",
"underlying": "<string>",
"quantity": 123,
"spot": 123,
"currency": "<string>",
"option": {
"strike": 123,
"expiration": "2023-12-25",
"implied_vol": 123,
"risk_free_rate": 123,
"dividend_yield": 123,
"contract_size": 123,
"payoff_type": "vanilla",
"deliverable_type": "standard",
"dividend_model": "continuous_yield",
"price_unit": "per_underlying_unit"
}
}
],
"scenarios": []
}
'import requests
url = "https://api.chicago.global/v1/portfolio/risk"
payload = {
"valuation_date": "2023-12-25",
"currency": "<string>",
"nav": 123,
"positions": [
{
"id": "<string>",
"underlying": "<string>",
"quantity": 123,
"spot": 123,
"currency": "<string>",
"option": {
"strike": 123,
"expiration": "2023-12-25",
"implied_vol": 123,
"risk_free_rate": 123,
"dividend_yield": 123,
"contract_size": 123,
"payoff_type": "vanilla",
"deliverable_type": "standard",
"dividend_model": "continuous_yield",
"price_unit": "per_underlying_unit"
}
}
],
"scenarios": []
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
valuation_date: '2023-12-25',
currency: '<string>',
nav: 123,
positions: [
{
id: '<string>',
underlying: '<string>',
quantity: 123,
spot: 123,
currency: '<string>',
option: {
strike: 123,
expiration: '2023-12-25',
implied_vol: 123,
risk_free_rate: 123,
dividend_yield: 123,
contract_size: 123,
payoff_type: 'vanilla',
deliverable_type: 'standard',
dividend_model: 'continuous_yield',
price_unit: 'per_underlying_unit'
}
}
],
scenarios: []
})
};
fetch('https://api.chicago.global/v1/portfolio/risk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.chicago.global/v1/portfolio/risk",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'valuation_date' => '2023-12-25',
'currency' => '<string>',
'nav' => 123,
'positions' => [
[
'id' => '<string>',
'underlying' => '<string>',
'quantity' => 123,
'spot' => 123,
'currency' => '<string>',
'option' => [
'strike' => 123,
'expiration' => '2023-12-25',
'implied_vol' => 123,
'risk_free_rate' => 123,
'dividend_yield' => 123,
'contract_size' => 123,
'payoff_type' => 'vanilla',
'deliverable_type' => 'standard',
'dividend_model' => 'continuous_yield',
'price_unit' => 'per_underlying_unit'
]
]
],
'scenarios' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.chicago.global/v1/portfolio/risk"
payload := strings.NewReader("{\n \"valuation_date\": \"2023-12-25\",\n \"currency\": \"<string>\",\n \"nav\": 123,\n \"positions\": [\n {\n \"id\": \"<string>\",\n \"underlying\": \"<string>\",\n \"quantity\": 123,\n \"spot\": 123,\n \"currency\": \"<string>\",\n \"option\": {\n \"strike\": 123,\n \"expiration\": \"2023-12-25\",\n \"implied_vol\": 123,\n \"risk_free_rate\": 123,\n \"dividend_yield\": 123,\n \"contract_size\": 123,\n \"payoff_type\": \"vanilla\",\n \"deliverable_type\": \"standard\",\n \"dividend_model\": \"continuous_yield\",\n \"price_unit\": \"per_underlying_unit\"\n }\n }\n ],\n \"scenarios\": []\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.chicago.global/v1/portfolio/risk")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"valuation_date\": \"2023-12-25\",\n \"currency\": \"<string>\",\n \"nav\": 123,\n \"positions\": [\n {\n \"id\": \"<string>\",\n \"underlying\": \"<string>\",\n \"quantity\": 123,\n \"spot\": 123,\n \"currency\": \"<string>\",\n \"option\": {\n \"strike\": 123,\n \"expiration\": \"2023-12-25\",\n \"implied_vol\": 123,\n \"risk_free_rate\": 123,\n \"dividend_yield\": 123,\n \"contract_size\": 123,\n \"payoff_type\": \"vanilla\",\n \"deliverable_type\": \"standard\",\n \"dividend_model\": \"continuous_yield\",\n \"price_unit\": \"per_underlying_unit\"\n }\n }\n ],\n \"scenarios\": []\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.chicago.global/v1/portfolio/risk")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"valuation_date\": \"2023-12-25\",\n \"currency\": \"<string>\",\n \"nav\": 123,\n \"positions\": [\n {\n \"id\": \"<string>\",\n \"underlying\": \"<string>\",\n \"quantity\": 123,\n \"spot\": 123,\n \"currency\": \"<string>\",\n \"option\": {\n \"strike\": 123,\n \"expiration\": \"2023-12-25\",\n \"implied_vol\": 123,\n \"risk_free_rate\": 123,\n \"dividend_yield\": 123,\n \"contract_size\": 123,\n \"payoff_type\": \"vanilla\",\n \"deliverable_type\": \"standard\",\n \"dividend_model\": \"continuous_yield\",\n \"price_unit\": \"per_underlying_unit\"\n }\n }\n ],\n \"scenarios\": []\n}"
response = http.request(request)
puts response.read_body{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Portfolio Analysis
Portfolio Risk
Full instantaneous single-currency repricing from supplied vanilla inputs (synchronous). Always includes a zero-shock baseline. Supplied scenarios report full model P&L and measured spot-only delta-gamma residuals, never guaranteed bounds. No live data, historical performance, FX, cash dividends or expiry settlement.
POST
/
v1
/
portfolio
/
risk
Portfolio Risk
curl --request POST \
--url https://api.chicago.global/v1/portfolio/risk \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"valuation_date": "2023-12-25",
"currency": "<string>",
"nav": 123,
"positions": [
{
"id": "<string>",
"underlying": "<string>",
"quantity": 123,
"spot": 123,
"currency": "<string>",
"option": {
"strike": 123,
"expiration": "2023-12-25",
"implied_vol": 123,
"risk_free_rate": 123,
"dividend_yield": 123,
"contract_size": 123,
"payoff_type": "vanilla",
"deliverable_type": "standard",
"dividend_model": "continuous_yield",
"price_unit": "per_underlying_unit"
}
}
],
"scenarios": []
}
'import requests
url = "https://api.chicago.global/v1/portfolio/risk"
payload = {
"valuation_date": "2023-12-25",
"currency": "<string>",
"nav": 123,
"positions": [
{
"id": "<string>",
"underlying": "<string>",
"quantity": 123,
"spot": 123,
"currency": "<string>",
"option": {
"strike": 123,
"expiration": "2023-12-25",
"implied_vol": 123,
"risk_free_rate": 123,
"dividend_yield": 123,
"contract_size": 123,
"payoff_type": "vanilla",
"deliverable_type": "standard",
"dividend_model": "continuous_yield",
"price_unit": "per_underlying_unit"
}
}
],
"scenarios": []
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
valuation_date: '2023-12-25',
currency: '<string>',
nav: 123,
positions: [
{
id: '<string>',
underlying: '<string>',
quantity: 123,
spot: 123,
currency: '<string>',
option: {
strike: 123,
expiration: '2023-12-25',
implied_vol: 123,
risk_free_rate: 123,
dividend_yield: 123,
contract_size: 123,
payoff_type: 'vanilla',
deliverable_type: 'standard',
dividend_model: 'continuous_yield',
price_unit: 'per_underlying_unit'
}
}
],
scenarios: []
})
};
fetch('https://api.chicago.global/v1/portfolio/risk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.chicago.global/v1/portfolio/risk",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'valuation_date' => '2023-12-25',
'currency' => '<string>',
'nav' => 123,
'positions' => [
[
'id' => '<string>',
'underlying' => '<string>',
'quantity' => 123,
'spot' => 123,
'currency' => '<string>',
'option' => [
'strike' => 123,
'expiration' => '2023-12-25',
'implied_vol' => 123,
'risk_free_rate' => 123,
'dividend_yield' => 123,
'contract_size' => 123,
'payoff_type' => 'vanilla',
'deliverable_type' => 'standard',
'dividend_model' => 'continuous_yield',
'price_unit' => 'per_underlying_unit'
]
]
],
'scenarios' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.chicago.global/v1/portfolio/risk"
payload := strings.NewReader("{\n \"valuation_date\": \"2023-12-25\",\n \"currency\": \"<string>\",\n \"nav\": 123,\n \"positions\": [\n {\n \"id\": \"<string>\",\n \"underlying\": \"<string>\",\n \"quantity\": 123,\n \"spot\": 123,\n \"currency\": \"<string>\",\n \"option\": {\n \"strike\": 123,\n \"expiration\": \"2023-12-25\",\n \"implied_vol\": 123,\n \"risk_free_rate\": 123,\n \"dividend_yield\": 123,\n \"contract_size\": 123,\n \"payoff_type\": \"vanilla\",\n \"deliverable_type\": \"standard\",\n \"dividend_model\": \"continuous_yield\",\n \"price_unit\": \"per_underlying_unit\"\n }\n }\n ],\n \"scenarios\": []\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.chicago.global/v1/portfolio/risk")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"valuation_date\": \"2023-12-25\",\n \"currency\": \"<string>\",\n \"nav\": 123,\n \"positions\": [\n {\n \"id\": \"<string>\",\n \"underlying\": \"<string>\",\n \"quantity\": 123,\n \"spot\": 123,\n \"currency\": \"<string>\",\n \"option\": {\n \"strike\": 123,\n \"expiration\": \"2023-12-25\",\n \"implied_vol\": 123,\n \"risk_free_rate\": 123,\n \"dividend_yield\": 123,\n \"contract_size\": 123,\n \"payoff_type\": \"vanilla\",\n \"deliverable_type\": \"standard\",\n \"dividend_model\": \"continuous_yield\",\n \"price_unit\": \"per_underlying_unit\"\n }\n }\n ],\n \"scenarios\": []\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.chicago.global/v1/portfolio/risk")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"valuation_date\": \"2023-12-25\",\n \"currency\": \"<string>\",\n \"nav\": 123,\n \"positions\": [\n {\n \"id\": \"<string>\",\n \"underlying\": \"<string>\",\n \"quantity\": 123,\n \"spot\": 123,\n \"currency\": \"<string>\",\n \"option\": {\n \"strike\": 123,\n \"expiration\": \"2023-12-25\",\n \"implied_vol\": 123,\n \"risk_free_rate\": 123,\n \"dividend_yield\": 123,\n \"contract_size\": 123,\n \"payoff_type\": \"vanilla\",\n \"deliverable_type\": \"standard\",\n \"dividend_model\": \"continuous_yield\",\n \"price_unit\": \"per_underlying_unit\"\n }\n }\n ],\n \"scenarios\": []\n}"
response = http.request(request)
puts response.read_body{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Full instantaneous, single-currency repricing of a portfolio of supplied
vanilla positions (stocks, ETFs, and European or American options), from
caller-supplied spot and implied-vol inputs. Synchronous — no job ID.
With an option position, each scenario’s
This never substitutes option deltas into historical returns, and uses no
live market data. Every price and Greek comes from what you send in the
request. A
baseline scenario (no shocks) is always included alongside any
scenarios you supply.Request Body
| Field | Type | Required | Description |
|---|---|---|---|
valuation_date | string (date) | Yes | As-of date for the repricing. |
currency | string | Yes | 3-letter currency code. Must match every position’s currency. |
nav | number | Yes | Portfolio NAV, must be positive. |
positions | array of Holding | Yes | 1–100 positions. Position id values must be unique. |
scenarios | array of Scenario | No | 0–20 scenarios. IDs must be unique and not baseline (reserved). |
Holding object:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Caller-assigned position identifier, unique within the request. |
asset_type | string | Yes | stock, etf, or option. |
underlying | string | Yes | RIC of the underlying. |
quantity | number | Yes | Signed position size. Integer-valued for options. |
spot | number | Yes | Spot price, must be positive. Positions sharing an underlying must share the same spot. |
currency | string | Yes | 3-letter code, must match the request’s currency. |
option | Contract object | Required only when asset_type is option | Option terms (see below). |
Contract object (option terms). Every field below is required whenever
option is present; there are no optional or defaulted fields in this object:
| Field | Type | Description |
|---|---|---|
option_type | string | call or put. |
option_style | string | european or american. |
strike | number | Positive. |
expiration | string (date) | Must be after valuation_date. |
implied_vol | number | Positive. |
risk_free_rate | number | |
dividend_yield | number | |
contract_size | integer | 1–100,000. |
settlement_type | string | am or pm. |
underlying_type | string | equity, index, or etf. |
payoff_type | string | vanilla (only value accepted). |
deliverable_type | string | standard (only value accepted). |
dividend_model | string | continuous_yield (only value accepted). |
price_unit | string | per_underlying_unit (only value accepted). |
Scenario object:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique, not baseline. |
spot_shocks | object | No | Map of underlying RIC to fractional spot shock (must exceed -1). Up to 100 entries. |
vol_shocks | object | No | Map of underlying RIC to additive implied-vol shock. Up to 100 entries. |
Request-size caps: positions × (scenarios + 1) ≤ 500 position-scenarios, and
American-style option valuations ≤ 40 across the request (scaled by
scenario count). A scenario naming an underlying not in
positions is
rejected.Response
Every position, in every scenario, carriesbase_greeks and position_risk,
whether it’s a stock, ETF, or option. If no position has asset_type: "option",
these are computed directly (exact stock arithmetic) and come out trivial
for stocks and ETFs (delta 1, all other Greeks 0, as in the example below).
With any option position, every position in the request is priced through
the same options-pricing path instead, so Greeks stay additive across the
book.
{
"schema_version": 1,
"valuation_date": "2026-11-04",
"currency": "USD",
"nav": 1000000,
"assumptions": [
"instantaneous",
"single_currency_no_fx_conversion",
"whole_day_actual_365",
"continuous_dividend_yield",
"flat_rates",
"fixed_strike_additive_volatility",
"model_to_model_pnl",
"no_constituent_lookthrough"
],
"market_status": "not_checked",
"underlying_exposures": [
{ "underlying": "AAPL.O", "delta_equivalent_units": 500, "dollar_delta": 95000, "delta_weight": 0.095 }
],
"scenarios": [
{
"id": "baseline",
"total_pnl": 0,
"pnl_fraction_nav": 0,
"delta_gamma_pnl": 0,
"approximation_residual": 0,
"approximation_status": "measured_spot_only_residual_not_bound",
"positions": [
{
"position_id": "pos-1",
"underlying": "AAPL.O",
"asset_type": "stock",
"quantity": 500,
"multiplier": 1,
"base_price": 190,
"base_greeks": { "delta": 1, "gamma": 0, "vega": 0, "theta": 0, "rho": 0 },
"position_risk": { "delta_equivalent_units": 500, "dollar_delta": 95000, "gamma_per_price_unit_squared": 0, "vega_per_vol_point": 0, "theta_per_calendar_day": 0, "rho_per_rate_point": 0 },
"scenario_price": 190,
"pnl": 0,
"delta_gamma_pnl": 0
}
]
}
],
"input_source": "caller_supplied_unverified",
"positions": [ { "id": "pos-1", "asset_type": "stock", "underlying": "AAPL.O", "quantity": 500, "spot": 190, "currency": "USD", "option": null } ]
}
positions[] row also carries
contract_eligibility and pricing_diagnostics; see the response example
for exact field presence, which varies by position.
Errors
| Status | Code | When |
|---|---|---|
422 | invalid_pricing_inputs | Request fails pricing validation. |
422 | pricing_unresolved | A price could not be resolved; pricing_diagnostics explains why. |
503 | pricing_unavailable | Option pricing is unavailable (option positions only; stock-only requests are unaffected). |
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
application/json
Response
Successful Response
Last modified on November 6, 2026
⌘I