use crate::curves::Curve;
use crate::error::CurveError;
pub trait BidAskSpreadCurve {
fn bid_ask_spread_curve(&self) -> Result<Curve, CurveError>;
}
#[cfg(test)]
mod tests_bid_ask_spread {
use super::*;
use crate::curves::Point2D;
use rust_decimal_macros::dec;
use std::collections::BTreeSet;
struct TestBidAskSpread;
impl BidAskSpreadCurve for TestBidAskSpread {
fn bid_ask_spread_curve(&self) -> Result<Curve, CurveError> {
let mut points = BTreeSet::new();
let strikes = [
(dec!(380.0), dec!(0.08)), (dec!(400.0), dec!(0.05)), (dec!(420.0), dec!(0.03)), (dec!(440.0), dec!(0.02)), (dec!(450.0), dec!(0.02)), (dec!(460.0), dec!(0.02)), (dec!(480.0), dec!(0.03)), (dec!(500.0), dec!(0.05)), (dec!(520.0), dec!(0.08)), ];
for (strike, spread) in strikes {
points.insert(Point2D::new(strike, spread));
}
Ok(Curve::new(points))
}
}
#[test]
fn test_bid_ask_spread_curve_creation() {
let spread = TestBidAskSpread;
let curve = spread.bid_ask_spread_curve();
assert!(curve.is_ok());
let curve = curve.unwrap();
assert_eq!(curve.points.len(), 9);
}
#[test]
fn test_bid_ask_spread_atm_tightest() {
let spread = TestBidAskSpread;
let curve = spread.bid_ask_spread_curve().unwrap();
let points: Vec<&Point2D> = curve.points.iter().collect();
let min_spread = points.iter().min_by(|a, b| a.y.partial_cmp(&b.y).unwrap());
if let Some(min) = min_spread {
assert!(min.x >= dec!(440.0) && min.x <= dec!(460.0));
assert_eq!(min.y, dec!(0.02));
}
}
#[test]
fn test_bid_ask_spread_otm_wider() {
let spread = TestBidAskSpread;
let curve = spread.bid_ask_spread_curve().unwrap();
let points: Vec<&Point2D> = curve.points.iter().collect();
let deep_otm_low = points.iter().find(|p| p.x == dec!(380.0)).unwrap();
let deep_otm_high = points.iter().find(|p| p.x == dec!(520.0)).unwrap();
let atm = points.iter().find(|p| p.x == dec!(450.0)).unwrap();
assert!(deep_otm_low.y > atm.y);
assert!(deep_otm_high.y > atm.y);
}
#[test]
fn test_bid_ask_spread_positive_values() {
let spread = TestBidAskSpread;
let curve = spread.bid_ask_spread_curve().unwrap();
for point in curve.points.iter() {
assert!(point.y > rust_decimal::Decimal::ZERO);
}
}
}