rust_options/
lib.rs

1// lib.rs
2
3
4pub mod pricing {
5    use statrs::distribution::Normal;
6    use statrs::distribution::ContinuousCDF;
7
8    pub fn black_scholes_call_price(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
9        let d1 = ((s / k).ln() + (r + 0.5 * v * v) * t) / (v * t.sqrt());
10        let d2 = d1 - v * t.sqrt();
11        let norm = Normal::new(0.0, 1.0).unwrap();
12        s * norm.cdf(d1) - k * (-r * t).exp() * norm.cdf(d2)
13    }
14
15    pub fn black_scholes_put_price(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
16        let d1 = ((s / k).ln() + (r + 0.5 * v * v) * t) / (v * t.sqrt());
17        let d2 = d1 - v * t.sqrt();
18        let norm = Normal::new(0.0, 1.0).unwrap();
19        k * (-r * t).exp() * norm.cdf(-d2) - s * norm.cdf(-d1)
20    }
21}
22
23
24pub mod greeks {
25    use statrs::distribution::Normal;
26    use statrs::distribution::ContinuousCDF;
27    use statrs::distribution::Continuous;
28
29    fn d1(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
30        ((s / k).ln() + (r + 0.5 * v * v) * t) / (v * t.sqrt())
31    }
32
33    fn d2(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
34        d1(s, k, t, r, v) - v * t.sqrt()
35    }
36
37    pub fn delta_call(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
38        let d1 = ((s / k).ln() + (r + 0.5 * v * v) * t) / (v * t.sqrt());
39        Normal::new(0.0, 1.0).unwrap().cdf(d1)
40    }
41
42    pub fn delta_put(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
43        delta_call(s, k, t, r, v) - 1.0
44    }
45    pub fn gamma(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
46    let norm = Normal::new(0.0, 1.0).unwrap();
47    norm.pdf(d1(s, k, t, r, v)) / (s * v * t.sqrt())
48}
49
50    pub fn vega(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
51        let norm = Normal::new(0.0, 1.0).unwrap();
52        s * norm.pdf(d1(s, k, t, r, v)) * t.sqrt() / 100.0 // per 1% change
53    }
54
55    pub fn theta_call(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
56        let norm = Normal::new(0.0, 1.0).unwrap();
57        let d1 = d1(s, k, t, r, v);
58        let d2 = d2(s, k, t, r, v);
59        let term1 = -s * norm.pdf(d1) * v / (2.0 * t.sqrt());
60        let term2 = r * k * (-r * t).exp() * norm.cdf(d2);
61        (term1 - term2) / 365.0
62    }
63
64    pub fn theta_put(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
65        let norm = Normal::new(0.0, 1.0).unwrap();
66        let d1 = d1(s, k, t, r, v);
67        let d2 = d2(s, k, t, r, v);
68        let term1 = -s * norm.pdf(d1) * v / (2.0 * t.sqrt());
69        let term2 = r * k * (-r * t).exp() * norm.cdf(-d2);
70        (term1 + term2) / 365.0
71    }
72
73    pub fn rho_call(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
74        let norm = Normal::new(0.0, 1.0).unwrap();
75        k * t * (-r * t).exp() * norm.cdf(d2(s, k, t, r, v)) / 100.0
76    }
77
78    pub fn rho_put(s: f64, k: f64, t: f64, r: f64, v: f64) -> f64 {
79        let norm = Normal::new(0.0, 1.0).unwrap();
80        -k * t * (-r * t).exp() * norm.cdf(-d2(s, k, t, r, v)) / 100.0
81    }
82
83}
84
85pub mod strategy {
86    /// Returns the payoff for a long call option
87    pub fn long_call_payoff(s: f64, k: f64, premium: f64) -> f64 {
88        (s - k).max(0.0) - premium
89    }
90
91    /// Returns the payoff for a short call option
92    pub fn short_call_payoff(s: f64, k: f64, premium: f64) -> f64 {
93        premium - (s - k).max(0.0)
94    }
95
96    /// Returns the payoff for a long put option
97    pub fn long_put_payoff(s: f64, k: f64, premium: f64) -> f64 {
98        (k - s).max(0.0) - premium
99    }
100
101    /// Returns the payoff for a short put option
102    pub fn short_put_payoff(s: f64, k: f64, premium: f64) -> f64 {
103        premium - (k - s).max(0.0)
104    }
105
106    /// Payoff for a long call spread (buy call at k1, sell call at k2)
107    pub fn long_call_spread(s: f64, k1: f64, c1: f64, k2: f64, c2: f64) -> f64 {
108        long_call_payoff(s, k1, c1) + short_call_payoff(s, k2, c2)
109    }
110
111    /// Payoff for a short call spread (sell call at k1, buy call at k2)
112    pub fn short_call_spread(s: f64, k1: f64, c1: f64, k2: f64, c2: f64) -> f64 {
113        short_call_payoff(s, k1, c1) + long_call_payoff(s, k2, c2)
114    }
115
116    /// Payoff for a long put spread (buy put at k1, sell put at k2)
117    pub fn long_put_spread(s: f64, k1: f64, p1: f64, k2: f64, p2: f64) -> f64 {
118        long_put_payoff(s, k1, p1) + short_put_payoff(s, k2, p2)
119    }
120
121    /// Payoff for a short put spread (sell put at k1, buy put at k2)
122    pub fn short_put_spread(s: f64, k1: f64, p1: f64, k2: f64, p2: f64) -> f64 {
123        short_put_payoff(s, k1, p1) + long_put_payoff(s, k2, p2)
124    }
125
126    /// Payoff for a long straddle (buy call and put at same strike)
127    pub fn long_straddle(s: f64, k: f64, c: f64, p: f64) -> f64 {
128        long_call_payoff(s, k, c) + long_put_payoff(s, k, p)
129    }
130
131    /// Payoff for a short straddle (sell call and put at same strike)
132    pub fn short_straddle(s: f64, k: f64, c: f64, p: f64) -> f64 {
133        short_call_payoff(s, k, c) + short_put_payoff(s, k, p)
134    }
135
136    /// Payoff for a long strangle (buy OTM call and OTM put)
137    pub fn long_strangle(s: f64, kc: f64, c: f64, kp: f64, p: f64) -> f64 {
138        long_call_payoff(s, kc, c) + long_put_payoff(s, kp, p)
139    }
140
141    /// Payoff for a short strangle (sell OTM call and OTM put)
142    pub fn short_strangle(s: f64, kc: f64, c: f64, kp: f64, p: f64) -> f64 {
143        short_call_payoff(s, kc, c) + short_put_payoff(s, kp, p)
144    }
145
146}
147
148pub mod options {
149    pub enum OptionType {
150        Call,
151        Put
152    }
153
154pub struct Option {
155        pub option_type: OptionType,
156        pub rfr: f64,
157        pub strike: f64,
158        pub spot: f64,
159        pub iv: f64
160    }
161}