tensorquantlib 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tensorquantlib/__init__.py +313 -0
- tensorquantlib/__main__.py +315 -0
- tensorquantlib/backtest/__init__.py +48 -0
- tensorquantlib/backtest/engine.py +240 -0
- tensorquantlib/backtest/metrics.py +320 -0
- tensorquantlib/backtest/strategy.py +348 -0
- tensorquantlib/core/__init__.py +6 -0
- tensorquantlib/core/ops.py +70 -0
- tensorquantlib/core/second_order.py +465 -0
- tensorquantlib/core/tensor.py +928 -0
- tensorquantlib/data/__init__.py +16 -0
- tensorquantlib/data/market.py +160 -0
- tensorquantlib/finance/__init__.py +52 -0
- tensorquantlib/finance/american.py +263 -0
- tensorquantlib/finance/basket.py +291 -0
- tensorquantlib/finance/black_scholes.py +219 -0
- tensorquantlib/finance/credit.py +199 -0
- tensorquantlib/finance/exotics.py +885 -0
- tensorquantlib/finance/fx.py +204 -0
- tensorquantlib/finance/greeks.py +133 -0
- tensorquantlib/finance/heston.py +543 -0
- tensorquantlib/finance/implied_vol.py +277 -0
- tensorquantlib/finance/ir_derivatives.py +203 -0
- tensorquantlib/finance/jump_diffusion.py +203 -0
- tensorquantlib/finance/local_vol.py +146 -0
- tensorquantlib/finance/rates.py +381 -0
- tensorquantlib/finance/risk.py +344 -0
- tensorquantlib/finance/variance_reduction.py +420 -0
- tensorquantlib/finance/volatility.py +355 -0
- tensorquantlib/py.typed +0 -0
- tensorquantlib/tt/__init__.py +43 -0
- tensorquantlib/tt/decompose.py +576 -0
- tensorquantlib/tt/ops.py +386 -0
- tensorquantlib/tt/pricing.py +304 -0
- tensorquantlib/tt/surrogate.py +634 -0
- tensorquantlib/utils/__init__.py +5 -0
- tensorquantlib/utils/validation.py +126 -0
- tensorquantlib/viz/__init__.py +27 -0
- tensorquantlib/viz/plots.py +331 -0
- tensorquantlib-0.3.0.dist-info/METADATA +602 -0
- tensorquantlib-0.3.0.dist-info/RECORD +44 -0
- tensorquantlib-0.3.0.dist-info/WHEEL +5 -0
- tensorquantlib-0.3.0.dist-info/licenses/LICENSE +21 -0
- tensorquantlib-0.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"""TensorQuantLib — Tensor-Train surrogate pricing engine with autodiff."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.3.0"
|
|
4
|
+
__author__ = "TensorQuantLib Contributors"
|
|
5
|
+
|
|
6
|
+
# ── Core autograd ───────────────────────────────────────────────────
|
|
7
|
+
from tensorquantlib.core.tensor import (
|
|
8
|
+
Tensor,
|
|
9
|
+
tensor_sin,
|
|
10
|
+
tensor_cos,
|
|
11
|
+
tensor_tanh,
|
|
12
|
+
tensor_abs,
|
|
13
|
+
tensor_clip,
|
|
14
|
+
tensor_where,
|
|
15
|
+
tensor_softmax,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# ── Second-order autodiff ───────────────────────────────────────────
|
|
19
|
+
from tensorquantlib.core.second_order import (
|
|
20
|
+
hvp,
|
|
21
|
+
hessian,
|
|
22
|
+
hessian_diag,
|
|
23
|
+
vhp,
|
|
24
|
+
mixed_partial,
|
|
25
|
+
gamma_autograd,
|
|
26
|
+
vanna_autograd,
|
|
27
|
+
volga_autograd,
|
|
28
|
+
second_order_greeks,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# ── Finance — Black-Scholes ─────────────────────────────────────────
|
|
32
|
+
from tensorquantlib.finance.black_scholes import (
|
|
33
|
+
bs_delta,
|
|
34
|
+
bs_gamma,
|
|
35
|
+
bs_price_numpy,
|
|
36
|
+
bs_price_tensor,
|
|
37
|
+
bs_rho,
|
|
38
|
+
bs_theta,
|
|
39
|
+
bs_vega,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# ── Finance — Implied Volatility ────────────────────────────────────
|
|
43
|
+
from tensorquantlib.finance.implied_vol import (
|
|
44
|
+
implied_vol,
|
|
45
|
+
implied_vol_batch,
|
|
46
|
+
implied_vol_nr,
|
|
47
|
+
iv_surface,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# ── Finance — Heston Model ──────────────────────────────────────────
|
|
51
|
+
from tensorquantlib.finance.heston import (
|
|
52
|
+
HestonParams,
|
|
53
|
+
HestonCalibrator,
|
|
54
|
+
heston_price,
|
|
55
|
+
heston_price_mc,
|
|
56
|
+
heston_greeks,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# ── Finance — American Options (LSM) ───────────────────────────────
|
|
60
|
+
from tensorquantlib.finance.american import (
|
|
61
|
+
american_option_lsm,
|
|
62
|
+
american_option_grid,
|
|
63
|
+
american_greeks,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# ── Finance — Exotic Options ────────────────────────────────────────
|
|
67
|
+
from tensorquantlib.finance.exotics import (
|
|
68
|
+
asian_price_mc,
|
|
69
|
+
asian_geometric_price,
|
|
70
|
+
digital_price,
|
|
71
|
+
digital_price_mc,
|
|
72
|
+
digital_greeks,
|
|
73
|
+
barrier_price,
|
|
74
|
+
barrier_price_mc,
|
|
75
|
+
lookback_fixed_analytic,
|
|
76
|
+
lookback_floating_analytic,
|
|
77
|
+
lookback_price_mc,
|
|
78
|
+
cliquet_price_mc,
|
|
79
|
+
rainbow_price_mc,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# ── Finance — Volatility Surface Models ─────────────────────────────
|
|
83
|
+
from tensorquantlib.finance.volatility import (
|
|
84
|
+
sabr_implied_vol,
|
|
85
|
+
sabr_calibrate,
|
|
86
|
+
svi_raw,
|
|
87
|
+
svi_implied_vol,
|
|
88
|
+
svi_calibrate,
|
|
89
|
+
svi_surface,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# ── Finance — Interest Rate Models ──────────────────────────────────
|
|
93
|
+
from tensorquantlib.finance.rates import (
|
|
94
|
+
vasicek_bond_price,
|
|
95
|
+
vasicek_yield,
|
|
96
|
+
vasicek_option_price,
|
|
97
|
+
vasicek_simulate,
|
|
98
|
+
cir_bond_price,
|
|
99
|
+
cir_yield,
|
|
100
|
+
cir_simulate,
|
|
101
|
+
feller_condition,
|
|
102
|
+
nelson_siegel,
|
|
103
|
+
nelson_siegel_calibrate,
|
|
104
|
+
bootstrap_yield_curve,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# ── Finance — FX Options ────────────────────────────────────────────
|
|
108
|
+
from tensorquantlib.finance.fx import (
|
|
109
|
+
garman_kohlhagen,
|
|
110
|
+
gk_greeks,
|
|
111
|
+
fx_forward,
|
|
112
|
+
quanto_option,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# ── Finance — Credit Risk ───────────────────────────────────────────
|
|
116
|
+
from tensorquantlib.finance.credit import (
|
|
117
|
+
merton_default_prob,
|
|
118
|
+
merton_credit_spread,
|
|
119
|
+
survival_probability,
|
|
120
|
+
hazard_rate_from_spread,
|
|
121
|
+
cds_spread,
|
|
122
|
+
cds_price,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# ── Finance — Variance Reduction ────────────────────────────────────
|
|
126
|
+
from tensorquantlib.finance.variance_reduction import (
|
|
127
|
+
bs_price_antithetic,
|
|
128
|
+
asian_price_cv,
|
|
129
|
+
bs_price_qmc,
|
|
130
|
+
bs_price_importance,
|
|
131
|
+
bs_price_stratified,
|
|
132
|
+
compare_variance_reduction,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# ── Finance — Risk Metrics ──────────────────────────────────────────
|
|
136
|
+
from tensorquantlib.finance.risk import (
|
|
137
|
+
PortfolioRisk,
|
|
138
|
+
OptionPosition,
|
|
139
|
+
var_parametric,
|
|
140
|
+
var_historical,
|
|
141
|
+
var_mc,
|
|
142
|
+
cvar,
|
|
143
|
+
scenario_analysis,
|
|
144
|
+
greeks_portfolio,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# ── Finance — Jump-Diffusion Models ─────────────────────────────────
|
|
148
|
+
from tensorquantlib.finance.jump_diffusion import (
|
|
149
|
+
merton_jump_price,
|
|
150
|
+
merton_jump_price_mc,
|
|
151
|
+
kou_jump_price_mc,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# ── Finance — Local Volatility ──────────────────────────────────────
|
|
155
|
+
from tensorquantlib.finance.local_vol import (
|
|
156
|
+
dupire_local_vol,
|
|
157
|
+
local_vol_mc,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# ── Finance — IR Derivatives (Black76) ──────────────────────────────
|
|
161
|
+
from tensorquantlib.finance.ir_derivatives import (
|
|
162
|
+
black76_caplet,
|
|
163
|
+
black76_floorlet,
|
|
164
|
+
cap_price,
|
|
165
|
+
floor_price,
|
|
166
|
+
swap_rate,
|
|
167
|
+
swaption_price,
|
|
168
|
+
swaption_parity,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# ── Finance — Basket & Greeks ───────────────────────────────────────
|
|
172
|
+
from tensorquantlib.finance.basket import (
|
|
173
|
+
build_pricing_grid,
|
|
174
|
+
build_pricing_grid_analytic,
|
|
175
|
+
simulate_basket,
|
|
176
|
+
)
|
|
177
|
+
from tensorquantlib.finance.greeks import compute_greeks, compute_greeks_vectorized
|
|
178
|
+
|
|
179
|
+
# ── TT Compression ──────────────────────────────────────────────────
|
|
180
|
+
from tensorquantlib.tt.decompose import tt_round, tt_svd, tt_cross
|
|
181
|
+
from tensorquantlib.tt.ops import (
|
|
182
|
+
tt_add,
|
|
183
|
+
tt_compression_ratio,
|
|
184
|
+
tt_dot,
|
|
185
|
+
tt_error,
|
|
186
|
+
tt_eval,
|
|
187
|
+
tt_eval_batch,
|
|
188
|
+
tt_frobenius_norm,
|
|
189
|
+
tt_hadamard,
|
|
190
|
+
tt_memory,
|
|
191
|
+
tt_ranks,
|
|
192
|
+
tt_scale,
|
|
193
|
+
tt_to_full,
|
|
194
|
+
)
|
|
195
|
+
from tensorquantlib.tt.surrogate import TTSurrogate
|
|
196
|
+
from tensorquantlib.tt.pricing import (
|
|
197
|
+
heston_surrogate,
|
|
198
|
+
american_surrogate,
|
|
199
|
+
exotic_surrogate,
|
|
200
|
+
jump_diffusion_surrogate,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# ── Visualization ────────────────────────────────────────────────────
|
|
204
|
+
from tensorquantlib.viz import plot_greeks_surface, plot_pricing_surface, plot_tt_ranks
|
|
205
|
+
|
|
206
|
+
# ── Backtesting ──────────────────────────────────────────────────────
|
|
207
|
+
from tensorquantlib.backtest import (
|
|
208
|
+
BacktestEngine,
|
|
209
|
+
BacktestResult,
|
|
210
|
+
SlippageModel,
|
|
211
|
+
CommissionModel,
|
|
212
|
+
ZERO_COST,
|
|
213
|
+
EQUITY_COMM,
|
|
214
|
+
FX_COMM,
|
|
215
|
+
EQUITY_SLIP,
|
|
216
|
+
ILLIQUID_SLIP,
|
|
217
|
+
Strategy,
|
|
218
|
+
Trade,
|
|
219
|
+
DeltaHedgeStrategy,
|
|
220
|
+
GammaScalpingStrategy,
|
|
221
|
+
DeltaGammaHedgeStrategy,
|
|
222
|
+
StraddleStrategy,
|
|
223
|
+
sharpe_ratio,
|
|
224
|
+
max_drawdown,
|
|
225
|
+
sortino_ratio,
|
|
226
|
+
win_rate,
|
|
227
|
+
profit_factor,
|
|
228
|
+
annualized_return,
|
|
229
|
+
calmar_ratio,
|
|
230
|
+
information_ratio,
|
|
231
|
+
turnover,
|
|
232
|
+
hedge_pnl_attribution,
|
|
233
|
+
hedge_efficiency,
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
__all__ = [
|
|
237
|
+
# Core
|
|
238
|
+
"Tensor",
|
|
239
|
+
"tensor_sin", "tensor_cos", "tensor_tanh", "tensor_abs",
|
|
240
|
+
"tensor_clip", "tensor_where", "tensor_softmax",
|
|
241
|
+
# Black-Scholes
|
|
242
|
+
"bs_price_numpy", "bs_price_tensor",
|
|
243
|
+
"bs_delta", "bs_gamma", "bs_vega", "bs_theta", "bs_rho",
|
|
244
|
+
# Implied volatility
|
|
245
|
+
"implied_vol", "implied_vol_batch", "implied_vol_nr", "iv_surface",
|
|
246
|
+
# Heston
|
|
247
|
+
"HestonParams", "HestonCalibrator",
|
|
248
|
+
"heston_price", "heston_price_mc", "heston_greeks",
|
|
249
|
+
# American options
|
|
250
|
+
"american_option_lsm", "american_option_grid", "american_greeks",
|
|
251
|
+
# Exotics
|
|
252
|
+
"asian_price_mc", "asian_geometric_price",
|
|
253
|
+
"digital_price", "digital_price_mc", "digital_greeks",
|
|
254
|
+
"barrier_price", "barrier_price_mc",
|
|
255
|
+
"lookback_fixed_analytic", "lookback_floating_analytic", "lookback_price_mc",
|
|
256
|
+
"cliquet_price_mc", "rainbow_price_mc",
|
|
257
|
+
# Volatility surface
|
|
258
|
+
"sabr_implied_vol", "sabr_calibrate",
|
|
259
|
+
"svi_raw", "svi_implied_vol", "svi_calibrate", "svi_surface",
|
|
260
|
+
# Interest rates
|
|
261
|
+
"vasicek_bond_price", "vasicek_yield", "vasicek_option_price", "vasicek_simulate",
|
|
262
|
+
"cir_bond_price", "cir_yield", "cir_simulate", "feller_condition",
|
|
263
|
+
"nelson_siegel", "nelson_siegel_calibrate", "bootstrap_yield_curve",
|
|
264
|
+
# FX options
|
|
265
|
+
"garman_kohlhagen", "gk_greeks", "fx_forward", "quanto_option",
|
|
266
|
+
# Credit risk
|
|
267
|
+
"merton_default_prob", "merton_credit_spread",
|
|
268
|
+
"survival_probability", "hazard_rate_from_spread",
|
|
269
|
+
"cds_spread", "cds_price",
|
|
270
|
+
# Variance reduction
|
|
271
|
+
"bs_price_antithetic", "asian_price_cv", "bs_price_qmc",
|
|
272
|
+
"bs_price_importance", "bs_price_stratified", "compare_variance_reduction",
|
|
273
|
+
# Risk
|
|
274
|
+
"PortfolioRisk", "OptionPosition",
|
|
275
|
+
"var_parametric", "var_historical", "var_mc", "cvar",
|
|
276
|
+
"scenario_analysis", "greeks_portfolio",
|
|
277
|
+
# Jump-diffusion
|
|
278
|
+
"merton_jump_price", "merton_jump_price_mc", "kou_jump_price_mc",
|
|
279
|
+
# Local volatility
|
|
280
|
+
"dupire_local_vol", "local_vol_mc",
|
|
281
|
+
# IR derivatives
|
|
282
|
+
"black76_caplet", "black76_floorlet", "cap_price", "floor_price",
|
|
283
|
+
"swap_rate", "swaption_price", "swaption_parity",
|
|
284
|
+
# Basket & Greeks
|
|
285
|
+
"simulate_basket", "build_pricing_grid", "build_pricing_grid_analytic",
|
|
286
|
+
"compute_greeks", "compute_greeks_vectorized",
|
|
287
|
+
# Second-order autodiff
|
|
288
|
+
"hvp", "hessian", "hessian_diag", "vhp", "mixed_partial",
|
|
289
|
+
"gamma_autograd", "vanna_autograd", "volga_autograd", "second_order_greeks",
|
|
290
|
+
# TT compression
|
|
291
|
+
"TTSurrogate",
|
|
292
|
+
"tt_svd", "tt_round", "tt_cross",
|
|
293
|
+
"tt_eval", "tt_eval_batch", "tt_to_full",
|
|
294
|
+
"tt_ranks", "tt_memory", "tt_error", "tt_compression_ratio",
|
|
295
|
+
"tt_add", "tt_scale", "tt_hadamard", "tt_dot", "tt_frobenius_norm",
|
|
296
|
+
# TT-accelerated pricers
|
|
297
|
+
"heston_surrogate", "american_surrogate",
|
|
298
|
+
"exotic_surrogate", "jump_diffusion_surrogate",
|
|
299
|
+
# Visualization
|
|
300
|
+
"plot_pricing_surface", "plot_greeks_surface", "plot_tt_ranks",
|
|
301
|
+
# Backtesting — engine
|
|
302
|
+
"BacktestEngine", "BacktestResult",
|
|
303
|
+
"SlippageModel", "CommissionModel",
|
|
304
|
+
"ZERO_COST", "EQUITY_COMM", "FX_COMM", "EQUITY_SLIP", "ILLIQUID_SLIP",
|
|
305
|
+
# Backtesting — strategies
|
|
306
|
+
"Strategy", "Trade",
|
|
307
|
+
"DeltaHedgeStrategy", "GammaScalpingStrategy",
|
|
308
|
+
"DeltaGammaHedgeStrategy", "StraddleStrategy",
|
|
309
|
+
# Backtesting — metrics
|
|
310
|
+
"sharpe_ratio", "max_drawdown", "sortino_ratio", "win_rate", "profit_factor",
|
|
311
|
+
"annualized_return", "calmar_ratio", "information_ratio", "turnover",
|
|
312
|
+
"hedge_pnl_attribution", "hedge_efficiency",
|
|
313
|
+
]
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command-line interface for TensorQuantLib.
|
|
3
|
+
|
|
4
|
+
Usage examples::
|
|
5
|
+
|
|
6
|
+
# European option pricing
|
|
7
|
+
python -m tensorquantlib price --S 100 --K 100 --T 1 --r 0.05 --sigma 0.2
|
|
8
|
+
|
|
9
|
+
# Implied volatility
|
|
10
|
+
python -m tensorquantlib iv --price 10.45 --S 100 --K 100 --T 1 --r 0.05
|
|
11
|
+
|
|
12
|
+
# American option (LSM)
|
|
13
|
+
python -m tensorquantlib american --S 100 --K 100 --T 1 --r 0.05 --sigma 0.2
|
|
14
|
+
|
|
15
|
+
# Heston model price
|
|
16
|
+
python -m tensorquantlib heston --S 100 --K 100 --T 1 --r 0.05 --kappa 2 --theta 0.04 --xi 0.3 --rho -0.7 --v0 0.04
|
|
17
|
+
|
|
18
|
+
# Asian option
|
|
19
|
+
python -m tensorquantlib asian --S 100 --K 100 --T 1 --r 0.05 --sigma 0.2
|
|
20
|
+
|
|
21
|
+
# Barrier option
|
|
22
|
+
python -m tensorquantlib barrier --S 100 --K 100 --T 1 --r 0.05 --sigma 0.2 --barrier 90 --barrier-type down-and-out
|
|
23
|
+
|
|
24
|
+
# Portfolio risk
|
|
25
|
+
python -m tensorquantlib risk --sigma 0.20 --horizon 1 --alpha 0.95
|
|
26
|
+
|
|
27
|
+
# VaR comparison methods
|
|
28
|
+
python -m tensorquantlib compare-vr --S 100 --K 100 --T 1 --r 0.05 --sigma 0.2
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import argparse
|
|
34
|
+
import sys
|
|
35
|
+
from typing import NoReturn
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _print_table(rows: list[tuple[str, str]]) -> None:
|
|
39
|
+
"""Print a two-column table."""
|
|
40
|
+
if not rows:
|
|
41
|
+
return
|
|
42
|
+
w = max(len(r[0]) for r in rows) + 2
|
|
43
|
+
print("-" * (w + 20))
|
|
44
|
+
for k, v in rows:
|
|
45
|
+
print(f" {k:<{w}}{v}")
|
|
46
|
+
print("-" * (w + 20))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def cmd_price(args: argparse.Namespace) -> None:
|
|
50
|
+
"""European Black-Scholes pricing."""
|
|
51
|
+
from tensorquantlib.finance.black_scholes import (
|
|
52
|
+
bs_price_numpy, bs_delta, bs_gamma, bs_vega, bs_theta, bs_rho,
|
|
53
|
+
)
|
|
54
|
+
price = bs_price_numpy(args.S, args.K, args.T, args.r, args.sigma, q=args.q, option_type=args.type)
|
|
55
|
+
delta = bs_delta(args.S, args.K, args.T, args.r, args.sigma, q=args.q, option_type=args.type)
|
|
56
|
+
gamma = bs_gamma(args.S, args.K, args.T, args.r, args.sigma, q=args.q)
|
|
57
|
+
vega = bs_vega(args.S, args.K, args.T, args.r, args.sigma, q=args.q)
|
|
58
|
+
theta = bs_theta(args.S, args.K, args.T, args.r, args.sigma, q=args.q, option_type=args.type)
|
|
59
|
+
rho = bs_rho(args.S, args.K, args.T, args.r, args.sigma, q=args.q, option_type=args.type)
|
|
60
|
+
|
|
61
|
+
print(f"\nBlack-Scholes European {args.type.upper()}")
|
|
62
|
+
_print_table([
|
|
63
|
+
("S", f"{args.S:.4f}"),
|
|
64
|
+
("K", f"{args.K:.4f}"),
|
|
65
|
+
("T", f"{args.T:.4f} yr"),
|
|
66
|
+
("r", f"{args.r:.4%}"),
|
|
67
|
+
("sigma", f"{args.sigma:.4%}"),
|
|
68
|
+
("q", f"{args.q:.4%}"),
|
|
69
|
+
("Price", f"{float(price):.6f}"),
|
|
70
|
+
("Delta", f"{float(delta):.6f}"),
|
|
71
|
+
("Gamma", f"{float(gamma):.6f}"),
|
|
72
|
+
("Vega", f"{float(vega):.6f}"),
|
|
73
|
+
("Theta", f"{float(theta):.6f}"),
|
|
74
|
+
("Rho", f"{float(rho):.6f}"),
|
|
75
|
+
])
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def cmd_iv(args: argparse.Namespace) -> None:
|
|
79
|
+
"""Implied volatility inversion."""
|
|
80
|
+
from tensorquantlib.finance.implied_vol import implied_vol_nr
|
|
81
|
+
try:
|
|
82
|
+
iv = implied_vol_nr(args.price, args.S, args.K, args.T, args.r, q=args.q, option_type=args.type)
|
|
83
|
+
print(f"\nImplied Volatility: {iv:.6f} ({iv*100:.2f}%)")
|
|
84
|
+
except ValueError as e:
|
|
85
|
+
print(f"\nError: {e}", file=sys.stderr)
|
|
86
|
+
sys.exit(1)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def cmd_american(args: argparse.Namespace) -> None:
|
|
90
|
+
"""American option pricing via Longstaff-Schwartz LSM."""
|
|
91
|
+
from tensorquantlib.finance.american import american_option_lsm
|
|
92
|
+
price, stderr = american_option_lsm(
|
|
93
|
+
args.S, args.K, args.T, args.r, args.sigma, q=args.q,
|
|
94
|
+
option_type=args.type, n_paths=args.paths, n_steps=args.steps,
|
|
95
|
+
seed=args.seed, return_stderr=True,
|
|
96
|
+
)
|
|
97
|
+
print(f"\nAmerican LSM {args.type.upper()}")
|
|
98
|
+
_print_table([
|
|
99
|
+
("Price", f"{price:.6f}"),
|
|
100
|
+
("StdErr", f"{stderr:.6f}"),
|
|
101
|
+
("n_paths", f"{args.paths:,}"),
|
|
102
|
+
("n_steps", f"{args.steps}"),
|
|
103
|
+
])
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def cmd_heston(args: argparse.Namespace) -> None:
|
|
107
|
+
"""Heston stochastic volatility pricing."""
|
|
108
|
+
from tensorquantlib.finance.heston import HestonParams, heston_price, heston_greeks
|
|
109
|
+
params = HestonParams(kappa=args.kappa, theta=args.theta, xi=args.xi, rho=args.rho, v0=args.v0)
|
|
110
|
+
price = heston_price(args.S, args.K, args.T, args.r, params, q=args.q, option_type=args.type)
|
|
111
|
+
greeks = heston_greeks(args.S, args.K, args.T, args.r, params, q=args.q, option_type=args.type)
|
|
112
|
+
print(f"\nHeston Model {args.type.upper()}")
|
|
113
|
+
print(f"Feller condition: {'satisfied' if params.feller_satisfied() else 'VIOLATED (possible instability)'}")
|
|
114
|
+
_print_table([
|
|
115
|
+
("Price", f"{price:.6f}"),
|
|
116
|
+
("Delta", f"{greeks['delta']:.6f}"),
|
|
117
|
+
("Gamma", f"{greeks['gamma']:.6f}"),
|
|
118
|
+
("Theta", f"{greeks['theta']:.6f}"),
|
|
119
|
+
("Vega", f"{greeks['vega']:.6f} (per unit v0)"),
|
|
120
|
+
])
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def cmd_asian(args: argparse.Namespace) -> None:
|
|
124
|
+
"""Asian option pricing."""
|
|
125
|
+
from tensorquantlib.finance.exotics import asian_price_mc, asian_geometric_price
|
|
126
|
+
price_mc, stderr = asian_price_mc(
|
|
127
|
+
args.S, args.K, args.T, args.r, args.sigma, q=args.q,
|
|
128
|
+
option_type=args.type, average_type=args.avg,
|
|
129
|
+
n_paths=args.paths, n_steps=args.steps, seed=args.seed, return_stderr=True,
|
|
130
|
+
)
|
|
131
|
+
print(f"\nAsian {args.avg.capitalize()} Average {args.type.upper()}")
|
|
132
|
+
_print_table([
|
|
133
|
+
("MC Price", f"{price_mc:.6f}"),
|
|
134
|
+
("MC StdErr", f"{stderr:.6f}"),
|
|
135
|
+
])
|
|
136
|
+
if args.avg == "geometric":
|
|
137
|
+
analytic = asian_geometric_price(args.S, args.K, args.T, args.r, args.sigma, q=args.q, option_type=args.type)
|
|
138
|
+
print(f" {'Analytic Geo:':<20}{analytic:.6f}")
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def cmd_barrier(args: argparse.Namespace) -> None:
|
|
142
|
+
"""Barrier option pricing."""
|
|
143
|
+
from tensorquantlib.finance.exotics import barrier_price, barrier_price_mc
|
|
144
|
+
try:
|
|
145
|
+
analytic = barrier_price(args.S, args.K, args.T, args.r, args.sigma,
|
|
146
|
+
args.barrier, args.barrier_type, q=args.q,
|
|
147
|
+
option_type=args.type)
|
|
148
|
+
except Exception:
|
|
149
|
+
analytic = float("nan")
|
|
150
|
+
mc, stderr = barrier_price_mc(
|
|
151
|
+
args.S, args.K, args.T, args.r, args.sigma,
|
|
152
|
+
args.barrier, args.barrier_type, q=args.q,
|
|
153
|
+
option_type=args.type, n_paths=args.paths, n_steps=args.steps,
|
|
154
|
+
seed=args.seed, return_stderr=True,
|
|
155
|
+
)
|
|
156
|
+
print(f"\nBarrier Option [{args.barrier_type}] {args.type.upper()}")
|
|
157
|
+
_print_table([
|
|
158
|
+
("Barrier", f"{args.barrier:.2f}"),
|
|
159
|
+
("Analytic", f"{analytic:.6f}"),
|
|
160
|
+
("MC Price", f"{mc:.6f}"),
|
|
161
|
+
("MC StdErr",f"{stderr:.6f}"),
|
|
162
|
+
])
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def cmd_risk(args: argparse.Namespace) -> None:
|
|
166
|
+
"""Portfolio risk metrics — VaR, CVaR, Sharpe."""
|
|
167
|
+
from tensorquantlib.finance.risk import var_parametric, var_mc, PortfolioRisk
|
|
168
|
+
import numpy as np
|
|
169
|
+
|
|
170
|
+
print(f"\nRisk Metrics (S={args.S}, sigma={args.sigma:.1%}, alpha={args.alpha:.0%}, horizon={int(args.horizon)}d)")
|
|
171
|
+
var_p = var_parametric(0.0, args.sigma, alpha=args.alpha, horizon=args.horizon / 252.0)
|
|
172
|
+
var_v, cvar_v = var_mc(args.S, args.sigma, horizon=args.horizon / 252.0, alpha=args.alpha,
|
|
173
|
+
n_paths=100_000, seed=42)
|
|
174
|
+
_print_table([
|
|
175
|
+
("Param VaR (1d)", f"{var_p * args.S:.4f} ({var_p:.4%} of S)"),
|
|
176
|
+
("MC VaR", f"{var_v * args.S:.4f} ({var_v:.4%} of S)"),
|
|
177
|
+
("MC CVaR (ES)", f"{cvar_v * args.S:.4f} ({cvar_v:.4%} of S)"),
|
|
178
|
+
])
|
|
179
|
+
|
|
180
|
+
# Simulate a return history and report portfolio-level stats
|
|
181
|
+
rng = np.random.default_rng(42)
|
|
182
|
+
ret_hist = rng.normal(0.0, args.sigma / np.sqrt(252), 252)
|
|
183
|
+
pr = PortfolioRisk(ret_hist, alpha=args.alpha)
|
|
184
|
+
stats = pr.summary()
|
|
185
|
+
print("\n Simulated 1-year daily return history:")
|
|
186
|
+
_print_table([(k, f"{v:.4f}") for k, v in stats.items()])
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def cmd_compare_vr(args: argparse.Namespace) -> None:
|
|
190
|
+
"""Compare variance reduction methods."""
|
|
191
|
+
from tensorquantlib.finance.variance_reduction import compare_variance_reduction
|
|
192
|
+
results = compare_variance_reduction(
|
|
193
|
+
args.S, args.K, args.T, args.r, args.sigma, n_paths=args.paths, seed=42,
|
|
194
|
+
)
|
|
195
|
+
print(f"\nVariance Reduction Comparison ({args.type.upper()} S={args.S} K={args.K} T={args.T})")
|
|
196
|
+
print(f" {'Method':<25} {'Price':>10} {'StdErr':>12} {'VR Ratio':>10}")
|
|
197
|
+
print(" " + "-" * 60)
|
|
198
|
+
for name, res in results.items():
|
|
199
|
+
print(f" {name:<25} {res['price']:>10.5f} {res['stderr']:>12.6f} {res['vr_ratio']:>10.2f}x")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
203
|
+
"""Construct the CLI argument parser."""
|
|
204
|
+
parser = argparse.ArgumentParser(
|
|
205
|
+
prog="python -m tensorquantlib",
|
|
206
|
+
description="TensorQuantLib — quantitative finance toolkit CLI",
|
|
207
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
208
|
+
epilog=__doc__,
|
|
209
|
+
)
|
|
210
|
+
sub = parser.add_subparsers(dest="command", metavar="COMMAND")
|
|
211
|
+
|
|
212
|
+
# ---- shared arguments ----
|
|
213
|
+
def add_bs_args(p: argparse.ArgumentParser) -> None:
|
|
214
|
+
p.add_argument("--S", type=float, required=True, help="Spot price")
|
|
215
|
+
p.add_argument("--K", type=float, required=True, help="Strike")
|
|
216
|
+
p.add_argument("--T", type=float, required=True, help="Time to expiry (years)")
|
|
217
|
+
p.add_argument("--r", type=float, required=True, help="Risk-free rate")
|
|
218
|
+
p.add_argument("--sigma", type=float, required=True, help="Volatility")
|
|
219
|
+
p.add_argument("--q", type=float, default=0.0, help="Dividend yield (default 0)")
|
|
220
|
+
p.add_argument("--type", choices=["call", "put"], default="call")
|
|
221
|
+
|
|
222
|
+
def add_mc_args(p: argparse.ArgumentParser) -> None:
|
|
223
|
+
p.add_argument("--paths", type=int, default=100_000, help="MC paths")
|
|
224
|
+
p.add_argument("--steps", type=int, default=252, help="Time steps")
|
|
225
|
+
p.add_argument("--seed", type=int, default=None, help="Random seed")
|
|
226
|
+
|
|
227
|
+
# ---- price ----
|
|
228
|
+
p_price = sub.add_parser("price", help="Black-Scholes European option price and Greeks")
|
|
229
|
+
add_bs_args(p_price)
|
|
230
|
+
p_price.set_defaults(func=cmd_price)
|
|
231
|
+
|
|
232
|
+
# ---- iv ----
|
|
233
|
+
p_iv = sub.add_parser("iv", help="Implied volatility solver")
|
|
234
|
+
p_iv.add_argument("--price", type=float, required=True, help="Market price")
|
|
235
|
+
p_iv.add_argument("--S", type=float, required=True)
|
|
236
|
+
p_iv.add_argument("--K", type=float, required=True)
|
|
237
|
+
p_iv.add_argument("--T", type=float, required=True)
|
|
238
|
+
p_iv.add_argument("--r", type=float, required=True)
|
|
239
|
+
p_iv.add_argument("--q", type=float, default=0.0)
|
|
240
|
+
p_iv.add_argument("--type", choices=["call", "put"], default="call")
|
|
241
|
+
p_iv.set_defaults(func=cmd_iv)
|
|
242
|
+
|
|
243
|
+
# ---- american ----
|
|
244
|
+
p_am = sub.add_parser("american", help="American option via LSM Monte Carlo")
|
|
245
|
+
add_bs_args(p_am)
|
|
246
|
+
add_mc_args(p_am)
|
|
247
|
+
p_am.set_defaults(func=cmd_american)
|
|
248
|
+
|
|
249
|
+
# ---- heston ----
|
|
250
|
+
p_heston = sub.add_parser("heston", help="Heston stochastic volatility model")
|
|
251
|
+
p_heston.add_argument("--S", type=float, required=True)
|
|
252
|
+
p_heston.add_argument("--K", type=float, required=True)
|
|
253
|
+
p_heston.add_argument("--T", type=float, required=True)
|
|
254
|
+
p_heston.add_argument("--r", type=float, required=True)
|
|
255
|
+
p_heston.add_argument("--q", type=float, default=0.0)
|
|
256
|
+
p_heston.add_argument("--type", choices=["call", "put"], default="call")
|
|
257
|
+
p_heston.add_argument("--kappa", type=float, default=2.0)
|
|
258
|
+
p_heston.add_argument("--theta", type=float, default=0.04)
|
|
259
|
+
p_heston.add_argument("--xi", type=float, default=0.3)
|
|
260
|
+
p_heston.add_argument("--rho", type=float, default=-0.7)
|
|
261
|
+
p_heston.add_argument("--v0", type=float, default=0.04)
|
|
262
|
+
p_heston.set_defaults(func=cmd_heston)
|
|
263
|
+
|
|
264
|
+
# ---- asian ----
|
|
265
|
+
p_asian = sub.add_parser("asian", help="Asian average-rate option")
|
|
266
|
+
add_bs_args(p_asian)
|
|
267
|
+
add_mc_args(p_asian)
|
|
268
|
+
p_asian.add_argument("--avg", choices=["arithmetic", "geometric"], default="arithmetic")
|
|
269
|
+
p_asian.set_defaults(func=cmd_asian)
|
|
270
|
+
|
|
271
|
+
# ---- barrier ----
|
|
272
|
+
p_barrier = sub.add_parser("barrier", help="Single-barrier European option")
|
|
273
|
+
add_bs_args(p_barrier)
|
|
274
|
+
add_mc_args(p_barrier)
|
|
275
|
+
p_barrier.add_argument("--barrier", type=float, required=True, help="Barrier level")
|
|
276
|
+
p_barrier.add_argument(
|
|
277
|
+
"--barrier-type",
|
|
278
|
+
dest="barrier_type",
|
|
279
|
+
choices=["down-and-in", "down-and-out", "up-and-in", "up-and-out"],
|
|
280
|
+
default="down-and-out",
|
|
281
|
+
)
|
|
282
|
+
p_barrier.set_defaults(func=cmd_barrier)
|
|
283
|
+
|
|
284
|
+
# ---- risk ----
|
|
285
|
+
p_risk = sub.add_parser("risk", help="Risk metrics: VaR, CVaR, Sharpe, drawdown")
|
|
286
|
+
p_risk.add_argument("--S", type=float, default=100.0, help="Spot / position size")
|
|
287
|
+
p_risk.add_argument("--sigma", type=float, required=True, help="Annualised volatility")
|
|
288
|
+
p_risk.add_argument("--horizon", type=float, default=1.0, help="Horizon in trading days (default 1)")
|
|
289
|
+
p_risk.add_argument("--alpha", type=float, default=0.95, help="Confidence level (default 0.95)")
|
|
290
|
+
p_risk.set_defaults(func=cmd_risk)
|
|
291
|
+
|
|
292
|
+
# ---- compare-vr ----
|
|
293
|
+
p_vr = sub.add_parser("compare-vr", help="Compare variance reduction methods")
|
|
294
|
+
add_bs_args(p_vr)
|
|
295
|
+
p_vr.add_argument("--paths", type=int, default=50_000)
|
|
296
|
+
p_vr.set_defaults(func=cmd_compare_vr)
|
|
297
|
+
|
|
298
|
+
return parser
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def main(argv: list[str] | None = None) -> int:
|
|
302
|
+
"""Entry point for the CLI."""
|
|
303
|
+
parser = build_parser()
|
|
304
|
+
args = parser.parse_args(argv)
|
|
305
|
+
|
|
306
|
+
if not args.command:
|
|
307
|
+
parser.print_help()
|
|
308
|
+
return 1
|
|
309
|
+
|
|
310
|
+
args.func(args)
|
|
311
|
+
return 0
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
if __name__ == "__main__":
|
|
315
|
+
sys.exit(main())
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Backtesting framework: strategy simulation and P&L tracking."""
|
|
2
|
+
from tensorquantlib.backtest.metrics import (
|
|
3
|
+
sharpe_ratio,
|
|
4
|
+
max_drawdown,
|
|
5
|
+
sortino_ratio,
|
|
6
|
+
win_rate,
|
|
7
|
+
profit_factor,
|
|
8
|
+
annualized_return,
|
|
9
|
+
calmar_ratio,
|
|
10
|
+
information_ratio,
|
|
11
|
+
turnover,
|
|
12
|
+
hedge_pnl_attribution,
|
|
13
|
+
hedge_efficiency,
|
|
14
|
+
)
|
|
15
|
+
from tensorquantlib.backtest.engine import (
|
|
16
|
+
BacktestEngine,
|
|
17
|
+
BacktestResult,
|
|
18
|
+
SlippageModel,
|
|
19
|
+
CommissionModel,
|
|
20
|
+
ZERO_COST,
|
|
21
|
+
EQUITY_COMM,
|
|
22
|
+
FX_COMM,
|
|
23
|
+
EQUITY_SLIP,
|
|
24
|
+
ILLIQUID_SLIP,
|
|
25
|
+
)
|
|
26
|
+
from tensorquantlib.backtest.strategy import (
|
|
27
|
+
Strategy,
|
|
28
|
+
Trade,
|
|
29
|
+
DeltaHedgeStrategy,
|
|
30
|
+
GammaScalpingStrategy,
|
|
31
|
+
DeltaGammaHedgeStrategy,
|
|
32
|
+
StraddleStrategy,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
# metrics
|
|
37
|
+
"sharpe_ratio", "max_drawdown", "sortino_ratio", "win_rate", "profit_factor",
|
|
38
|
+
"annualized_return", "calmar_ratio", "information_ratio", "turnover",
|
|
39
|
+
"hedge_pnl_attribution", "hedge_efficiency",
|
|
40
|
+
# engine
|
|
41
|
+
"BacktestEngine", "BacktestResult",
|
|
42
|
+
"SlippageModel", "CommissionModel",
|
|
43
|
+
"ZERO_COST", "EQUITY_COMM", "FX_COMM", "EQUITY_SLIP", "ILLIQUID_SLIP",
|
|
44
|
+
# strategy
|
|
45
|
+
"Strategy", "Trade",
|
|
46
|
+
"DeltaHedgeStrategy", "GammaScalpingStrategy",
|
|
47
|
+
"DeltaGammaHedgeStrategy", "StraddleStrategy",
|
|
48
|
+
]
|