Skip to main content

rustrade_data/subscription/
greeks.rs

1//! Option Greeks subscription type.
2//!
3//! This module defines the [`OptionGreeks`] data type for option analytics
4//! (delta, gamma, theta, vega, implied volatility).
5//!
6//! Unlike other subscription types in this module, Greeks are typically
7//! computed by the exchange/broker from live market data rather than being
8//! raw market data themselves.
9
10use serde::{Deserialize, Serialize};
11
12/// Option Greeks values.
13///
14/// All fields are optional because the data source may not return all Greeks
15/// depending on the contract type, market state, or subscription level.
16///
17/// # Fields
18///
19/// - `delta`: Rate of change of option price with respect to underlying price
20/// - `gamma`: Rate of change of delta with respect to underlying price
21/// - `theta`: Rate of change of option price with respect to time (per day)
22/// - `vega`: Rate of change of option price with respect to volatility
23/// - `implied_volatility`: Market-implied volatility
24/// - `theoretical_price`: Model price computed by the exchange/broker
25/// - `underlying_price`: Current underlying price used in computation
26///
27/// # Note on Precision
28///
29/// Values are stored as `f64` rather than `Decimal` because Greeks are
30/// analytics (not monetary values) and the precision loss is acceptable.
31#[non_exhaustive]
32#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
33pub struct OptionGreeks {
34    pub delta: Option<f64>,
35    pub gamma: Option<f64>,
36    pub theta: Option<f64>,
37    pub vega: Option<f64>,
38    pub implied_volatility: Option<f64>,
39    pub theoretical_price: Option<f64>,
40    pub underlying_price: Option<f64>,
41}
42
43impl OptionGreeks {
44    /// Returns true if at least one first-order Greek (delta, gamma, theta,
45    /// vega, or implied volatility) is present.
46    ///
47    /// Does NOT consider `theoretical_price` or `underlying_price` — a tick
48    /// containing only those fields is treated as having no Greek data.
49    pub fn has_any_greek(&self) -> bool {
50        self.delta.is_some()
51            || self.gamma.is_some()
52            || self.theta.is_some()
53            || self.vega.is_some()
54            || self.implied_volatility.is_some()
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn option_greeks_default_has_no_values() {
64        let greeks = OptionGreeks::default();
65        assert!(!greeks.has_any_greek());
66    }
67
68    #[test]
69    fn option_greeks_partial_has_any_greek() {
70        let greeks = OptionGreeks {
71            delta: Some(0.55),
72            ..Default::default()
73        };
74        assert!(greeks.has_any_greek());
75    }
76
77    #[test]
78    fn option_greeks_full_has_any_greek() {
79        let greeks = OptionGreeks {
80            delta: Some(0.55),
81            gamma: Some(0.02),
82            theta: Some(-0.05),
83            vega: Some(0.15),
84            implied_volatility: Some(0.25),
85            theoretical_price: Some(5.50),
86            underlying_price: Some(150.0),
87        };
88        assert!(greeks.has_any_greek());
89    }
90
91    #[test]
92    fn option_greeks_price_only_has_no_greek() {
93        let greeks = OptionGreeks {
94            theoretical_price: Some(5.50),
95            underlying_price: Some(150.0),
96            ..Default::default()
97        };
98        assert!(!greeks.has_any_greek());
99    }
100}