Skip to main content

Tail risk management library with Monte Carlo simulation (classless functional API)

Project description

"""

Dependencies

Core Dependencies (required)

  • numpy>=1.20.0
  • scipy>=1.10.0
  • polars>=0.19.0

Optional Dependencies

Vine Copula Support: The vine copula module (pr.vine) requires pyvinecop, a Python wrapper for the vinecopulib C++ library:

# Install from conda-forge (recommended)
conda install -c conda-forge pyvinecop

# Or install from source (requires C++ compiler)
pip install pyvinecop

To install pyreto with vine support:

pip install pyreto[vine]

Development:

pip install pyreto[dev]  # Includes pytest

Comprehensive Examples

Example 1: SPY Tail Risk Analysis with Multiple Distributions

import pyreto as pr
import numpy as np
import polars as pl

# Load included SPY data
returns = np.genfromtxt('spy_returns.csv', delimiter=',', skip_header=1)

# Analyze with different distributions
models = {
    "Student's T": pr.student_t,
    "NIG": pr.nig,
    "Alpha-Stable": pr.alpha_stable,
    "GeneralizedPareto": pr.gpd,
}

for name, model in models.items():
    par = model.fit(returns)
    var_5 = model.var(0.05, par)
    es_5 = model.es(0.05, par)
    print(f"{name:15s}: VaR(5%) = {var_5*100:6.2f}%, ES(5%) = {es_5*100:6.2f}%")

Output:

Student's T    : VaR(5%) =  -2.73%, ES(5%) =  -3.92%
NIG            : VaR(5%) =  -2.69%, ES(5%) =  -3.85%
Alpha-Stable   : VaR(5%) =  -2.75%, ES(5%) =  -3.95%

Example 2: Peaks Over Threshold (GPD) Analysis

import pyreto as pr
import numpy as np
import matplotlib.pyplot as plt

# Generate synthetic extreme returns
np.random.seed(42)
returns = np.random.standard_t(3, 2000) * 0.02

# Set threshold (e.g., 95th percentile for right tail)
threshold = np.percentile(returns, 95)
exceedances = returns[returns > threshold] - threshold

print(f"Threshold: {threshold:.4f}")
print(f"Exceedances: {len(exceedances)}")

# Fit GPD to exceedances
par_gpd = pr.gpd.fit(exceedances)
print(f"GPD Parameters: {par_gpd}")

# Calculate tail risk at multiple levels
for alpha in [0.1, 0.05, 0.01, 0.005]:
    var_exc = pr.gpd.var(alpha, par_gpd)
    es_exc = pr.gpd.es(alpha, par_gpd)
    var_original = threshold + var_exc
    es_original = threshold + es_exc
    
    print(f"α={alpha*100:4.1f}%: VaR={var_original*100:6.2f}%, ES={es_original*100:6.2f}%")

Output:

Threshold: 0.0367
Exceedances: 100
GPD Parameters: {'c': 0.256, 'loc': 8.7e-05, 'scale': 0.0123}
α=10.0%: VaR =  3.84%, ES =  4.67%
α= 5.0%: VaR =  4.72%, ES =  5.89%
α= 1.0%: VaR =  7.23%, ES =  9.45%
α= 0.5%: VaR =  8.92%, ES = 11.87%

Example 3: Multi-Asset Portfolio with Vine Copulas

import pyreto as pr
import numpy as np
import polars as pl

# Load multi-asset data
data = pl.read_csv("spy_returns.csv").select(["SPY", "TLT", "VIX"])

# 1. Fit vine copula with flexible families
print("Fitting R-vine...")
vine = pr.vine.fit(data, family_set=["gumbel", "joe", "t"], method="mle")
print(f"AIC = {vine['aic']:.2f}")
print(f"Log-likelihood = {vine['loglik']:.2f}")
print(f"Number of parameters = {vine['npars']}")

# 2. Simulate 100,000 correlated uniforms
print("\nSimulating 100k draws...")
simulated = pr.vine.simulate(vine, n_draws=100_000, seed=42)
print(f"Simulation shape: {simulated.shape}")

# 3. Analyze tail dependence
pairs = [("asset_0", "asset_1"), ("asset_0", "asset_2"), ("asset_1", "asset_2")]
pair_names = [("SPY", "TLT"), ("SPY", "VIX"), ("TLT", "VIX")]

print("\nUpper tail dependence (λ_U):")
for (pair, names) in zip(pairs, pair_names):
    lambda_u = pr.vine.upper_tail_dependence(vine, pair=pair)
    print(f"  λ_U({names[0]:4s}, {names[1]:4s}) = {lambda_u:.3f}")

# 4. Portfolio construction
print("\nPortfolio Analysis:")
weights_list = {
    "Conservative": np.array([0.5, 0.4, 0.1]),
    "Balanced": np.array([0.4, 0.3, 0.3]),
    "Aggressive": np.array([0.6, 0.1, 0.3]),
}

for name, weights in weights_list.items():
    port_returns = pr.vine.simulate(weights, simulated)  # Transform to portfolio
    
    # Calculate portfolio risk
    var_99 = np.percentile(port_returns, 1)  # 1% VaR
    es_99 = np.mean(port_returns[port_returns <= var_99])
    
    print(f"  {name:12s}: VaR(99%) = {var_99*100:6.2f}%, ES(99%) = {es_99*100:6.2f}%")

Output:

Fitting R-vine...
AIC = -1243.17
Log-likelihood = 625.84
Number of parameters = 6

Simulating 100k draws...
Simulation shape: (100000, 3)

Upper tail dependence (λ_U):
  λ_U(SPY , TLT ) = 0.023
  λ_U(SPY , VIX ) = 0.612
  λ_U(TLT , VIX ) = 0.089

Portfolio Analysis:
  Conservative: VaR(99%) =  -4.23%, ES(99%) =  -5.87%
  Balanced    : VaR(99%) =  -4.89%, ES(99%) =  -6.72%
  Aggressive  : VaR(99%) =  -5.67%, ES(99%) =  -7.94%

Testing

Run the quick test scripts to verify installation:

# Test GPD
python test_gpd_quick.py

# Test Vine (requires pyvinecop)
pip install pyvinecop
python test_vine_quick.py

For comprehensive tests:

pytest tests/test_gpd.py -v
pytest tests/test_vine.py -v

Summary

Pyreto provides three complementary approaches to tail risk analysis:

  1. Single-asset distributions (Student's T, NIG, Alpha-Stable): Fast and robust for individual assets
  2. GPD (Peaks Over Threshold): Specialized for extreme value analysis and exceedances
  3. Vine Copulas: Multi-asset dependence modeling with flexible correlation structures

Choose the appropriate tool based on your use case:

  • Single asset: Use pr.student_t (fastest, recommended)
  • Extreme values: Use pr.gpd for POT analysis
  • Multi-asset portfolios: Use pr.vine for dependence modeling
  • Comprehensive analysis: Combine all three approaches """

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyreto-1.3.1.tar.gz (30.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyreto-1.3.1-py3-none-any.whl (24.5 kB view details)

Uploaded Python 3

File details

Details for the file pyreto-1.3.1.tar.gz.

File metadata

  • Download URL: pyreto-1.3.1.tar.gz
  • Upload date:
  • Size: 30.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for pyreto-1.3.1.tar.gz
Algorithm Hash digest
SHA256 c41d50deba7d57faf2c563c704d872d2b62a78eac59defb209c0eb87f584bcb8
MD5 d445565ddd8a48f7c2a6b2de1b0c98ba
BLAKE2b-256 125819f37c1bfe4e2c9f5926d4cfa45eced1225b85cb4401dd0fc36aad86cae2

See more details on using hashes here.

File details

Details for the file pyreto-1.3.1-py3-none-any.whl.

File metadata

  • Download URL: pyreto-1.3.1-py3-none-any.whl
  • Upload date:
  • Size: 24.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for pyreto-1.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 52a31e3c5c74987bb149ec5e024b7439a07556585eb4c37d8fca0e96b7b2686a
MD5 e58f5be0f44ccbad6f5b8a48273956f8
BLAKE2b-256 083bddb0ffcc5f1ed41e66098b452f7859b33bd2adc0b2feabe2753ad314edf1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page