use crate::chains::OptionChainBuildParams;
use positive::Positive;
use pretty_simple_display::{DebugPretty, DisplaySimple};
use serde::{Deserialize, Serialize};
#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
pub struct OptionSeriesBuildParams {
pub(crate) chain_params: OptionChainBuildParams,
pub(crate) series: Vec<Positive>,
}
impl OptionSeriesBuildParams {
#[inline]
#[must_use]
pub fn new(chain_params: OptionChainBuildParams, series: Vec<Positive>) -> Self {
Self {
chain_params,
series,
}
}
#[inline]
pub fn set_underlying_price(&mut self, price: &Positive) {
let price = Some(Box::new(*price));
self.chain_params.set_underlying_price(price);
}
#[inline]
pub fn set_implied_volatility(&mut self, volatility: Positive) {
self.chain_params.set_implied_volatility(volatility);
}
}
#[cfg(test)]
mod tests {
use super::*;
use positive::{Positive, pos_or_panic, spos};
use crate::ExpirationDate;
use crate::chains::utils::OptionDataPriceParams;
use rust_decimal_macros::dec;
#[test]
fn test_display_empty_series() {
let expiration = ExpirationDate::Days(pos_or_panic!(30.0));
let price_params = OptionDataPriceParams::new(
Some(Box::new(Positive::HUNDRED)),
Some(expiration),
Some(dec!(0.05)),
spos!(0.02),
Some("AAPL".to_string()),
);
let chain_params = OptionChainBuildParams::new(
"AAPL".to_string(),
spos!(1000.0),
10,
spos!(5.0),
dec!(-0.2),
dec!(0.1),
pos_or_panic!(0.02),
2,
price_params,
pos_or_panic!(0.2),
);
let params = OptionSeriesBuildParams {
chain_params,
series: vec![],
};
let result = r#"{"chain_params":{"symbol":"AAPL","volume":"1000","chain_size":10,"strike_interval":"5","skew_slope":"-0.2","smile_curve":"0.1","spread":"0.02","decimal_places":2,"price_params":{"underlying_price":"100","expiration_date":{"days":30.0},"risk_free_rate":"0.05","dividend_yield":"0.02","underlying_symbol":"AAPL"},"implied_volatility":"0.2"},"series":[]}"#;
assert_eq!(params.to_string(), result);
}
#[test]
fn test_debug_empty_series() {
let expiration = ExpirationDate::Days(pos_or_panic!(30.0));
let price_params = OptionDataPriceParams::new(
Some(Box::new(Positive::HUNDRED)),
Some(expiration),
Some(dec!(0.05)),
spos!(0.02),
Some("AAPL".to_string()),
);
let chain_params = OptionChainBuildParams::new(
"AAPL".to_string(),
spos!(1000.0),
10,
spos!(5.0),
dec!(-0.2),
dec!(0.1),
pos_or_panic!(0.02),
2,
price_params,
pos_or_panic!(0.2),
);
let params = OptionSeriesBuildParams {
chain_params,
series: vec![],
};
let result = r#"{
"chain_params": {
"symbol": "AAPL",
"volume": "1000",
"chain_size": 10,
"strike_interval": "5",
"skew_slope": "-0.2",
"smile_curve": "0.1",
"spread": "0.02",
"decimal_places": 2,
"price_params": {
"underlying_price": "100",
"expiration_date": {
"days": 30.0
},
"risk_free_rate": "0.05",
"dividend_yield": "0.02",
"underlying_symbol": "AAPL"
},
"implied_volatility": "0.2"
},
"series": []
}"#;
let debug_result = format!("{params:?}");
assert_eq!(debug_result, result);
}
}