finance_query/models/chart/
events.rs1use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::sync::OnceLock;
8
9#[derive(Debug, Default, Serialize, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub(crate) struct ChartEvents {
16 #[serde(default)]
18 pub dividends: HashMap<String, DividendEvent>,
19 #[serde(default)]
21 pub splits: HashMap<String, SplitEvent>,
22 #[serde(default)]
24 pub capital_gains: HashMap<String, CapitalGainEvent>,
25
26 #[serde(skip)]
28 dividends_cache: OnceLock<Vec<Dividend>>,
29 #[serde(skip)]
31 splits_cache: OnceLock<Vec<Split>>,
32 #[serde(skip)]
34 capital_gains_cache: OnceLock<Vec<CapitalGain>>,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39pub(crate) struct DividendEvent {
40 pub amount: f64,
42 pub date: i64,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(rename_all = "camelCase")]
49pub(crate) struct SplitEvent {
50 pub date: i64,
52 pub numerator: f64,
54 pub denominator: f64,
56 pub split_ratio: String,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
62pub(crate) struct CapitalGainEvent {
63 pub amount: f64,
65 pub date: i64,
67}
68
69#[non_exhaustive]
73#[derive(Debug, Clone, Serialize, Deserialize)]
74#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
75pub struct Dividend {
76 pub timestamp: i64,
78 pub amount: f64,
80}
81
82#[non_exhaustive]
86#[derive(Debug, Clone, Serialize, Deserialize)]
87#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
88pub struct Split {
89 pub timestamp: i64,
91 pub numerator: f64,
93 pub denominator: f64,
95 pub ratio: String,
97}
98
99#[non_exhaustive]
103#[derive(Debug, Clone, Serialize, Deserialize)]
104#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
105pub struct CapitalGain {
106 pub timestamp: i64,
108 pub amount: f64,
110}
111
112impl Clone for ChartEvents {
113 fn clone(&self) -> Self {
114 fn clone_cache<T: Clone>(cache: &OnceLock<T>) -> OnceLock<T> {
116 let new_cache = OnceLock::new();
117 if let Some(value) = cache.get() {
118 let _ = new_cache.set(value.clone());
119 }
120 new_cache
121 }
122
123 Self {
124 dividends: self.dividends.clone(),
125 splits: self.splits.clone(),
126 capital_gains: self.capital_gains.clone(),
127 dividends_cache: clone_cache(&self.dividends_cache),
128 splits_cache: clone_cache(&self.splits_cache),
129 capital_gains_cache: clone_cache(&self.capital_gains_cache),
130 }
131 }
132}
133
134impl ChartEvents {
135 pub(crate) fn to_dividends(&self) -> Vec<Dividend> {
137 self.dividends_cache
138 .get_or_init(|| {
139 let mut dividends: Vec<Dividend> = self
140 .dividends
141 .values()
142 .map(|d| Dividend {
143 timestamp: d.date,
144 amount: d.amount,
145 })
146 .collect();
147 dividends.sort_by_key(|d| d.timestamp);
148 dividends
149 })
150 .clone()
151 }
152
153 pub(crate) fn to_splits(&self) -> Vec<Split> {
155 self.splits_cache
156 .get_or_init(|| {
157 let mut splits: Vec<Split> = self
158 .splits
159 .values()
160 .map(|s| Split {
161 timestamp: s.date,
162 numerator: s.numerator,
163 denominator: s.denominator,
164 ratio: s.split_ratio.clone(),
165 })
166 .collect();
167 splits.sort_by_key(|s| s.timestamp);
168 splits
169 })
170 .clone()
171 }
172
173 pub(crate) fn to_capital_gains(&self) -> Vec<CapitalGain> {
175 self.capital_gains_cache
176 .get_or_init(|| {
177 let mut gains: Vec<CapitalGain> = self
178 .capital_gains
179 .values()
180 .map(|g| CapitalGain {
181 timestamp: g.date,
182 amount: g.amount,
183 })
184 .collect();
185 gains.sort_by_key(|g| g.timestamp);
186 gains
187 })
188 .clone()
189 }
190}