use crate::curves::Curve;
use crate::error::CurveError;
pub trait OpenInterestCurve {
fn open_interest_curve(&self) -> Result<Curve, CurveError>;
}
#[cfg(test)]
mod tests_open_interest {
use super::*;
use crate::curves::Point2D;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use std::collections::BTreeSet;
struct TestOpenInterest;
impl OpenInterestCurve for TestOpenInterest {
fn open_interest_curve(&self) -> Result<Curve, CurveError> {
let mut points = BTreeSet::new();
let strikes = [
(dec!(380.0), dec!(2500.0)),
(dec!(400.0), dec!(8000.0)), (dec!(420.0), dec!(5000.0)),
(dec!(440.0), dec!(6500.0)),
(dec!(450.0), dec!(15000.0)), (dec!(460.0), dec!(7000.0)),
(dec!(480.0), dec!(5500.0)),
(dec!(500.0), dec!(10000.0)), (dec!(520.0), dec!(3000.0)),
];
for (strike, oi) in strikes {
points.insert(Point2D::new(strike, oi));
}
Ok(Curve::new(points))
}
}
#[test]
fn test_open_interest_curve_creation() {
let oi = TestOpenInterest;
let curve = oi.open_interest_curve();
assert!(curve.is_ok());
let curve = curve.unwrap();
assert_eq!(curve.points.len(), 9);
}
#[test]
fn test_open_interest_max_at_atm() {
let oi = TestOpenInterest;
let curve = oi.open_interest_curve().unwrap();
let points: Vec<&Point2D> = curve.points.iter().collect();
let max_oi = points
.iter()
.max_by(|a, b| a.y.partial_cmp(&b.y).unwrap_or(std::cmp::Ordering::Equal));
if let Some(max) = max_oi {
assert_eq!(max.x, dec!(450.0));
assert_eq!(max.y, dec!(15000.0));
}
}
#[test]
fn test_open_interest_round_strikes_higher() {
let oi = TestOpenInterest;
let curve = oi.open_interest_curve().unwrap();
let points: Vec<&Point2D> = curve.points.iter().collect();
let oi_400 = points.iter().find(|p| p.x == dec!(400.0)).unwrap().y;
let oi_420 = points.iter().find(|p| p.x == dec!(420.0)).unwrap().y;
let oi_380 = points.iter().find(|p| p.x == dec!(380.0)).unwrap().y;
assert!(oi_400 > oi_420);
assert!(oi_400 > oi_380);
}
#[test]
fn test_open_interest_positive_values() {
let oi = TestOpenInterest;
let curve = oi.open_interest_curve().unwrap();
for point in curve.points.iter() {
assert!(point.y > Decimal::ZERO);
}
}
#[test]
fn test_open_interest_strike_ordering() {
let oi = TestOpenInterest;
let curve = oi.open_interest_curve().unwrap();
let points: Vec<&Point2D> = curve.points.iter().collect();
for i in 1..points.len() {
assert!(points[i].x > points[i - 1].x);
}
}
}