Skip to main content

Auditable NumPy implementation and partial replication of deep hedging

Project description

ASR Deep Hedging

Auditable neural option hedging under transaction costs

CI Paper Python Version PyPI Code license Manuscript license

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 tanh network.
  • 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:

  1. constructs market-state features;
  2. evaluates the policy at every trading date;
  3. computes terminal losses and transaction-cost-coupled position gradients;
  4. assigns exact empirical-CVaR tail weights;
  5. accumulates network gradients across dates;
  6. 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:

  1. a committed configuration and deterministic seeds;
  2. raw per-seed outputs and software metadata;
  3. an explicit validation and checkpoint-selection rule;
  4. paired uncertainty estimates on common test paths;
  5. regenerated tables, figures, and manuscript;
  6. a clean CI run on the exact reported commit.

Related documentation:

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


Download files

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

Source Distribution

asr_deep_hedging-0.1.0.tar.gz (491.2 kB view details)

Uploaded Source

Built Distribution

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

asr_deep_hedging-0.1.0-py3-none-any.whl (22.2 kB view details)

Uploaded Python 3

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

Hashes for asr_deep_hedging-0.1.0.tar.gz
Algorithm Hash digest
SHA256 eb86622a28f22318e48cf2aaf5176b19328e616adc44c964b430d825195665ed
MD5 961650850ab2c2d2a8e28e8f3bfaa2f0
BLAKE2b-256 462dafc60daf831f8f7f08fb82ae92e948ac28e2a3b2e7c2a588a12fe80316d3

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file asr_deep_hedging-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for asr_deep_hedging-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f38fc12115338c7c0a66c758cb1631c47cf893c6bfd50b2d0c00b10644624680
MD5 4ab67b75b0e406b21f745a9ee3d3998f
BLAKE2b-256 de4af63d3e33c4a5698e511fd29e9d7c64a9196685a879de048893241e3d6afd

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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