Skip to main content

pyvar-client

Python SDK for pyvar.com's open-source risk computation API — 385 functions across 8 domains, one typed client.

Status: v0.2.0-track, built ahead of its originally planned schedule (see docs/pyvar_release_plan.md in the main repo). Alpha — the API surface may still change before a 1.0 release.

Install

pip install pyvar-client

Quick start

from pyvar_client import Client

client = Client(api_key="eyJ...")  # a JWT obtained via pyvar.com registration + email verification

result = client.market_risk.historical_simulation_var(
    returns=[...],  # historical daily log-returns
    portfolio_value=1_000_000,
    confidence_level=0.99,
)
print(result["var_pct"], result["var_abs"])

Or as a context manager, which closes the underlying connection pool on exit:

with Client(api_key="eyJ...") as client:
    ...

The one async function: Monte Carlo VaR

Every domain function is synchronous request/response — call it, get the result. POST /var/compute is the one exception: it's a real Monte Carlo job dispatched to pyvar's Celery/SQS worker fleet, so it returns a task_id immediately instead of a result. client.var wraps that:

# Blocks: submits, polls until done, returns the finished result.
result = client.var.compute(
    portfolio_value=1_000_000,
    returns=[...],
    n_simulations=100_000,
)

# Or drive it yourself:
task_id = client.var.submit(portfolio_value=1_000_000, returns=[...])
status = client.var.poll(task_id)  # check once, no blocking

Above a simulation-count threshold, the API offloads the full loss distribution to S3 and returns a presigned_url instead of the inline loss_dist — compute() returns exactly what the API returned either way; fetching a presigned URL is a plain httpx.get() if you want the raw distribution.

Errors

Every non-2xx response raises a typed exception, not a generic HTTP error:

Exception Status Notes
PyvarAuthError 401 Token missing, invalid, or expired. Register/verify at pyvar.com to get a new one — this client doesn't automate that flow.
PyvarValidationError 422 .detail carries the field-level validation errors.
PyvarRateLimitError 429 .retry_after (seconds) from the response's Retry-After header.
PyvarComputeError — A VaR job (client.var.compute) reached status="failure" server-side. .task_id and .detail.
PyvarTimeoutError — A VaR job didn't finish within poll_timeout_seconds. .task_id — poll it again later, the job may still complete.
PyvarError any other 4xx/5xx Base class for everything above; catch this if you just want "did it fail".
from pyvar_client import Client, PyvarValidationError, PyvarRateLimitError

try:
    client.market_risk.historical_simulation_var(returns=[...], portfolio_value=1_000_000)
except PyvarValidationError as e:
    print(e.detail)
except PyvarRateLimitError as e:
    print(f"retry after {e.retry_after}s")

Retries

Every synchronous domain function is idempotent (pure compute, no side effects) — connection errors, timeouts, and 5xx responses are retried automatically with exponential backoff. client.var.submit() is the one call that's never auto-retried: retrying a job submission blindly risks double-submitting real compute work, since the API has no idempotency-key mechanism to de-duplicate on. Polling (client.var.poll()) is a read, so it retries normally.

Domains

client.market_risk, client.derivatives, client.credit_risk, client.portfolio, client.operational_risk, client.liquidity_risk, client.alm, client.regulatory — one namespace per domain, one method per function. See portal/functions.json in the main repo for the full, live list, or just use your editor's autocomplete — every method is fully typed.

CLI

pip install pyvar-client also installs a pyvar command — stdlib argparse only, no extra install step, no extras group. It's a thin, generic dispatcher over the same Client namespaces above: pyvar <domain> <function> --params file.json resolves to client.<domain>.<function>(**params), so every current and future method works without the CLI needing its own copy of the 385-method catalogue.

export PYVAR_API_KEY="eyJ..."   # or pass --api-key on every call

pyvar market_risk historical_simulation_var --params-json \
    '{"returns": [0.01, -0.02, 0.015], "portfolio_value": 1000000}'

# Or from a file, or piped in via stdin with --params -
pyvar market_risk historical_simulation_var --params params.json

Calling a function with neither --params nor --params-json prints its docstring and signature instead of making a doomed API call with zero fields — handy when you don't remember what a function needs:

$ pyvar market_risk historical_simulation_var --api-key "$PYVAR_API_KEY"
historical_simulation_var(*, returns: list[float] | list[list[float]], portfolio_value: float, ...) -> dict[str, Any]

Historical simulation VaR from empirical return distribution.
...

The one async function gets its own submit/poll/compute sub-subcommands, matching client.var exactly:

pyvar var compute --params var_params.json          # blocks: submit + poll + return
pyvar var submit --params var_params.json           # returns immediately: {"task_id": "..."}
pyvar var poll <task_id>                            # checks once, no blocking
pyvar var compute --params var_params.json --poll-interval 1 --poll-timeout 60

Discover what's available without any credentials at all:

pyvar list-domains
pyvar list-functions --domain market_risk

Exit codes distinguish failure modes for scripting, mirroring the exception table above:

Exit code Meaning
0 Success (or a docstring/help display)
1 Bad input — unknown domain/function, malformed --params, missing/wrong keyword arguments, or any other non-auth/validation/rate-limit/compute API error
2 PyvarAuthError (401)
3 PyvarValidationError (422) — field errors printed to stderr
4 PyvarRateLimitError (429) — retry_after printed to stderr
5 PyvarComputeError / PyvarTimeoutError — task_id printed to stderr
130 Interrupted (Ctrl-C)

How the domain methods are generated

385 methods is too much to hand-maintain without drifting from the API (see docs/p9-function-catalogue-reconciliation.md in the main repo for a real instance of exactly that drift). pyvar_client/_generated/ is produced by codegen/generate.py, which reads the live OpenAPI schema (main.create_app().openapi()) directly — regenerate after any API schema change:

python3 codegen/generate.py

This needs the main repo's own dependencies installed (it imports main.create_app() directly), so run it from a checkout with requirements.txt

  • requirements-heavy.txt installed, not just this package's own runtime deps.

Development

pip install -e ".[dev]"
pytest -v --cov=pyvar_client --cov-report=term-missing
black --check --line-length 100 .
isort --check-only --profile black .
ruff check .

No real HTTP calls anywhere in the test suite — httpx.MockTransport intercepts every request, so the real retry/error-mapping/auth logic runs against a handler the tests control, never a live server. See tests/conftest.py.

License

Apache License 2.0 — see LICENSE. Same license as the main pyvar.com repository.

Release files for pyvar-client 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyvar-client 0.1.2
File Size Uploaded
pyvar_client-0.1.2.tar.gz 96.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyvar-client 0.1.2
File Interpreter ABI Platform
pyvar_client-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 193.0 kB

Release files / pyvar_client-0.1.2.tar.gz

Download URL pyvar_client-0.1.2.tar.gz
Size 96.9 kB
Tags Source
SHA-256 checksum
How to use checksums
2afd6ad353eaf5a250067aa27404ea50c11aefcffe9e488110f9469c8f16916b
BLAKE2b-256 checksum
How to use checksums
285f62ae0b8c05f6292f2b821878e907188feff105b9ba58639eb143f49b9ee3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 24, 2026.

Transparency log

Release files / pyvar_client-0.1.2-py3-none-any.whl

Download URL pyvar_client-0.1.2-py3-none-any.whl
Size 96.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f57d4ac650468538b38e9a6fe642af685e41d77c2025e87fa111cc4ba1707c31
BLAKE2b-256 checksum
How to use checksums
1d8692faef6a7f9294999ebe739ff065c52ec8d15cbfb44af72b7dfaf725ebe6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page