use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Strike(pub f64);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Tenor(pub f64);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Vol(pub f64);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Variance(pub f64);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum OptionType {
Call,
Put,
}
impl fmt::Display for Strike {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Display for Tenor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Display for Vol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Display for Variance {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Display for OptionType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
OptionType::Call => f.write_str("Call"),
OptionType::Put => f.write_str("Put"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn strike_serde_round_trip() {
let s = Strike(123.456);
let json = serde_json::to_string(&s).unwrap();
let s2: Strike = serde_json::from_str(&json).unwrap();
assert_eq!(s, s2);
}
#[test]
fn tenor_serde_round_trip() {
let t = Tenor(0.25);
let json = serde_json::to_string(&t).unwrap();
let t2: Tenor = serde_json::from_str(&json).unwrap();
assert_eq!(t, t2);
}
#[test]
fn vol_serde_round_trip() {
let v = Vol(0.20);
let json = serde_json::to_string(&v).unwrap();
let v2: Vol = serde_json::from_str(&json).unwrap();
assert_eq!(v, v2);
}
#[test]
fn variance_serde_round_trip() {
let v = Variance(0.04);
let json = serde_json::to_string(&v).unwrap();
let v2: Variance = serde_json::from_str(&json).unwrap();
assert_eq!(v, v2);
}
#[test]
fn option_type_call_serde_round_trip() {
let ot = OptionType::Call;
let json = serde_json::to_string(&ot).unwrap();
let ot2: OptionType = serde_json::from_str(&json).unwrap();
assert_eq!(ot, ot2);
}
#[test]
fn option_type_put_serde_round_trip() {
let ot = OptionType::Put;
let json = serde_json::to_string(&ot).unwrap();
let ot2: OptionType = serde_json::from_str(&json).unwrap();
assert_eq!(ot, ot2);
}
#[test]
fn serde_preserves_special_float_values() {
let values = [0.0, -0.0, 1e-300, 1e300, f64::MIN_POSITIVE];
for &v in &values {
let vol = Vol(v);
let json = serde_json::to_string(&vol).unwrap();
let vol2: Vol = serde_json::from_str(&json).unwrap();
assert_eq!(vol.0.to_bits(), vol2.0.to_bits());
}
}
}