Skip to content

Commit 5b81714

Browse files
authored
Merge pull request #278 from joaquinbejar/feat/issue-243-cliquet-option
feat: issue #243 cliquet option pricing
2 parents 769b37c + a3101eb commit 5b81714

17 files changed

Lines changed: 770 additions & 13 deletions
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Issue #237: Asian Option Pricing Model
2+
3+
## Overview
4+
5+
Asian options are path-dependent options where the payoff depends on the average price of the underlying asset over a specified period. This implementation will support both geometric and arithmetic averaging, with fixed and floating strike variants.
6+
7+
## Implementation Phases
8+
9+
### Phase 1: Core Data Model Verification
10+
- Verify `OptionType::Asian { averaging_type: AsianAveragingType }` exists
11+
- Ensure `AsianAveragingType` enum has Arithmetic and Geometric variants
12+
- Add any missing fields for fixed/floating strike distinction
13+
14+
### Phase 2: Geometric Average Asian Option (Closed-Form)
15+
- Implement `geometric_asian_black_scholes()` in new `src/pricing/asian.rs`
16+
- Use adjusted Black-Scholes formula:
17+
- Adjusted volatility: `σ_adj = σ / √3`
18+
- Adjusted rate: `r_adj = (r + σ²/6) / 2` for the cost-of-carry adjustment
19+
- Support both call and put options
20+
21+
### Phase 3: Arithmetic Average Asian Option
22+
- Implement Turnbull-Wakeman approximation for closed-form pricing
23+
- Match first two moments of arithmetic average to lognormal distribution
24+
- Fallback to Monte Carlo for higher accuracy if needed
25+
26+
### Phase 4: Fixed vs Floating Strike
27+
- Fixed strike: payoff = max(Average - K, 0) for calls
28+
- Floating strike: payoff = max(S_T - Average, 0) for calls
29+
- Handle both variants in pricing functions
30+
31+
### Phase 5: Integration
32+
- Route `OptionType::Asian` to new pricing functions in `black_scholes_model.rs`
33+
- Integrate with unified pricing API
34+
35+
### Phase 6: Greeks
36+
- Use numerical Greeks from existing `src/greeks/numerical.rs` module
37+
- Route Asian options to numerical implementations in `equations.rs`
38+
39+
### Phase 7: Testing
40+
- Test geometric average closed-form against known values
41+
- Test arithmetic approximation accuracy
42+
- Verify put-call parity relationships
43+
- Edge cases: zero volatility, zero time, extreme averaging periods
44+
45+
### Phase 8: Documentation
46+
- Add docstrings and examples
47+
- Document formula sources and limitations
48+
49+
## Technical Notes
50+
51+
### Geometric Average Closed-Form
52+
For a geometric average Asian call:
53+
```
54+
C = S * e^((b_adj - r) * T) * N(d1) - K * e^(-r * T) * N(d2)
55+
```
56+
where:
57+
- `σ_adj = σ / √3`
58+
- `b_adj = 0.5 * (r - q - σ²/6)`
59+
60+
### Turnbull-Wakeman Approximation
61+
Matches moments of the arithmetic average to a lognormal distribution.
62+
63+
## Dependencies
64+
65+
- Existing Black-Scholes infrastructure
66+
- Numerical Greeks module
67+
68+
## Files to Modify/Create
69+
70+
- `src/pricing/asian.rs` - NEW: Asian option pricing functions
71+
- `src/pricing/mod.rs` - Export new module
72+
- `src/pricing/black_scholes_model.rs` - Route Asian to new functions
73+
- `src/greeks/equations.rs` - Route to numerical Greeks
74+
75+
## Estimated Effort
76+
77+
8-12 hours
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Issue #239: Binary Option Pricing Model
2+
3+
## Overview
4+
5+
Binary options (also called digital options) have a fixed payout if the option expires in-the-money, regardless of how far in-the-money it is. This implementation will support cash-or-nothing and asset-or-nothing variants.
6+
7+
## Implementation Phases
8+
9+
### Phase 1: Core Data Model Verification
10+
- Verify `OptionType::Binary { binary_type: BinaryPayoffType }` exists
11+
- Check `BinaryPayoffType` enum for CashOrNothing and AssetOrNothing variants
12+
- Ensure the data model captures the payout amount (Q) for cash-or-nothing
13+
14+
### Phase 2: Cash-or-Nothing Binary Options
15+
- Implement `cash_or_nothing_call()`: `C = Q * e^(-rT) * N(d2)`
16+
- Implement `cash_or_nothing_put()`: `P = Q * e^(-rT) * N(-d2)`
17+
- Q = fixed cash payout amount
18+
19+
### Phase 3: Asset-or-Nothing Binary Options
20+
- Implement `asset_or_nothing_call()`: `C = S * e^(-qT) * N(d1)`
21+
- Implement `asset_or_nothing_put()`: `P = S * e^(-qT) * N(-d1)`
22+
23+
### Phase 4: Integration
24+
- Create `src/pricing/binary.rs` with all pricing functions
25+
- Route `OptionType::Binary` in `black_scholes_model.rs`
26+
- Export from `mod.rs`
27+
28+
### Phase 5: Greeks (Numerical)
29+
- Use numerical Greeks from existing `src/greeks/numerical.rs`
30+
- Note: Delta is discontinuous at strike, Gamma very large near expiration
31+
32+
### Phase 6: Testing
33+
- Test cash-or-nothing and asset-or-nothing variants
34+
- Test call/put symmetry where applicable
35+
- Test edge cases: ATM, deep ITM/OTM, zero time
36+
37+
### Phase 7: Documentation
38+
- Add docstrings explaining binary option behavior
39+
- Note discontinuous Delta at strike
40+
41+
## Technical Notes
42+
43+
### Cash-or-Nothing
44+
- **Call**: Pays Q if S_T > K
45+
- **Put**: Pays Q if S_T < K
46+
- Formula: `C = Q * e^(-rT) * N(d2)` where d2 is standard BS d2
47+
48+
### Asset-or-Nothing
49+
- **Call**: Pays S_T if S_T > K
50+
- **Put**: Pays S_T if S_T < K
51+
- Formula: `C = S * e^(-qT) * N(d1)` where d1 is standard BS d1
52+
53+
## Files to Modify/Create
54+
55+
- `src/pricing/binary.rs` - NEW: Binary option pricing functions
56+
- `src/pricing/mod.rs` - Export new module
57+
- `src/pricing/black_scholes_model.rs` - Route Binary to new functions
58+
59+
## Estimated Effort
60+
61+
4-6 hours
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Issue #240: Lookback Option Pricing Model
2+
3+
## Overview
4+
5+
Lookback options are path-dependent options with payoffs that depend on the maximum or minimum price of the underlying asset during the option's life. This implementation uses the Goldman-Sosin-Gatto (1979) closed-form solutions.
6+
7+
## Implementation Phases
8+
9+
### Phase 1: Core Data Model Verification
10+
- Verify `OptionType::Lookback { lookback_type: LookbackType }` exists
11+
- Check `LookbackType` enum for FixedStrike and FloatingStrike variants
12+
- Ensure the data model captures the observed min/max prices
13+
14+
### Phase 2: Floating Strike Lookback Options
15+
- **Call**: buyer pays minimum price (S_min), always exercised
16+
- Formula: Standard Black-Scholes + premium for lookback feature
17+
- **Put**: buyer receives maximum price (S_max), always exercised
18+
- Uses Goldman-Sosin-Gatto closed-form
19+
20+
### Phase 3: Fixed Strike Lookback Options
21+
- **Call**: Payoff = max(S_max - K, 0)
22+
- **Put**: Payoff = max(K - S_min, 0)
23+
- Uses Conze-Viswanathan formulas
24+
25+
### Phase 4: Goldman-Sosin-Gatto Formulas
26+
For floating strike lookback call (new contract):
27+
```
28+
C = S*N(a1) - S*e^(-rT)*(sigma^2/(2r))*N(-a1)
29+
- S*e^(-rT)*N(a2) + S*(sigma^2/(2r))*N(a3)
30+
```
31+
Where a1, a2, a3 are adjusted d-values.
32+
33+
### Phase 5: Integration
34+
- Create `src/pricing/lookback.rs` with all pricing functions
35+
- Route `OptionType::Lookback` in `black_scholes_model.rs`
36+
- Export from `mod.rs`
37+
38+
### Phase 6: Greeks
39+
- Use numerical Greeks from existing `src/greeks/numerical.rs`
40+
41+
### Phase 7: Testing
42+
- Test floating and fixed strike variants
43+
- Test call/put pricing
44+
- Test edge cases: ATM, deep ITM/OTM, zero time
45+
46+
### Phase 8: Documentation
47+
- Add docstrings explaining lookback behavior
48+
- Document the path-dependent nature
49+
50+
## Technical Notes
51+
52+
### Floating Strike Lookback
53+
- Call: `C = S*N(a1) - S_min*e^(-rT)*N(a2) + Y(lambda=1)`
54+
- Put: `P = S_max*e^(-rT)*N(b1) - S*N(b2) + Y(lambda=-1)`
55+
56+
### Fixed Strike Lookback
57+
- Uses standard BS formulas with S_max or S_min instead of S
58+
59+
### Key Parameters
60+
- For new contracts: S_min = S_max = S (current price)
61+
- For seasoned contracts: actual observed min/max prices
62+
63+
## Files to Modify/Create
64+
65+
- `src/pricing/lookback.rs` - NEW: Lookback option pricing functions
66+
- `src/pricing/mod.rs` - Export new module
67+
- `src/pricing/black_scholes_model.rs` - Route Lookback to new functions
68+
69+
## Estimated Effort
70+
71+
8-12 hours
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Issue #241: Compound Option Pricing Model
2+
3+
## Overview
4+
5+
Compound options are options on options. They have two layers: an outer option (compound) and an inner option (underlying). The holder of a compound option can exercise at T1 to receive (or sell) the underlying option that expires at T2.
6+
7+
## Implementation Phases
8+
9+
### Phase 1: Core Data Model Verification
10+
- Verify `OptionType::Compound { compound_type: CompoundType }` exists
11+
- Check `CompoundType` enum for the four variants:
12+
- CallOnCall, CallOnPut, PutOnCall, PutOnPut
13+
- Ensure data model captures both strikes (K1, K2) and expiries (T1, T2)
14+
15+
### Phase 2: Bivariate Normal Distribution
16+
- Implement bivariate CDF approximation (Drezner-Wesolowsky)
17+
- Required for Geske (1979) compound option formulas
18+
- Create helper function: `bivariate_normal_cdf(a, b, rho)`
19+
20+
### Phase 3: Critical Value Calculation
21+
- Find critical underlying price S* where compound option is ATM at T1
22+
- Solve: f(S*) = 0 where f is the underlying option value minus K1
23+
- Use Newton-Raphson or bisection method
24+
25+
### Phase 4: Compound Option Pricing (Geske 1979)
26+
- **Call-on-Call**: Right to buy a call option
27+
- **Call-on-Put**: Right to buy a put option
28+
- **Put-on-Call**: Right to sell a call option
29+
- **Put-on-Put**: Right to sell a put option
30+
31+
### Phase 5: Integration
32+
- Create `src/pricing/compound.rs` with all pricing functions
33+
- Route `OptionType::Compound` in `black_scholes_model.rs`
34+
- Export from `mod.rs`
35+
36+
### Phase 6: Greeks
37+
- Use numerical Greeks from existing module
38+
39+
### Phase 7: Testing
40+
- Test all four compound types
41+
- Test edge cases: T1 ≈ T2, deep ITM/OTM
42+
43+
## Technical Notes
44+
45+
### Geske Formula Key Components
46+
- Two cumulative normal distributions N(d1), N(d2)
47+
- One bivariate normal distribution M(a, b, rho)
48+
- Correlation rho = sqrt(T1/T2)
49+
50+
### Parameters
51+
- S: current underlying price
52+
- K1: strike of compound option
53+
- K2: strike of underlying option
54+
- T1: time to compound expiry
55+
- T2: time to underlying expiry (T2 > T1)
56+
- r: risk-free rate
57+
- σ: volatility
58+
59+
## Files to Modify/Create
60+
61+
- `src/pricing/compound.rs` - NEW: Compound option pricing functions
62+
- `src/pricing/mod.rs` - Export new module
63+
- `src/pricing/black_scholes_model.rs` - Route Compound to new functions
64+
65+
## Estimated Effort
66+
67+
8-12 hours
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Issue #242: Chooser Option Pricing Model
2+
3+
## Overview
4+
5+
Chooser options allow the holder to choose at a specified date (choice date) whether the option becomes a call or a put. Uses Rubinstein (1991) decomposition.
6+
7+
## Implementation Phases
8+
9+
### Phase 1: Core Data Model Verification
10+
- Verify `OptionType::Chooser { choice_date: f64 }` exists
11+
- Ensure choice_date is captured as time until choice
12+
13+
### Phase 2: Simple Chooser (Rubinstein 1991)
14+
- Same strike K and expiration T for both call and put
15+
- Choice date t < T
16+
- Formula: Chooser = Call(K, T) + Put(K, t) * e^(-(r-q)(T-t))
17+
- Alternative: C + Se^(-q*t)*N(-y2) - Ke^(-r*t)*N(-y1 + sigma*sqrt(t))
18+
19+
### Phase 3: Complex Chooser (Optional)
20+
- Different strikes and/or expirations for call vs put
21+
- More complex valuation
22+
23+
### Phase 4: Integration
24+
- Create `src/pricing/chooser.rs`
25+
- Route `OptionType::Chooser` in `black_scholes_model.rs`
26+
- Export from `mod.rs`
27+
28+
### Phase 5: Testing
29+
- Test simple chooser pricing
30+
- Test edge cases: choice_date = 0, choice_date = T
31+
- Test call/put parity relationships
32+
33+
## Technical Notes
34+
35+
### Simple Chooser Formula
36+
```
37+
V = S*e^(-qT)*N(d1) - K*e^(-rT)*N(d2)
38+
+ K*e^(-rT)*N(-y2) - S*e^(-qT)*N(-y1)
39+
```
40+
Where:
41+
- d1, d2 are standard BS d-values for T
42+
- y1 = [ln(S/K) + (b + σ²/2)t] / (σ√t)
43+
- y2 = y1 - σ√t
44+
- t = choice date, T = expiration
45+
46+
## Files to Modify/Create
47+
48+
- `src/pricing/chooser.rs` - NEW
49+
- `src/pricing/mod.rs` - Export
50+
- `src/pricing/black_scholes_model.rs` - Route
51+
52+
## Estimated Effort
53+
54+
6-8 hours
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Issue #243: Cliquet Option Pricing Model
2+
3+
## Overview
4+
5+
Cliquet options (ratchet options) reset their strike periodically, locking in gains. The payoff is the sum of capped/floored returns over each period.
6+
7+
## Implementation Phases
8+
9+
### Phase 1: Core Data Model Verification
10+
- Verify `OptionType::Cliquet { reset_dates: Vec<f64> }` exists
11+
- Ensure reset_dates captures the periodic reset schedule
12+
13+
### Phase 2: Forward-Starting Option Approach
14+
- Treat each period as an independent forward-starting option
15+
- Price each period's contribution and sum them
16+
- Apply local caps/floors to each period's return
17+
18+
### Phase 3: Cliquet Pricing Formula
19+
- For each period i with return R_i = (S_i - S_{i-1}) / S_{i-1}
20+
- Capped return: min(max(R_i, floor), cap)
21+
- Total value: Sum of discounted capped returns
22+
23+
### Phase 4: Integration
24+
- Create `src/pricing/cliquet.rs`
25+
- Route `OptionType::Cliquet` in `black_scholes_model.rs`
26+
- Export from `mod.rs`
27+
28+
### Phase 5: Testing
29+
- Test with various reset frequencies
30+
- Test caps and floors
31+
- Test edge cases
32+
33+
## Technical Notes
34+
35+
### Payoff Structure
36+
- Total Payoff = Σ max(min(R_i, cap), floor)
37+
- R_i = return in period i
38+
39+
### Pricing Approach
40+
- Analytical: Sum of forward-starting call/put spreads
41+
- Each period contributes: BS_call(K=1, T_i) - BS_call(K=1+cap, T_i)
42+
43+
### Default Parameters
44+
- Local cap: 10% per period
45+
- Local floor: 0% per period
46+
- Global cap/floor: Not implemented in first version
47+
48+
## Files to Modify/Create
49+
50+
- `src/pricing/cliquet.rs` - NEW
51+
- `src/pricing/mod.rs` - Export
52+
- `src/pricing/black_scholes_model.rs` - Route
53+
54+
## Estimated Effort
55+
56+
10-14 hours

0 commit comments

Comments
 (0)