Auditable NumPy implementation and partial replication of deep hedging
Project description
ASR Deep Hedging
Auditable neural option hedging under transaction costs
A transparent NumPy library for discrete-time option hedging, exact empirical CVaR optimization, transaction-cost modelling, and reproducible simulation experiments.
Installation · Library quick start · Public API · Experiments · Manuscript
Overview
asr-deep-hedging is an installable research library for studying neural hedging under discrete rebalancing and transaction costs. It is designed for researchers, students, and quantitative developers who need an implementation whose loss convention, risk estimator, simulation scheme, policy gradients, and evaluation protocol can be inspected directly.
The repository combines:
- the installable distribution
asr-deep-hedging; - the Python import package
deep_hedging; - Geometric Brownian Motion and Heston simulators;
- proportional and quadratic transaction costs;
- exact finite-sample empirical CVaR weighting;
- state-only and inventory-aware neural policies;
- manual NumPy forward and backward passes;
- classical hedging benchmarks and evaluation utilities;
- automated tests, reproducible configurations, figures, and manuscript sources.
Scientific scope. This software is intended for methodological research, numerical validation, and reproducibility. The legacy numerical values retained in
results/legacy/are exploratory single-run outputs. They are not evidence of general trading superiority and are not intended for live trading or investment decisions.
Package identity
The name used by pip is different from the name used in Python imports:
Distribution name: asr-deep-hedging
Import package: deep_hedging
Current version: 0.1.0
Required Python: 3.11 or newer
After installation, import the library as follows:
import deep_hedging
print(deep_hedging.__version__)
Expected output:
0.1.0
Installation
Current installation from GitHub
Until the first public PyPI release is completed, install the package directly from the ASR repository:
python -m pip install --upgrade pip
python -m pip install \
"asr-deep-hedging @ git+https://github.com/Alpha-Stochastic-Research/asr-deep-hedging.git"
After the corresponding release tag exists, install that exact version with:
python -m pip install \
"asr-deep-hedging @ git+https://github.com/Alpha-Stochastic-Research/asr-deep-hedging.git@v0.1.0"
PyPI installation
Once version 0.1.0 has been published to PyPI, the standard installation command will be:
python -m pip install asr-deep-hedging
The PyPI workflow is already included in the repository, but the command above becomes publicly available only after the first release has successfully been published.
Installation from a wheel
Build or download the wheel, then run:
python -m pip install ./asr_deep_hedging-0.1.0-py3-none-any.whl
Editable development installation
git clone https://github.com/Alpha-Stochastic-Research/asr-deep-hedging.git
cd asr-deep-hedging
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'
On Windows PowerShell:
python -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
Conda
conda env create -f environment.yml
conda activate asr-deep-hedging
python -m pip install -e '.[dev]'
Docker
docker build -t asr-deep-hedging .
docker run --rm asr-deep-hedging
Library quick start
Simulate GBM paths and compute empirical CVaR
import numpy as np
from deep_hedging import empirical_cvar, simulate_gbm
prices = simulate_gbm(
n_paths=20_000,
n_steps=30,
s0=100.0,
maturity=30 / 252,
mu=0.0,
sigma=0.20,
seed=42,
)
strike = 100.0
losses = np.maximum(prices[:, -1] - strike, 0.0)
cvar_95 = empirical_cvar(losses, alpha=0.95)
print(f"Empirical CVaR 95%: {cvar_95:.6f}")
simulate_gbm returns an array with shape (n_paths, n_steps + 1). The first column contains the initial spot and the final column contains the terminal spot.
Evaluate a Black--Scholes delta hedge
from deep_hedging import (
black_scholes_delta,
evaluate_positions,
simulate_gbm,
)
maturity = 30 / 252
prices = simulate_gbm(
n_paths=30_000,
n_steps=30,
s0=100.0,
maturity=maturity,
sigma=0.20,
seed=2026,
)
deltas = black_scholes_delta(
prices,
strike=100.0,
maturity=maturity,
sigma=0.20,
)
metrics, losses = evaluate_positions(
prices,
deltas,
strike=100.0,
kappa=0.01,
cost_kind="linear",
alpha=0.95,
)
for name, value in metrics.items():
print(f"{name}: {value}")
Returned metrics include the number of paths, mean loss, loss standard deviation, empirical VaR, empirical CVaR, average absolute trade, and mean total transaction cost.
Train one state-only neural policy step
from deep_hedging import Adam, TanhMLP, simulate_gbm, train_step
maturity = 30 / 252
network = TanhMLP(input_dim=2, hidden=16, delta_max=1.5, seed=1)
optimizer = Adam(network.params, lr=3e-3)
prices = simulate_gbm(
n_paths=4_096,
n_steps=30,
s0=100.0,
maturity=maturity,
sigma=0.20,
seed=100,
)
cvar, losses, deltas, details, grad_norm = train_step(
network,
optimizer,
prices=prices,
strike=100.0,
maturity=maturity,
alpha=0.95,
kappa=0.01,
cost_kind="linear",
)
print(f"CVaR: {cvar:.6f}")
print(f"Gradient norm: {grad_norm:.6f}")
print(f"Positions shape: {deltas.shape}")
For GBM, the state-only policy uses two inputs: normalized time to maturity and log-moneyness.
Main capabilities
Market simulation
- Exact grid-point Geometric Brownian Motion simulation.
- Full-truncation Euler variance dynamics with log-Euler spot updates for Heston.
- Reproducible random seeds.
- Optional Heston substepping.
- Diagnostics for auxiliary variance states and terminal variance.
Risk and loss functions
- Exact empirical CVaR for finite samples.
- Fractional weighting at the empirical tail boundary.
- Stable sorting for deterministic tie handling.
- Empirical VaR.
- Terminal hedging loss and pathwise position gradients.
- Proportional and quadratic transaction costs.
- Optional initial premium and terminal liquidation cost.
Neural policies
- Shared-weight two-hidden-layer
tanhnetwork. - State-only target-position policy.
- Inventory-aware semi-recurrent policy.
- Manual feedforward and backward passes.
- Backpropagation through the inventory state.
- NumPy implementation of Adam.
Benchmarks and evaluation
- No hedge.
- Black--Scholes delta.
- Shrunk Black--Scholes delta.
- Reduced-frequency rebalancing.
- No-trade-band rule.
- Instantaneous-volatility delta under stochastic volatility.
- Mean loss, standard deviation, VaR, CVaR, turnover, and transaction-cost metrics.
- Paired bootstrap confidence intervals for CVaR differences.
Core mathematical conventions
Terminal loss
For a short European call with payoff H(S_T), initial premium p_0, positions delta_k, and transaction costs c_k, the implemented terminal loss is:
L_T
=
H(S_T)-p_0
-
\sum_{k=0}^{n-1}\delta_k\left(S_{k+1}-S_k\right)
+
\sum_k c_k\left(\delta_k-\delta_{k-1}\right).
The default numerical convention uses premium=0.0 and terminal_liquidation=False.
Exact empirical CVaR
For losses sorted from largest to smallest,
L_{[1]} \geq L_{[2]} \geq \cdots \geq L_{[B]},
let
q=(1-\alpha)B,
\qquad
r=\lfloor q\rfloor,
\qquad
\lambda=q-r.
The library computes:
\widehat{\mathrm{CVaR}}_{\alpha,B}
=
\frac{1}{q}
\left(
\sum_{j=1}^{r}L_{[j]}
+
\lambda L_{[r+1]}
\right),
with the fractional boundary term omitted when lambda = 0. The same weights are used to construct a valid empirical subgradient away from sorting ties.
Detailed library examples
Compute hedging losses and position gradients
import numpy as np
from deep_hedging import hedging_loss_and_gradient, simulate_gbm
prices = simulate_gbm(
n_paths=5_000,
n_steps=30,
s0=100.0,
maturity=30 / 252,
sigma=0.20,
seed=7,
)
deltas = np.zeros((prices.shape[0], prices.shape[1] - 1))
losses, position_gradient, details = hedging_loss_and_gradient(
prices,
deltas,
strike=100.0,
kappa=0.01,
cost_kind="linear",
premium=0.0,
terminal_liquidation=False,
)
print(losses.shape) # (5000,)
print(position_gradient.shape) # (5000, 30)
print(details.trades.shape) # (5000, 30)
print(details.costs.shape) # (5000, 30)
Train a state-only policy over multiple iterations
from deep_hedging import Adam, TanhMLP, simulate_gbm, train_step
strike = 100.0
maturity = 30 / 252
network = TanhMLP(input_dim=2, hidden=16, delta_max=1.5, seed=1)
optimizer = Adam(network.params, lr=3e-3)
for iteration in range(200):
prices = simulate_gbm(
n_paths=4_096,
n_steps=30,
s0=100.0,
maturity=maturity,
sigma=0.20,
seed=10_000 + iteration,
)
cvar, losses, deltas, details, grad_norm = train_step(
network,
optimizer,
prices=prices,
strike=strike,
maturity=maturity,
alpha=0.95,
kappa=0.01,
cost_kind="linear",
)
if iteration % 25 == 0:
print(
f"iteration={iteration:03d} "
f"cvar={cvar:.6f} "
f"grad_norm={grad_norm:.6f}"
)
Each training step:
- constructs market-state features;
- evaluates the policy at every trading date;
- computes terminal losses and transaction-cost-coupled position gradients;
- assigns exact empirical-CVaR tail weights;
- accumulates network gradients across dates;
- applies one Adam update.
Train an inventory-aware policy
The inventory-aware policy receives the previous position as an additional input. Under GBM, the network therefore uses three inputs rather than two.
from deep_hedging import Adam, TanhMLP, inventory_policy_step, simulate_gbm
maturity = 30 / 252
network = TanhMLP(input_dim=3, hidden=16, delta_max=1.5, seed=2)
optimizer = Adam(network.params, lr=3e-3)
prices = simulate_gbm(
n_paths=4_096,
n_steps=30,
maturity=maturity,
sigma=0.20,
seed=123,
)
cvar, losses, deltas, details, grad_norm = inventory_policy_step(
network,
optimizer,
prices=prices,
strike=100.0,
maturity=maturity,
alpha=0.95,
kappa=0.01,
cost_kind="linear",
)
print(f"CVaR: {cvar:.6f}")
print(f"Average absolute trade: {abs(details.trades).mean():.6f}")
Simulate Heston paths
from deep_hedging import simulate_heston_full_truncation
prices, variances, diagnostics = simulate_heston_full_truncation(
n_paths=20_000,
n_steps=30,
s0=100.0,
maturity=30 / 252,
v0=0.04,
kappa_v=2.0,
theta_v=0.04,
xi=0.5,
rho=-0.7,
substeps=4,
seed=42,
)
print(prices.shape)
print(variances.shape)
print(diagnostics)
For state-only Heston training, instantiate TanhMLP(input_dim=3, ...) and pass variances=variances to train_step. The three features are normalized time to maturity, log-moneyness, and truncated instantaneous variance.
Compare two strategies with a paired bootstrap
from deep_hedging import paired_bootstrap_cvar_difference
comparison = paired_bootstrap_cvar_difference(
loss_a=losses_strategy_a,
loss_b=losses_strategy_b,
alpha=0.95,
n_boot=2_000,
seed=42,
)
print(comparison)
The returned dictionary contains the estimated CVaR difference and the 2.5% and 97.5% bootstrap quantiles.
Public Python API
The following objects are exported directly from deep_hedging:
from deep_hedging import (
Adam,
HestonDiagnostics,
LossBreakdown,
TanhMLP,
TrainRecord,
black_scholes_delta,
build_features,
empirical_cvar,
empirical_cvar_weights,
empirical_var,
evaluate_positions,
hedging_loss_and_gradient,
instantaneous_vol_delta,
inventory_policy_step,
inventory_positions,
no_hedge,
no_trade_band,
paired_bootstrap_cvar_difference,
policy_positions,
reduced_frequency,
shrunk_delta,
simulate_gbm,
simulate_heston_full_truncation,
train_step,
)
API summary
| Category | Public objects |
|---|---|
| Simulation | simulate_gbm, simulate_heston_full_truncation, HestonDiagnostics |
| Risk | empirical_var, empirical_cvar, empirical_cvar_weights |
| Losses | hedging_loss_and_gradient, LossBreakdown |
| Features | build_features |
| Networks | TanhMLP |
| Optimization | Adam, TrainRecord, train_step, policy_positions |
| Inventory-aware policy | inventory_policy_step, inventory_positions |
| Benchmarks | no_hedge, black_scholes_delta, shrunk_delta, reduced_frequency, no_trade_band, instantaneous_vol_delta |
| Evaluation | evaluate_positions, paired_bootstrap_cvar_difference |
Core array conventions
| Object | Shape | Meaning |
|---|---|---|
prices |
(B, n + 1) |
Initial spot plus prices at all trading endpoints |
variances |
(B, n + 1) |
Truncated Heston variance observations |
features |
(B, n, d) |
Policy state at every decision date |
deltas |
(B, n) |
Position held over every trading interval |
trades |
(B, n) |
Position changes from the previous holding |
losses |
(B,) |
Terminal loss by path |
position_gradient |
(B, n) |
Pathwise derivative of loss with respect to each position |
Here, B is the number of simulated paths, n the number of trading intervals, and d the feature dimension.
Repository experiments
The package API can be used independently, while the scripts/ directory provides reproducible command-line experiments.
Smoke experiment
python scripts/run_experiment.py \
--config configs/smoke_gbm_linear.json \
--output results/generated/smoke_gbm_linear
Inventory-aware smoke experiment
python scripts/run_experiment.py \
--config configs/smoke_gbm_inventory.json \
--output results/generated/smoke_gbm_inventory
Heston smoke experiment
python scripts/run_experiment.py \
--config configs/smoke_heston_linear.json \
--output results/generated/smoke_heston_linear
Confirmatory experiment plan
python scripts/run_plan.py \
--plan configs/plans/confirmatory_gbm_cost_sweep.json
Before running a confirmatory campaign, freeze the source commit, environment, seeds, validation rule, and output directory as described in docs/reproducibility.md.
Benchmark calibration
python scripts/calibrate_benchmarks.py \
--config configs/confirmatory_gbm_linear_k001.json \
--output results/generated/benchmark_calibration.json
Calibration paths must remain separate from final evaluation paths.
Heston delta surface
python scripts/precompute_heston_delta.py \
--config configs/heston_delta_surface_example.json \
--output results/generated/heston_delta_surface.npz
Reference the generated file through heston_delta_surface in the corresponding Heston experiment configuration.
Verification
Run the complete local validation suite:
make lint
make test
make gradient-check
make smoke
make paper
Equivalent direct commands include:
ruff check src tests scripts
pytest
python scripts/validate_gradients.py
python scripts/reproduce_all.py --profile smoke
The repository validates:
- finite-sample CVaR boundary weighting;
- cash translation;
- deterministic GBM simulation;
- GBM mean behavior;
- Heston output constraints and pricing bounds;
- transaction-cost indexing;
- feedforward-network derivatives;
- pathwise hedging-loss gradients;
- inventory-aware backpropagation.
The finite-difference validator checks the feedforward-network backward pass, the quadratic pathwise hedging-loss gradient, and transaction-cost coupling across adjacent dates. The repository does not claim an independent automatic-differentiation verification of the complete profiled empirical-CVaR parameter gradient.
Build the package
python -m pip install --upgrade build
python -m build
The command creates a source distribution and a wheel under dist/.
Test the wheel in a clean virtual environment:
python -m venv .package-test
source .package-test/bin/activate
python -m pip install dist/asr_deep_hedging-0.1.0-py3-none-any.whl
python -c "import deep_hedging; print(deep_hedging.__version__)"
Publish to PyPI
The repository contains .github/workflows/publish-pypi.yml, configured for PyPI Trusted Publishing through OpenID Connect.
Required publisher values:
PyPI project: asr-deep-hedging
GitHub owner: Alpha-Stochastic-Research
GitHub repository: asr-deep-hedging
Workflow file: publish-pypi.yml
Environment: pypi
After the trusted publisher is configured, create and push the release tag:
git tag -a v0.1.0 -m "ASR Deep Hedging v0.1.0"
git push origin v0.1.0
The workflow builds and verifies the wheel and source distribution before publishing them. No long-lived PyPI API token is required.
After the workflow succeeds, users will be able to install the package with:
python -m pip install asr-deep-hedging
Repository structure
asr-deep-hedging/
├── src/deep_hedging/ # Installable Python research library
├── scripts/ # Experiments, diagnostics, tables, and figures
├── configs/ # Smoke and confirmatory configurations
├── tests/ # Unit, gradient, simulator, and package tests
├── paper/ # Editable LaTeX and compiled manuscript
├── results/legacy/ # Archived exploratory outputs
├── results/generated/ # Outputs produced by the current code
├── docs/ # Reproducibility and review documentation
└── authorship/ # Machine-readable CRediT contribution record
Manuscript
The compiled manuscript is available at paper/manuscript.pdf.
Build it locally with:
make paper
The paper presents the implementation conventions, empirical-CVaR treatment, analytic derivatives, archived exploratory experiments, validation status, and scientific limitations.
Reproducibility policy
Every numerical claim intended for the manuscript should include:
- a committed configuration and deterministic seeds;
- raw per-seed outputs and software metadata;
- an explicit validation and checkpoint-selection rule;
- paired uncertainty estimates on common test paths;
- regenerated tables, figures, and manuscript;
- a clean CI run on the exact reported commit.
Related documentation:
docs/reproducibility.mddocs/claims-register.mddocs/experiment-matrix.mddocs/model-card.mddocs/release-checklist.md
Scientific limitations
The library prioritizes transparency and numerical auditability over production-scale performance. Current limitations include:
- exploratory legacy results based on individual training runs;
- incomplete multi-seed confirmatory results;
- no independent autodiff validation of the full profiled-CVaR training gradient;
- simplified liquidity and transaction-cost models;
- an exploratory Heston comparison with asymmetric information sets;
- no modelling of live execution, market impact, latency, or production risk controls.
Citation
Citation metadata are provided in CITATION.cff. GitHub displays the recommended citation in the repository sidebar.
Contributing
Scientific changes must disclose whether they alter:
- the terminal-loss or premium convention;
- the simulator or stochastic parameters;
- the policy information set;
- the empirical risk estimator;
- benchmark calibration;
- reported numerical results.
Read CONTRIBUTING.md before opening a pull request.
Security and model-risk reporting
Use SECURITY.md for security, numerical-integrity, and model-risk reports. Do not include credentials, confidential datasets, or exploitable details in a public issue.
License
- Source code: MIT License.
- Manuscript text: CC BY 4.0.
- Third-party publisher templates, articles, datasets, and figures are not redistributed unless their licenses explicitly permit it.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file asr_deep_hedging-0.1.0.tar.gz.
File metadata
- Download URL: asr_deep_hedging-0.1.0.tar.gz
- Upload date:
- Size: 491.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb86622a28f22318e48cf2aaf5176b19328e616adc44c964b430d825195665ed
|
|
| MD5 |
961650850ab2c2d2a8e28e8f3bfaa2f0
|
|
| BLAKE2b-256 |
462dafc60daf831f8f7f08fb82ae92e948ac28e2a3b2e7c2a588a12fe80316d3
|
Provenance
The following attestation bundles were made for asr_deep_hedging-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on Alpha-Stochastic-Research/asr-deep-hedging
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
asr_deep_hedging-0.1.0.tar.gz -
Subject digest:
eb86622a28f22318e48cf2aaf5176b19328e616adc44c964b430d825195665ed - Sigstore transparency entry: 2228925582
- Sigstore integration time:
-
Permalink:
Alpha-Stochastic-Research/asr-deep-hedging@b6e6476763ef6b1570944688ff731984b9e5f64a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Alpha-Stochastic-Research
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@b6e6476763ef6b1570944688ff731984b9e5f64a -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file asr_deep_hedging-0.1.0-py3-none-any.whl.
File metadata
- Download URL: asr_deep_hedging-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f38fc12115338c7c0a66c758cb1631c47cf893c6bfd50b2d0c00b10644624680
|
|
| MD5 |
4ab67b75b0e406b21f745a9ee3d3998f
|
|
| BLAKE2b-256 |
de4af63d3e33c4a5698e511fd29e9d7c64a9196685a879de048893241e3d6afd
|
Provenance
The following attestation bundles were made for asr_deep_hedging-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on Alpha-Stochastic-Research/asr-deep-hedging
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
asr_deep_hedging-0.1.0-py3-none-any.whl -
Subject digest:
f38fc12115338c7c0a66c758cb1631c47cf893c6bfd50b2d0c00b10644624680 - Sigstore transparency entry: 2228926317
- Sigstore integration time:
-
Permalink:
Alpha-Stochastic-Research/asr-deep-hedging@b6e6476763ef6b1570944688ff731984b9e5f64a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Alpha-Stochastic-Research
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@b6e6476763ef6b1570944688ff731984b9e5f64a -
Trigger Event:
workflow_dispatch
-
Statement type: