use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpgradeDowngradeHistory {
#[serde(default)]
pub history: Vec<GradeChange>,
#[serde(default)]
pub max_age: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GradeChange {
#[serde(default)]
pub epoch_grade_date: Option<i64>,
#[serde(default)]
pub firm: Option<String>,
#[serde(default)]
pub from_grade: Option<String>,
#[serde(default)]
pub to_grade: Option<String>,
#[serde(default)]
pub action: Option<String>,
#[serde(default)]
pub prior_price_target: Option<f64>,
#[serde(default)]
pub current_price_target: Option<f64>,
#[serde(default)]
pub price_target_action: Option<String>,
}
impl GradeChange {
pub fn is_upgrade(&self) -> bool {
matches!(
self.action.as_deref(),
Some("up") | Some("init-upgrade") | Some("reit-up")
)
}
pub fn is_downgrade(&self) -> bool {
matches!(
self.action.as_deref(),
Some("down") | Some("init-downgrade") | Some("reit-down")
)
}
pub fn price_target_raised(&self) -> bool {
self.price_target_action.as_deref() == Some("Raises")
}
pub fn price_target_lowered(&self) -> bool {
self.price_target_action.as_deref() == Some("Lowers")
}
pub fn price_target_change(&self) -> Option<f64> {
match (self.current_price_target, self.prior_price_target) {
(Some(current), Some(prior)) => Some(current - prior),
_ => None,
}
}
pub fn price_target_change_percent(&self) -> Option<f64> {
match (self.current_price_target, self.prior_price_target) {
(Some(current), Some(prior)) if prior != 0.0 => {
Some(((current - prior) / prior) * 100.0)
}
_ => None,
}
}
}