API Reference¶
Comprehensive reference documentation for the Neutryx Core Python API.
Overview¶
Neutryx Core provides a complete JAX-first quantitative finance platform with:
- 500+ tests ensuring production-ready quality
- Multi-asset class coverage: Interest rates, FX, equity, credit, commodity
- Enterprise features: SSO/OAuth/MFA, Kubernetes deployment support, observability
- Regulatory compliance: FRTB SA/IMA, SA-CCR, SIMM, IFRS 9/13
- Advanced analytics: Backtesting, factor analysis, portfolio optimization
Quick Navigation¶
| Module | Description |
|---|---|
core |
Core pricing engines, Monte Carlo, PDE solvers |
models |
Stochastic models (Heston, SABR, Hull-White, etc.) |
products |
Multi-asset class derivatives products |
risk |
VaR, stress testing, Greeks, P&L attribution |
valuations |
XVA, margin, collateral, regulatory capital |
calibration |
Model calibration, regularization, diagnostics |
market |
Market data adapters, storage, validation |
research |
Backtesting, factor analysis, performance |
analytics |
Factor models, PCA, style attribution |
infrastructure |
Observability, governance, authentication |
regulatory |
FRTB, SA-CCR, SIMM, Basel III/IV |
api |
REST/gRPC endpoints, web services |
Core Modules¶
neutryx.core¶
Core computational infrastructure for pricing and risk calculations.
Key Components¶
Engine Configuration
from neutryx.core.engine import MCConfig, PDEConfig, simulate_gbm, present_value
# Monte Carlo configuration
mc_config = MCConfig(
steps=252, # Time steps
paths=100_000, # Number of paths
seed=42, # Random seed
antithetic=True # Use antithetic variates
)
# Simulate GBM paths
paths = simulate_gbm(key, S0=100.0, mu=0.05, sigma=0.2, T=1.0, config=mc_config)
# Present value calculation
pv = present_value(payoff, maturity, discount_rate)
PDE Grid Configuration
# PDE solver configuration
pde_config = PDEConfig(
spatial_points=200,
time_steps=100,
theta=0.5 # Crank-Nicolson scheme
)
neutryx.core.rng¶
Random number generation with reproducibility.
from neutryx.core.rng import PRNGManager
# Initialize PRNG with seed
prng = PRNGManager(seed=42)
key = prng.get_key()
# Split for parallel operations
keys = prng.split(n=10)
neutryx.core.grid¶
Grid generation for finite difference methods.
from neutryx.core.grid import Grid1D, Grid2D
# 1D grid for vanilla options
grid = Grid1D(xmin=0.0, xmax=200.0, nx=200)
# 2D grid for basket options
grid2d = Grid2D(
xmin=0.0, xmax=200.0, nx=100,
ymin=0.0, ymax=200.0, ny=100
)
Models¶
Equity Models¶
Black-Scholes (neutryx.models.bs)¶
from neutryx.models.bs import price, greeks, implied_volatility
# Vanilla option pricing
call_price = price(S=100, K=100, T=1.0, r=0.05, q=0.02, sigma=0.2, option_type="call")
# Greeks calculation
delta, gamma, vega, theta, rho = greeks(S=100, K=100, T=1.0, r=0.05, q=0.02, sigma=0.2)
# Implied volatility
iv = implied_volatility(price=10.5, S=100, K=100, T=1.0, r=0.05, q=0.02, option_type="call")
Heston Model (neutryx.models.heston)¶
Stochastic volatility model for equity and FX options.
from neutryx.models.heston import (
HestonParams,
characteristic_function,
price_european_call_put,
calibrate_to_surface
)
# Heston parameters
params = HestonParams(
v0=0.04, # Initial variance
theta=0.04, # Long-term variance
kappa=2.0, # Mean reversion speed
sigma_v=0.3, # Vol of vol
rho=-0.7 # Correlation
)
# Price European option
call_price = price_european_call_put(
S=100, K=100, T=1.0, r=0.05, q=0.02, params=params, option_type="call"
)
# Calibrate to market surface
calibrated_params = calibrate_to_surface(strikes, maturities, market_prices, S=100, r=0.05, q=0.02)
Local Volatility - Dupire (neutryx.models.dupire)¶
from neutryx.models.dupire import LocalVolModel, calibrate_local_vol
# Calibrate local vol surface from market
local_vol_model = calibrate_local_vol(
spot=100.0,
strikes=strikes_array,
maturities=maturities_array,
market_ivs=implied_vols_matrix
)
# Price exotic with local vol
price = local_vol_model.price_barrier(K=100, H=120, T=1.0, barrier_type="up-and-out")
Stochastic Local Volatility (neutryx.models.equity_models)¶
from neutryx.models.equity_models import SLVModel
# Hybrid SLV model
slv = SLVModel(heston_params=heston_params, local_vol_surface=local_vol)
price = slv.price_european(S=100, K=100, T=1.0)
Jump Diffusion Models¶
from neutryx.models.equity_models import (
MertonJumpDiffusion,
KouJumpDiffusion,
VarianceGammaModel
)
# Merton jump-diffusion
merton = MertonJumpDiffusion(
sigma=0.2, # Diffusion volatility
lambda_jump=0.5, # Jump intensity
mu_jump=-0.05, # Jump mean
sigma_jump=0.1 # Jump volatility
)
price = merton.price_european(S=100, K=100, T=1.0, r=0.05)
# Variance Gamma
vg = VarianceGammaModel(sigma=0.2, nu=0.1, theta=-0.1)
Interest Rate Models¶
Hull-White Model (neutryx.models.hull_white)¶
from neutryx.models.hull_white import (
HullWhite1F,
HullWhite2F,
calibrate_hw1f,
price_zero_coupon_bond
)
# 1-factor Hull-White
hw1f = HullWhite1F(a=0.1, sigma=0.01)
zcb_price = price_zero_coupon_bond(r0=0.03, T=5.0, model=hw1f)
# 2-factor Hull-White for richer term structure dynamics
hw2f = HullWhite2F(a1=0.1, a2=0.2, sigma1=0.01, sigma2=0.015, rho=-0.3)
# Calibrate to cap/floor market
calibrated_hw = calibrate_hw1f(
cap_strikes=strikes,
cap_maturities=maturities,
market_prices=prices,
curve=discount_curve
)
Black-Karasinski (neutryx.models.black_karasinski)¶
from neutryx.models.black_karasinski import BlackKarasinski, calibrate_bk
# Black-Karasinski (log-normal short rate)
bk = BlackKarasinski(a=0.1, sigma=0.15)
bond_price = bk.price_bond(T=10.0, r0=0.03)
CIR Model (neutryx.models.cir)¶
from neutryx.models.cir import CIRModel, calibrate_cir
# Cox-Ingersoll-Ross (strictly positive rates)
cir = CIRModel(kappa=0.15, theta=0.04, sigma=0.05)
bond_price = cir.bond_price(r0=0.03, T=5.0)
LMM/BGM (neutryx.models.lmm)¶
LIBOR Market Model for interest rate derivatives.
from neutryx.models.lmm import LMMModel, calibrate_lmm
# LMM with full volatility and correlation structure
lmm = LMMModel(
tenors=[0.25, 0.5, 1.0, 2.0, 5.0, 10.0],
volatilities=vol_matrix,
correlations=corr_matrix
)
# Price swaption with LMM
swaption_price = lmm.price_swaption(
strike=0.05,
option_maturity=2.0,
swap_maturity=10.0
)
G2++ Model (neutryx.models.g2pp) 🆕¶
Two-factor Gaussian interest rate model.
from neutryx.models.g2pp import G2PPModel
g2 = G2PPModel(
a=0.1, b=0.2, # Mean reversion speeds
sigma=0.01, eta=0.015, # Volatilities
rho=-0.3 # Correlation
)
FX Models¶
Garman-Kohlhagen (neutryx.models.fx_models)¶
from neutryx.models.fx_models import (
garman_kohlhagen_price,
fx_heston_price,
fx_sabr_smile
)
# FX vanilla option (Garman-Kohlhagen)
fx_call = garman_kohlhagen_price(
S=1.20, # FX spot
K=1.25, # Strike
T=1.0, # Maturity
r_dom=0.02, # Domestic rate
r_for=0.01, # Foreign rate
sigma=0.10 # Volatility
)
# FX Heston model
fx_heston = fx_heston_price(S=1.20, K=1.25, T=1.0, r_dom=0.02, r_for=0.01, heston_params=params)
# FX SABR smile
smile = fx_sabr_smile(forward=1.20, strikes=strikes, T=1.0, alpha=0.1, beta=0.5, rho=-0.3, nu=0.3)
Credit Models¶
Structural Models (neutryx.models.credit_models)¶
from neutryx.models.credit_models import (
MertonCreditModel,
BlackCoxModel,
JarrowTurnbullHazardModel
)
# Merton structural model
merton_credit = MertonCreditModel(
asset_value=100,
debt_face_value=80,
asset_volatility=0.3,
risk_free_rate=0.05,
time_to_maturity=5.0
)
default_prob = merton_credit.default_probability()
# Jarrow-Turnbull hazard rate model
jt_model = JarrowTurnbullHazardModel(hazard_rate=0.02, recovery_rate=0.4)
cds_spread = jt_model.cds_spread(T=5.0)
Copula Models¶
from neutryx.models.credit_models import (
GaussianCopula,
StudentTCopula,
LargePortfolioApproximation
)
# Gaussian copula for CDO tranches
copula = GaussianCopula(correlation=0.3, n_names=125)
tranche_loss = copula.expected_tranche_loss(
attachment=0.03,
detachment=0.07,
default_probs=default_probabilities
)
# Student-t copula for tail dependence
t_copula = StudentTCopula(correlation=0.3, degrees_of_freedom=5, n_names=125)
Adaptive Mesh Refinement 🆕¶
AMR for PDEs (neutryx.models.amr)¶
Advanced adaptive mesh refinement for PDE solvers.
from neutryx.models.amr import AMRSolver, AMRConfig
# Configure AMR
amr_config = AMRConfig(
min_level=0,
max_level=3,
refine_threshold=0.01,
coarsen_threshold=0.001
)
# Solve with adaptive refinement
solver = AMRSolver(config=amr_config)
solution = solver.solve_bs_pde(
S_range=(0, 200),
T=1.0,
K=100,
r=0.05,
sigma=0.2
)
Products¶
Vanilla Options¶
European Options (neutryx.products.base)¶
from neutryx.products.base import EuropeanOption
euro_call = EuropeanOption(
strike=100.0,
maturity=1.0,
option_type="call"
)
price = euro_call.price(spot=100, vol=0.2, rate=0.05, div_yield=0.02)
delta = euro_call.delta(spot=100, vol=0.2, rate=0.05, div_yield=0.02)
American Options (neutryx.products.american)¶
Longstaff-Schwartz Monte Carlo for early exercise.
from neutryx.products.american import AmericanOption, price_american_lsm
# American put option
american_put = AmericanOption(
strike=100.0,
maturity=1.0,
option_type="put"
)
# Price with LSM
price = price_american_lsm(
spot=100,
strike=100,
maturity=1.0,
rate=0.05,
div_yield=0.02,
vol=0.2,
option_type="put",
n_paths=100_000,
n_steps=50
)
Path-Dependent Options¶
Asian Options (neutryx.products.asian)¶
from neutryx.products.asian import AsianOption, price_asian_mc
asian = AsianOption(
strike=100.0,
maturity=1.0,
option_type="call",
averaging_type="arithmetic" # or "geometric"
)
price = price_asian_mc(spot=100, strike=100, T=1.0, r=0.05, sigma=0.2, n_paths=100_000)
Barrier Options (neutryx.products.barrier)¶
from neutryx.products.barrier import BarrierOption, price_barrier
barrier = BarrierOption(
strike=100.0,
barrier=120.0,
maturity=1.0,
barrier_type="up-and-out",
option_type="call"
)
price = price_barrier(S=100, K=100, H=120, T=1.0, r=0.05, sigma=0.2, barrier_type="up-and-out")
Interest Rate Products¶
Interest Rate Swaps (neutryx.products.interest_rate)¶
from neutryx.products.interest_rate import (
InterestRateSwap,
OISSwap,
CrossCurrencySwap,
BasisSwap
)
# Vanilla IRS
irs = InterestRateSwap(
notional=10_000_000,
fixed_rate=0.03,
tenor=5.0,
payment_freq=0.5
)
pv = irs.present_value(curve=discount_curve, forward_curve=libor_curve)
# OIS (Overnight Index Swap)
ois = OISSwap(
notional=10_000_000,
fixed_rate=0.025,
tenor=3.0,
index="SOFR" # or "ESTR", "SONIA"
)
# Cross-currency swap
ccs = CrossCurrencySwap(
notional_domestic=10_000_000,
notional_foreign=8_000_000,
fixed_rate_dom=0.03,
fixed_rate_for=0.02,
tenor=5.0,
fx_spot=1.25
)
Swaptions (neutryx.products.swaptions)¶
from neutryx.products.swaptions import (
EuropeanSwaption,
AmericanSwaption,
BermudanSwaption,
european_swaption_black
)
# European swaption (Black formula)
payer_swaption = european_swaption_black(
strike=0.05,
option_maturity=1.0,
swap_maturity=5.0,
volatility=0.20,
notional=1_000_000,
is_payer=True
)
# Bermudan swaption (LSM)
bermudan = BermudanSwaption(
strike=0.05,
notional=1_000_000,
exercise_dates=jnp.array([0.25, 0.5, 0.75, 1.0]),
tenor=5.0,
option_type='payer'
)
bermudan_price = bermudan.price_lsm(rate_paths, discount_factors)
Advanced Interest Rate Products (neutryx.products.advanced_rates)¶
from neutryx.products.advanced_rates import (
TargetRedemptionNote,
RangeAccrual,
SnowballNote,
AutocallableNote
)
# TARN (Target Redemption Note)
tarn = TargetRedemptionNote(
notional=1_000_000,
target_coupon=100_000,
coupon_rate=0.05,
payment_freq=4,
maturity=5.0
)
# Range accrual
range_accrual = RangeAccrual(
notional=1_000_000,
coupon_rate=0.06,
lower_bound=0.02,
upper_bound=0.04,
tenor=3.0
)
CMS Products (neutryx.products.interest_rate)¶
from neutryx.products.interest_rate import (
cms_caplet_price,
cms_floorlet_price,
price_cms_spread_option
)
# CMS caplet with convexity adjustment
cms_cap = cms_caplet_price(
cms_forward=0.04,
strike=0.045,
time_to_expiry=1.0,
volatility=0.25,
discount_factor=0.97,
annuity=9.0,
convexity_adjustment=0.002
)
# CMS spread option (10Y - 2Y)
spread_option = price_cms_spread_option(
cms1_forward=0.045,
cms2_forward=0.035,
strike=0.01,
time_to_expiry=1.0,
spread_volatility=0.30,
discount_factor=0.97,
annuity=4.5,
is_call=True
)
Credit Derivatives¶
Credit Default Swaps (neutryx.products.credit_derivatives)¶
from neutryx.products.credit_derivatives import (
CDS,
CDSIndex,
CDOTranche,
NthToDefault
)
# Single-name CDS
cds = CDS(
notional=10_000_000,
spread=100, # bps
maturity=5.0,
recovery_rate=0.40
)
pv = cds.present_value(hazard_rate=0.02, discount_curve=curve)
# CDX/iTraxx index
cdx = CDSIndex(
notional=10_000_000,
index_spread=80, # bps
maturity=5.0,
n_names=125
)
# CDO tranche
cdo_tranche = CDOTranche(
notional=10_000_000,
attachment=0.03,
detachment=0.07,
maturity=5.0
)
Equity Derivatives¶
Equity Forwards and Swaps (neutryx.products.equity)¶
from neutryx.products.equity import (
equity_forward_price,
variance_swap_value,
dividend_swap_price,
total_return_swap_value
)
# Equity forward
forward = equity_forward_price(
spot=100.0,
maturity=1.0,
risk_free_rate=0.05,
dividend_yield=0.02
)
# Variance swap
var_swap = variance_swap_value(
realized_variance=0.04,
strike_variance=0.0625, # 25% vol squared
notional=1_000_000,
days_remaining=252
)
Autocallables and Structured Products¶
from neutryx.products.equity_exotic import (
PhoenixAutocallable,
ReverseConvertible,
WorstOfNote
)
# Phoenix autocallable
phoenix = PhoenixAutocallable(
strike=100.0,
barrier=70.0,
coupon=0.10,
autocall_barrier=100.0,
observation_dates=[0.25, 0.5, 0.75, 1.0]
)
FX Products¶
FX Exotics (neutryx.products.fx)¶
from neutryx.products.fx import (
FXForward,
FXBarrier,
TARF,
FXAccumulator
)
# FX forward
fx_fwd = FXForward(
notional=1_000_000,
strike=1.25,
maturity=0.25
)
# TARF (Target Redemption Forward)
tarf = TARF(
notional=1_000_000,
strike=1.25,
target_profit=50_000,
observation_dates=jnp.linspace(0, 1, 12)
)
Commodity Derivatives¶
Commodity Products (neutryx.products.commodity)¶
from neutryx.products.commodity import (
commodity_forward_price,
commodity_option_price,
spread_option_price
)
# Commodity forward with convenience yield
forward = commodity_forward_price(
spot=50.0,
maturity=1.0,
risk_free_rate=0.05,
storage_cost=0.02,
convenience_yield=0.03
)
# Commodity spread option (crack spread, calendar spread)
spread = spread_option_price(
S1=50.0,
S2=55.0,
K=5.0,
T=1.0,
sigma1=0.30,
sigma2=0.25,
rho=0.6,
is_call=True
)
Risk Management¶
VaR and Risk Metrics (neutryx.risk.analytics)¶
from neutryx.risk.analytics import (
historical_var,
monte_carlo_var,
parametric_var,
expected_shortfall,
incremental_var,
component_var
)
# Historical VaR
var_95 = historical_var(returns, confidence=0.95)
var_99 = historical_var(returns, confidence=0.99)
# Expected Shortfall (CVaR)
es_95 = expected_shortfall(returns, confidence=0.95)
# Monte Carlo VaR
mc_var = monte_carlo_var(
portfolio_value=10_000_000,
returns_simulation=simulated_returns,
confidence=0.99
)
# Component VaR (risk contribution by position)
comp_var = component_var(
positions=position_weights,
covariance=cov_matrix,
portfolio_var=portfolio_var
)
Stress Testing (neutryx.risk.stress)¶
from neutryx.risk.stress import (
apply_stress_scenario,
historical_scenarios,
hypothetical_scenarios,
reverse_stress_test
)
# Historical stress scenarios
stress_results = historical_scenarios(
portfolio=portfolio,
scenarios=["2008_crisis", "covid_2020", "brexit", "lehman"]
)
# Hypothetical scenario
hypo_result = apply_stress_scenario(
portfolio=portfolio,
equity_shock=-0.30, # -30% equity
rate_shock=+0.02, # +200bps rates
fx_shock={"EURUSD": +0.10} # +10% USD strength
)
# Reverse stress testing (find scenario causing target loss)
scenario = reverse_stress_test(
portfolio=portfolio,
target_loss=1_000_000,
risk_factors=["equities", "rates", "credit_spreads"]
)
Greeks and Sensitivities¶
from neutryx.risk.greeks import (
calculate_delta,
calculate_gamma,
calculate_vega,
calculate_theta,
calculate_rho,
calculate_vanna,
calculate_volga,
calculate_charm
)
# First-order Greeks
delta = calculate_delta(portfolio, spot_shift=0.01)
vega = calculate_vega(portfolio, vol_shift=0.01)
# Second-order Greeks
gamma = calculate_gamma(portfolio, spot_shift=0.01)
volga = calculate_volga(portfolio, vol_shift=0.01) # Vega convexity
# Cross Greeks
vanna = calculate_vanna(portfolio, spot_shift=0.01, vol_shift=0.01) # dVega/dSpot
charm = calculate_charm(portfolio, spot_shift=0.01, time_shift=1/252) # dDelta/dTime
P&L Attribution (neutryx.risk.pnl_attribution)¶
from neutryx.risk.pnl_attribution import (
daily_pnl_explain,
risk_factor_attribution,
greeks_pnl_attribution
)
# Daily P&L decomposition
pnl_explain = daily_pnl_explain(
portfolio_today=portfolio_t,
portfolio_yesterday=portfolio_t1,
market_data_today=market_t,
market_data_yesterday=market_t1
)
# Returns: {carry, delta_pnl, gamma_pnl, vega_pnl, theta_pnl, unexplained}
# Risk factor attribution
factor_pnl = risk_factor_attribution(
pnl=total_pnl,
factor_changes={"equity_index": 0.02, "rates_10y": -0.0050, "fx_eurusd": 0.015}
)
Valuations & XVA¶
CVA/DVA/FVA (neutryx.valuations.xva)¶
from neutryx.valuations.xva import (
calculate_cva,
calculate_dva,
calculate_fva,
calculate_mva,
calculate_kva
)
# Credit Valuation Adjustment
cva = calculate_cva(
exposure_profile=epe_profile, # Expected Positive Exposure
survival_probability=survival_curve,
loss_given_default=0.60,
discount_curve=curve
)
# Debit Valuation Adjustment (own default)
dva = calculate_dva(
exposure_profile=ene_profile, # Expected Negative Exposure
survival_probability=own_survival_curve,
loss_given_default=0.60,
discount_curve=curve
)
# Funding Valuation Adjustment
fva = calculate_fva(
exposure_profile=exposure,
funding_spread=0.0050, # 50bps funding spread
discount_curve=curve
)
# Margin Valuation Adjustment
mva = calculate_mva(
initial_margin_profile=im_profile,
funding_spread=0.0050,
discount_curve=curve
)
# Capital Valuation Adjustment (regulatory capital cost)
kva = calculate_kva(
regulatory_capital=capital_profile,
hurdle_rate=0.12, # 12% ROE target
discount_curve=curve
)
Collateral Management (neutryx.valuations.collateral)¶
from neutryx.valuations.collateral import (
calculate_variation_margin,
calculate_initial_margin_simm,
margin_call_with_aging,
collateral_optimization
)
# Variation margin
vm = calculate_variation_margin(
mtm_today=1_500_000,
mtm_yesterday=1_200_000,
threshold=100_000,
minimum_transfer_amount=50_000
)
# Initial margin (ISDA SIMM)
im = calculate_initial_margin_simm(
portfolio=portfolio,
sensitivities=delta_gamma_vega,
simm_version="2.6"
)
# Margin call with aging
margin_call = margin_call_with_aging(
required_collateral=2_000_000,
posted_collateral=1_500_000,
outstanding_calls=outstanding,
valuation_date=date.today()
)
Collateral Transformation 🆕¶
from neutryx.valuations.collateral import (
CollateralTransformationStrategy,
optimize_collateral_basket
)
# Collateral transformation strategy
strategy = CollateralTransformationStrategy(
available_collateral={"cash_usd": 1_000_000, "us_treasury": 5_000_000},
required_collateral=3_000_000,
haircuts={"cash_usd": 0.0, "us_treasury": 0.02},
transformation_costs={"us_treasury_to_cash": 0.001}
)
optimal_allocation = strategy.optimize()
Regulatory Compliance¶
FRTB - Standardized Approach (neutryx.regulatory.frtb)¶
from neutryx.valuations.regulatory.frtb import (
calculate_delta_charge,
calculate_vega_charge,
calculate_curvature_charge,
calculate_total_sa_capital
)
# Delta risk charge
delta_rc = calculate_delta_charge(
sensitivities=delta_sensitivities,
risk_class="IR", # Interest Rate
currency="USD"
)
# Vega risk charge
vega_rc = calculate_vega_charge(
vega_sensitivities=vega_grid,
risk_class="FX"
)
# Curvature risk charge
curv_rc = calculate_curvature_charge(
curvature_sensitivities=curvature_grid,
risk_class="Equity"
)
# Total SA capital
total_sa = calculate_total_sa_capital(
delta_charge=delta_rc,
vega_charge=vega_rc,
curvature_charge=curv_rc
)
FRTB - Internal Models Approach (IMA) 🆕¶
from neutryx.regulatory.ima import (
calculate_expected_shortfall,
pla_test,
backtest_traffic_light,
identify_nmrf
)
# Expected Shortfall at 97.5%
es_97_5 = calculate_expected_shortfall(
pnl_series=daily_pnl,
confidence_level=0.975,
liquidity_horizons={"equities": 10, "rates": 20, "credit": 60}
)
# P&L Attribution Test
pla_result = pla_test(
risk_theoretical_pnl=rtpl,
hypothetical_pnl=hpl,
actual_pnl=apl
)
# Backtesting with traffic light approach
backtest_result = backtest_traffic_light(
var_forecasts=var_series,
actual_pnl=pnl_series,
confidence_level=0.99
)
# Returns: {"breaches": 5, "zone": "yellow", "multiplier": 3.4}
# Non-modellable risk factors
nmrf = identify_nmrf(
risk_factors=risk_factor_data,
real_price_test_threshold=24,
risk_factor_eligibility_test=rfet_criteria
)
FRTB - Default Risk Charge (DRC) 🆕¶
from neutryx.valuations.regulatory.frtb_drc import (
calculate_drc_non_securitizations,
calculate_drc_securitizations
)
# DRC for non-securitizations (bonds, CDS)
drc_nonsec = calculate_drc_non_securitizations(
exposures=bond_exposures,
credit_quality=rating_buckets,
gross_jt m=gross_jump_to_default,
hedging_sets=hedging_structure
)
# DRC for securitizations
drc_sec = calculate_drc_securitizations(
exposures=securitization_exposures,
attachment_points=attachment,
detachment_points=detachment
)
FRTB - Residual Risk Add-On (RRAO) 🆕¶
from neutryx.valuations.regulatory.frtb_rrao import (
calculate_rrao,
classify_exotic_products
)
# Residual Risk Add-On for exotic payoffs
rrao = calculate_rrao(
notional=10_000_000,
product_type="barrier_option",
underlying_type="FX"
)
# Returns RRAO capital charge based on product complexity
SA-CCR (neutryx.valuations.regulatory.sa_ccr)¶
from neutryx.valuations.regulatory.sa_ccr import (
calculate_replacement_cost,
calculate_pfe_addon,
calculate_ead
)
# Replacement Cost (RC)
rc = calculate_replacement_cost(
mtm=1_500_000,
independent_collateral_amount=500_000,
net_independent_collateral_amount=400_000
)
# Potential Future Exposure (PFE) Add-On
pfe = calculate_pfe_addon(
trades=netting_set_trades,
asset_class="IR",
supervisory_delta=delta,
maturity_factor=maturity_factor
)
# Exposure at Default
ead = calculate_ead(
replacement_cost=rc,
pfe_addon=pfe,
alpha=1.4 # Supervisory alpha
)
ISDA SIMM (neutryx.valuations.simm)¶
from neutryx.valuations.simm import (
calculate_simm_im,
SIMMSensitivities,
simm_risk_weights,
simm_concentration_thresholds
)
# Calculate SIMM Initial Margin
sensitivities = SIMMSensitivities(
delta=delta_grid,
vega=vega_grid,
curvature=curvature_grid
)
simm_im = calculate_simm_im(
sensitivities=sensitivities,
product_class="RatesFX",
simm_version="2.6",
calculation_currency="USD"
)
Basel III Capital (neutryx.regulatory.basel)¶
from neutryx.valuations.regulatory.basel import (
calculate_credit_rwa,
calculate_market_rwa,
calculate_cva_capital,
calculate_capital_ratios
)
# Credit Risk-Weighted Assets
credit_rwa = calculate_credit_rwa(
exposures=credit_exposures,
pd=probability_of_default,
lgd=loss_given_default,
approach="advanced_irb"
)
# CVA capital charge
cva_capital = calculate_cva_capital(
cva_amount=cva,
cva_volatility=cva_vol,
approach="ba-cva" # Basic Approach
)
# Capital ratios
ratios = calculate_capital_ratios(
cet1_capital=10_000_000,
tier1_capital=12_000_000,
total_capital=15_000_000,
rwa=100_000_000
)
# Returns: {cet1_ratio: 0.10, tier1_ratio: 0.12, total_ratio: 0.15}
IFRS 9/13 Compliance¶
from neutryx.accounting.ifrs import (
classify_fair_value_level,
calculate_ecl_staging,
hedge_effectiveness_test
)
# Fair value hierarchy classification
fv_level = classify_fair_value_level(
instrument=instrument,
market_data_availability=availability,
valuation_technique="model"
)
# Returns: "Level 1", "Level 2", or "Level 3"
# Expected Credit Loss (ECL) staging
ecl_stage = calculate_ecl_staging(
current_credit_risk=current_risk,
origination_credit_risk=origination_risk,
significant_increase_threshold=0.10
)
# Returns: 1 (12-month ECL), 2 (lifetime ECL), or 3 (credit-impaired)
# Hedge effectiveness testing
effectiveness = hedge_effectiveness_test(
hedge_pnl=hedge_pnl_series,
hedged_item_pnl=item_pnl_series,
test_type="prospective", # or "retrospective"
effectiveness_range=(0.80, 1.25)
)
Calibration¶
Model Calibration (neutryx.calibration)¶
from neutryx.calibration import (
calibrate_model,
CalibrationConfig,
LossFunction
)
# Calibration configuration
config = CalibrationConfig(
optimizer="L-BFGS-B",
max_iterations=1000,
tolerance=1e-6,
regularization="L2",
regularization_strength=0.01
)
# Calibrate model to market
calibrated_params = calibrate_model(
model=heston_model,
market_data=market_prices,
loss_fn=LossFunction.MSE,
config=config
)
Joint Calibration 🆕¶
from neutryx.calibration.joint_calibration import (
JointCalibrationFramework,
calibrate_joint_instruments
)
# Joint calibration of caps and swaptions
joint_cal = calibrate_joint_instruments(
instruments=["caps", "swaptions"],
market_prices={"caps": cap_prices, "swaptions": swaption_prices},
model=hull_white_2f,
weights={"caps": 0.6, "swaptions": 0.4} # Relative importance
)
Bayesian Model Averaging 🆕¶
from neutryx.calibration.bayesian_model_averaging import (
BayesianModelAveraging,
calculate_model_weights
)
# BMA across multiple models
bma = BayesianModelAveraging(
models=[heston, sabr, local_vol],
market_data=market_data
)
# Posterior model probabilities
weights = bma.calculate_weights(criterion="BIC")
# Returns: {heston: 0.45, sabr: 0.35, local_vol: 0.20}
# BMA price (weighted average)
bma_price = bma.price(strike=100, maturity=1.0)
Regularization Techniques¶
from neutryx.calibration.regularization import (
TikhonovRegularization,
L1Regularization,
SmoothnessConstraint,
ArbitrageFreeConstraint
)
# Tikhonov (L2) regularization
tikhonov = TikhonovRegularization(lambda_reg=0.01)
# Smoothness penalty for local vol
smoothness = SmoothnessConstraint(
penalty_strike=0.1,
penalty_maturity=0.1
)
# Enforce no-arbitrage
arbitrage_free = ArbitrageFreeConstraint(
butterfly_tolerance=0.0,
calendar_spread_tolerance=0.0
)
Model Selection and Diagnostics¶
from neutryx.calibration.model_selection import (
calculate_aic,
calculate_bic,
k_fold_cross_validation,
rolling_window_validation
)
# Information criteria
aic = calculate_aic(log_likelihood, n_params)
bic = calculate_bic(log_likelihood, n_params, n_observations)
# Cross-validation
cv_score = k_fold_cross_validation(
model=model,
data=market_data,
n_folds=5
)
# Rolling window for time-series
rolling_scores = rolling_window_validation(
model=model,
time_series=historical_prices,
window_size=252, # 1 year
forecast_horizon=20
)
Market Data¶
Bloomberg Integration (neutryx.market.adapters.bloomberg)¶
from neutryx.market.adapters import BloombergAdapter, BloombergConfig
# Configure Bloomberg adapter
config = BloombergConfig(
adapter_name="bloomberg",
host="localhost",
port=8194,
timeout=30000
)
adapter = BloombergAdapter(config)
# Fetch real-time data
await adapter.connect()
quote = await adapter.get_quote("AAPL US Equity")
# Subscribe to real-time feed
await adapter.subscribe("equity", ["AAPL", "MSFT", "GOOGL"])
Refinitiv Integration (neutryx.market.adapters.refinitiv)¶
from neutryx.market.adapters import RefinitivAdapter, RefinitivConfig
config = RefinitivConfig(
adapter_name="refinitiv",
app_key="your_app_key",
username="your_username"
)
adapter = RefinitivAdapter(config)
TimescaleDB Storage (neutryx.market.storage.timescale)¶
from neutryx.market.storage import TimescaleDBStorage, TimescaleDBConfig
# Configure TimescaleDB with compression
config = TimescaleDBConfig(
host="localhost",
port=5432,
database="market_data",
compression_enabled=True,
compression_after_days=7,
retention_policy_days=90
)
storage = TimescaleDBStorage(config)
# Store market data
await storage.store(
asset_class="equity",
symbol="AAPL",
data=quote_data,
timestamp=datetime.now()
)
# Query historical data
historical = await storage.query(
asset_class="equity",
symbols=["AAPL", "MSFT"],
start_date=start,
end_date=end
)
Data Validation (neutryx.market.validation)¶
from neutryx.market.validation import (
ValidationPipeline,
PriceRangeValidator,
SpreadValidator,
VolumeSpikeDetector
)
# Build validation pipeline
pipeline = ValidationPipeline()
pipeline.add_validator(PriceRangeValidator(max_jump_pct=0.20))
pipeline.add_validator(SpreadValidator(max_spread_bps=50))
pipeline.add_validator(VolumeSpikeDetector(threshold_sigma=5.0))
# Validate data
validation_result = pipeline.validate(market_data)
if not validation_result.is_valid:
print(f"Validation failed: {validation_result.errors}")
Research & Analytics¶
Backtesting Framework 🆕¶
from neutryx.research.backtest import (
BacktestEngine,
Strategy,
TransactionCostModel
)
# Define trading strategy
class MyStrategy(Strategy):
def generate_signals(self, data):
# Your strategy logic
return signals
def size_positions(self, signals, capital):
# Position sizing
return positions
# Configure transaction costs
cost_model = TransactionCostModel(
commission_pct=0.001, # 10bps
slippage_bps=5.0,
market_impact_model="sqrt"
)
# Run backtest
engine = BacktestEngine(
strategy=MyStrategy(),
initial_capital=1_000_000,
cost_model=cost_model
)
results = engine.run(
data=historical_data,
start_date="2020-01-01",
end_date="2023-12-31"
)
Walk-Forward Analysis 🆕¶
from neutryx.research.walk_forward import (
walk_forward_analysis,
optimize_in_sample,
validate_out_of_sample
)
# Walk-forward optimization
wf_results = walk_forward_analysis(
strategy=strategy,
data=historical_data,
in_sample_period=252, # 1 year
out_of_sample_period=63, # 3 months
step_size=21 # 1 month
)
Performance Attribution 🆕¶
from neutryx.research.performance import (
calculate_sharpe_ratio,
calculate_sortino_ratio,
calculate_calmar_ratio,
calculate_max_drawdown,
returns_attribution
)
# Performance metrics
sharpe = calculate_sharpe_ratio(returns, risk_free_rate=0.02)
sortino = calculate_sortino_ratio(returns, mar=0.0) # Minimum Acceptable Return
calmar = calculate_calmar_ratio(returns)
max_dd = calculate_max_drawdown(equity_curve)
# Returns attribution
attribution = returns_attribution(
portfolio_returns=returns,
factor_returns=factor_returns,
factor_loadings=betas
)
Analytics¶
Factor Analysis 🆕¶
from neutryx.analytics.factor_analysis import (
FactorModel,
PCA,
BarraFactorModel,
StyleAttribution
)
# Principal Component Analysis
pca = PCA(n_components=10)
factor_loadings = pca.fit(returns_matrix)
factor_returns = pca.transform(returns_matrix)
# Barra-style factor model
barra = BarraFactorModel(
style_factors=["value", "growth", "momentum", "size"],
industry_factors=["tech", "finance", "healthcare", "energy"]
)
factor_exposures = barra.calculate_exposures(stock_data)
factor_returns = barra.estimate_factor_returns(returns_data)
# Style attribution
attribution = StyleAttribution()
style_decomp = attribution.decompose(
portfolio_returns=returns,
style_exposures=exposures,
style_factor_returns=factor_returns
)
# Returns: {value: 0.02, growth: 0.015, momentum: -0.005, ...}
Portfolio Optimization¶
from neutryx.portfolio.optimization import (
MarkowitzOptimizer,
RiskParityOptimizer,
CVaROptimizer
)
# Mean-variance optimization (Markowitz)
markowitz = MarkowitzOptimizer(
expected_returns=mu,
covariance_matrix=sigma,
risk_aversion=1.0
)
optimal_weights = markowitz.optimize()
# Risk parity
risk_parity = RiskParityOptimizer(covariance_matrix=sigma)
rp_weights = risk_parity.optimize()
# CVaR optimization
cvar_opt = CVaROptimizer(
returns_scenarios=scenarios,
confidence_level=0.95,
target_return=0.10
)
cvar_weights = cvar_opt.optimize()
Infrastructure¶
Observability (neutryx.infrastructure.observability)¶
Prometheus Metrics¶
from neutryx.infrastructure.observability.prometheus import (
pricing_duration_metric,
pricing_requests_total,
active_sessions_gauge
)
# Record pricing duration
with pricing_duration_metric.time():
price = price_option(...)
# Increment request counter
pricing_requests_total.labels(product="european_call", status="success").inc()
Distributed Tracing¶
from neutryx.infrastructure.observability.tracing import (
tracer,
create_span
)
# Trace pricing workflow
with tracer.start_as_current_span("price_portfolio"):
with create_span("load_market_data"):
market_data = load_data()
with create_span("calculate_sensitivities"):
greeks = calculate_greeks(portfolio, market_data)
Performance Profiling¶
from neutryx.infrastructure.observability.profiling import (
profile_function,
ProfilerConfig
)
@profile_function(threshold_ms=100) # Profile if >100ms
def expensive_calculation():
# Your code
pass
Authentication & Authorization 🆕¶
from neutryx.infrastructure.auth import (
OAuth2Provider,
MFAProvider,
LDAPConnector,
RBACManager
)
# OAuth 2.0 / OpenID Connect
oauth = OAuth2Provider(
client_id="your_client_id",
client_secret="your_secret",
redirect_uri="https://app.neutryx.tech/callback"
)
# Multi-Factor Authentication
mfa = MFAProvider(provider="totp") # Time-based OTP
totp_secret = mfa.generate_secret()
is_valid = mfa.verify_token(user_token)
# LDAP Integration
ldap = LDAPConnector(
server="ldap://ldap.company.com",
base_dn="dc=company,dc=com"
)
user = ldap.authenticate(username, password)
# Role-Based Access Control
rbac = RBACManager()
rbac.assign_role(user_id="john.doe", role="trader")
has_permission = rbac.check_permission(user_id="john.doe", resource="portfolio", action="write")
Kubernetes Deployment 🆕¶
from neutryx.infrastructure.k8s import (
K8sDeployment,
AutoScalingConfig,
MultiRegionSetup
)
# Auto-scaling configuration
autoscaling = AutoScalingConfig(
min_replicas=2,
max_replicas=10,
target_cpu_utilization=70,
target_memory_utilization=80
)
# Multi-region deployment
multi_region = MultiRegionSetup(
regions=["us-east-1", "eu-west-1", "ap-southeast-1"],
replication_strategy="active-active",
failover_policy="automatic"
)
API Services¶
REST API (neutryx.api.rest)¶
from neutryx.api.rest import app
from fastapi import FastAPI
# Example endpoint usage
import httpx
# Price European option
response = httpx.post("http://api.neutryx.tech/v1/price/european", json={
"spot": 100,
"strike": 100,
"maturity": 1.0,
"rate": 0.05,
"vol": 0.2,
"option_type": "call"
})
price = response.json()["price"]
# Calculate portfolio VaR
response = httpx.post("http://api.neutryx.tech/v1/risk/var", json={
"portfolio_id": "PORT123",
"confidence": 0.99,
"method": "historical"
})
var_99 = response.json()["var"]
gRPC API (neutryx.api.grpc)¶
from neutryx.api.grpc import run_server
# Launch the pricing service with JWT auth and RBAC policies enabled.
run_server(
address="0.0.0.0:50051",
enable_auth=True,
exempt_methods={"HealthCheck"},
method_permissions={
"PriceVanilla": "pricing.vanilla:read",
"ComputeCVA": "xva.cva:read",
},
)
All method identifiers accept short forms like "PriceVanilla" or fully-qualified
paths such as "/neutryx.api.PricingService/PriceVanilla". When authentication is
enabled, requests must include a Bearer token in the authorization metadata
header. The RBAC mapping above enforces that only tokens with the corresponding
permission strings can invoke the protected RPCs. A ready-to-use launcher is
available at scripts/run_grpc_server.py for local experimentation.
import grpc
from google.protobuf.struct_pb2 import Struct
SERVICE_NAME = "neutryx.api.PricingService"
FULL_METHOD_NAME = f"/{SERVICE_NAME}/PriceVanilla"
async def price_vanilla(channel: grpc.aio.Channel, token: str) -> float:
stub = channel.unary_unary(
FULL_METHOD_NAME,
request_serializer=Struct.SerializeToString,
response_deserializer=Struct.FromString,
)
request = Struct()
request.update({
"spot": 100.0,
"strike": 100.0,
"maturity": 1.0,
"volatility": 0.2,
})
response = await stub(
request,
metadata=(("authorization", f"Bearer {token}"),),
)
return response.fields["price"].number_value
Exposure simulation inputs¶
The /portfolio/xva endpoint supports pathwise exposure simulation for the following
ProductType values. The market data payload must provide the listed keys to ensure
successful valuation.
| ProductType | Required market data |
|---|---|
EquityOption |
equities.{underlying}.spot, equities.{underlying}.volatility, optional equities.{underlying}.dividend, base currency rate under rates.{currency}.rate |
FxOption |
fx.{pair}.spot, fx.{pair}.volatility, domestic/foreign currencies (or inferrable from the 6-letter pair), domestic and foreign rates via fx.{pair} or rates.{currency}.rate |
InterestRateSwap |
rates.{currency}.rate, optional rates.{currency}.volatility, optional rates.{currency}.discount_curve |
Example market data payload:
{
"equities": {
"AAPL": {"spot": 100.0, "volatility": 0.2, "dividend": 0.01}
},
"fx": {
"EURUSD": {
"spot": 1.10,
"volatility": 0.15,
"domestic_currency": "USD",
"foreign_currency": "EUR"
}
},
"rates": {
"USD": {"rate": 0.03, "volatility": 0.01}
}
}
Any missing spot, volatility or rate inputs trigger 400 validation errors to make the
required data explicit.
Utilities and Helpers¶
Date and Calendar Utilities¶
from neutryx.utils.calendar import (
BusinessDayCalendar,
add_business_days,
is_business_day
)
# Create calendar
calendar = BusinessDayCalendar(country="US")
# Add business days
settlement_date = add_business_days(trade_date, days=2, calendar=calendar)
# Check if business day
is_bday = is_business_day(date, calendar=calendar)
Interpolation¶
from neutryx.utils.interpolation import (
LinearInterpolator,
CubicSplineInterpolator,
LogLinearInterpolator
)
# Linear interpolation
interp = LinearInterpolator(x=maturities, y=rates)
rate_at_2_5y = interp(2.5)
# Cubic spline (smooth curves)
spline = CubicSplineInterpolator(x=maturities, y=rates)
Day Count Conventions¶
from neutryx.utils.daycount import (
DayCountConvention,
year_fraction
)
# Common day count conventions
act_360 = DayCountConvention("ACT/360")
year_frac = year_fraction(start_date, end_date, convention=act_360)
# Other conventions: "30/360", "ACT/365", "ACT/ACT", "30E/360", etc.
Configuration¶
Config Management (neutryx.config)¶
from neutryx.config import load_config, ConfigSchema
# Load configuration from YAML
config = load_config("config/production.yaml")
# Access config values
mc_config = config["pricing"]["monte_carlo"]
n_paths = mc_config["paths"]
Testing¶
Neutryx Core includes 500+ comprehensive tests.
# Run all tests
pytest -v
# Run specific module tests
pytest src/neutryx/tests/products/ -v
pytest src/neutryx/tests/regulatory/ -v
# Run with coverage
pytest --cov=neutryx --cov-report=html
# Parallel execution
pytest -n auto # Use all CPU cores
Advanced Topics¶
Custom Model Development¶
Create custom pricing models by extending base classes:
from neutryx.models.base import StochasticModel
import jax.numpy as jnp
class MyCustomModel(StochasticModel):
def __init__(self, param1, param2):
self.param1 = param1
self.param2 = param2
def simulate_paths(self, key, S0, T, n_paths, n_steps):
# Implement your simulation logic
dt = T / n_steps
# ... simulation code ...
return paths
def price(self, payoff_fn, S0, T):
# Implement pricing
paths = self.simulate_paths(...)
payoff = payoff_fn(paths)
return jnp.mean(payoff) * jnp.exp(-self.r * T)
Custom Product Development¶
from neutryx.products.base import Product
class CustomExotic(Product):
def __init__(self, strike, barrier, maturity, **kwargs):
super().__init__(**kwargs)
self.strike = strike
self.barrier = barrier
self.maturity = maturity
def payoff(self, paths):
# Define custom payoff logic
ST = paths[:, -1]
# ... payoff calculation ...
return payoff_values
Migration Guides¶
Upgrading from v0.1.x to v1.0.0¶
Key changes: - SSO/OAuth authentication is now available - Kubernetes deployment support added - FRTB IMA, DRC, RRAO modules added - Backtesting and factor analysis modules added
For complete release history, refer to the git commit log or GitHub releases.
Further Reading¶
- Getting Started - Installation and quick start
- Tutorials - Step-by-step guides
- Architecture Guide - Platform architecture
- Developer Guide - Contributing and development
- Performance Tuning - Optimization tips
Support¶
- Documentation: https://neutryx-lab.github.io/neutryx-core/
- Issues: https://github.com/neutryx-lab/neutryx-core/issues
- Email: dev@neutryx.tech
Last updated: November 2025 | Neutryx Core v1.0.0+