Skip to content

Add local and global caps and floors to EquityCliquetOption (#221) - #404

Open
huuan26 wants to merge 2 commits into
domokane:masterfrom
huuan26:feature/equity-cliquet-floor-cap-221
Open

huuan26 wants to merge 2 commits into
domokane:masterfrom
huuan26:feature/equity-cliquet-floor-cap-221

Conversation

@huuan26

@huuan26 huuan26 commented Oct 16, 2026 •

Copy link
Copy Markdown

Summary

Fixes #221.

This PR extends EquityCliquetOption to support Local Caps/Floors $(f, c)$ per period and Global Caps/Floors $(F, C)$ at maturity, as requested in Issue #221.

Key Changes

  1. Model Parameters (EquityCliquetOption.__init__):
    • Added optional parameters: local_floor, local_cap, global_floor, and global_cap.
    • Backward compatible: notional remains the 7th argument and existing positional/keyword calls retain default unconstrained behavior: $f=-\infty$, $c=+\infty$, $F=-\infty$, $C=+\infty$.
  2. Validation (_validate):
    • Enforces $f \le c$ and $F \le C$.
    • Ensures global bounds are only specified for CliquetPayoffTypes.MATURITY.
  3. Analytical Pricing (value()):
    • Extended analytical closed-form pricing for CliquetTypes.RETURN with local floor/cap via forward-start vanilla option decomposition.
    • Raises informative FinError if global caps/floors are specified with value(), directing users to value_mc().
  4. Monte Carlo Pricing (value_mc()):
    • Extended both Call and Put cliquets with local floors/caps applied period-by-period.
    • For MATURITY payoff type, global floor/cap is applied to cumulative payoff before discounting: $\text{Payoff} = \min(\max(\sum_{i=1}^N \tilde{R}_i, F), C)$.
  5. String Representation (__repr__):
    • Displays configured local/global caps and floors when non-default values are provided.

Mathematical Formulation

1. Local Capped & Floored Return Decomposition

For a cliquet option with reset dates $t_0 < t_1 < \dots < t_N$, let the period return be $R_i = \frac{S(t_i) - S(t_{i-1})}{S(t_{i-1})}$.

With local floor $f$ and local cap $c$ ($f \le c$):

$$ \tilde{R}_i = \min(\max(R_i, f), c) = f + \max(R_i - f, 0) - \max(R_i - c, 0) $$

For a Call Cliquet, the discounted expected payoff for period $i$ under risk-neutral measure $\mathbb{Q}$ decomposes into:

$$ e^{-r t_i} \mathbb{E}^{\mathbb{Q}}[\tilde{R}_i] = e^{-r t_i} f + e^{-r t_{i-1}} \left[ C_{\text{BS}}(1.0, 1 + f, \tau_i) - C_{\text{BS}}(1.0, 1 + c, \tau_i) \right] $$

where $\tau_i = t_i - t_{i-1}$ and $C_{\text{BS}}(S_0, K, \tau)$ is the Black-Scholes European call formula with strike $K$ and spot $S_0 = 1.0$.

For a Put Cliquet ($R_i = \frac{S(t_{i-1}) - S(t_i)}{S(t_{i-1})}$):

$$ \tilde{R}_i = \min(\max(R_i, f), c) = f + \max(R_i - f, 0) - \max(R_i - c, 0) $$

Using Put-Call parity, this decomposes into:

$$ e^{-r t_i} \mathbb{E}^{\mathbb{Q}}[\tilde{R}_i] = e^{-r t_i} f + e^{-r t_{i-1}} \left[ P_{\text{BS}}(1.0, 1 - f, \tau_i) - P_{\text{BS}}(1.0, 1 - c, \tau_i) \right] $$

2. Global Bounds (Maturity Payoff)

For a globally floored and locally capped (GFLC) cliquet with cumulative return payoff at maturity $t_N$:

$$ \text{Payoff} = \min\left(\max\left(\sum_{i=1}^N \tilde{R}_i, F\right), C\right) $$

Priced via Monte Carlo simulation with exact lognormal state transitions.


Testing & Verification

Comprehensive test suite added to tests/unit/test_FinEquityCliquetOption.py:

  • Input Validation Tests: Verified that $f > c$ and $F > C$ raise FinError.
  • Analytical vs Monte Carlo Consistency: Tested Call and Put cliquets with local floor/cap against MC simulation (all $|Z| < 3.0$ standard errors).
  • 1-Period Benchmark Verification: Verified that a 1-period Call cliquet with local floor $f=0$ and cap $c=0.08$ exactly matches the analytical Black-Scholes Bull Call Spread ($K_1=1.00$, $K_2=1.08$) within ${10}^{-12}$ ($< 10^{-12}$).
  • Asymptotic Limit Verification: Verified that as local cap $c \to \infty$, analytical capped cliquet value converges to the uncapped cliquet within ${10}^{-9}$ ($< 10^{-9}$).
  • Monotonicity Tests: Verified that option price increases monotonically with higher cap $c$ and higher floor $f$.
  • Global Floor/Cap (GFLC) Monte Carlo Tests: Verified pricing and sensitivity for cliquets with both local cap and global floor.
  • Regression Tests: Confirmed 100% backward compatibility for existing unconstrained cliquet tests.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cliquet option with global floor and local cap + VolSwap valuation

1 participant