finance_query/models/chart/
events.rs

1//! Chart events module
2//!
3//! Contains dividend, split, and capital gain data structures.
4
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8/// Chart events containing dividends, splits, and capital gains
9#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase")]
11pub(crate) struct ChartEvents {
12    /// Dividend events keyed by timestamp
13    #[serde(default)]
14    pub dividends: HashMap<String, DividendEvent>,
15    /// Stock split events keyed by timestamp
16    #[serde(default)]
17    pub splits: HashMap<String, SplitEvent>,
18    /// Capital gain events keyed by timestamp
19    #[serde(default)]
20    pub capital_gains: HashMap<String, CapitalGainEvent>,
21}
22
23/// Raw dividend event from Yahoo Finance
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub(crate) struct DividendEvent {
26    /// Dividend amount per share
27    pub amount: f64,
28    /// Timestamp of the dividend
29    pub date: i64,
30}
31
32/// Raw split event from Yahoo Finance
33#[derive(Debug, Clone, Serialize, Deserialize)]
34#[serde(rename_all = "camelCase")]
35pub(crate) struct SplitEvent {
36    /// Timestamp of the split
37    pub date: i64,
38    /// Numerator of the split ratio
39    pub numerator: f64,
40    /// Denominator of the split ratio
41    pub denominator: f64,
42    /// Split ratio as string (e.g., "2:1", "10:1")
43    pub split_ratio: String,
44}
45
46/// Raw capital gain event from Yahoo Finance
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub(crate) struct CapitalGainEvent {
49    /// Capital gain amount per share
50    pub amount: f64,
51    /// Timestamp of the capital gain distribution
52    pub date: i64,
53}
54
55/// Public dividend data
56///
57/// Note: This struct cannot be manually constructed - obtain via `Ticker::dividends()`.
58#[non_exhaustive]
59#[derive(Debug, Clone, Serialize, Deserialize)]
60#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
61pub struct Dividend {
62    /// Timestamp (Unix)
63    pub timestamp: i64,
64    /// Dividend amount per share
65    pub amount: f64,
66}
67
68/// Public stock split data
69///
70/// Note: This struct cannot be manually constructed - obtain via `Ticker::splits()`.
71#[non_exhaustive]
72#[derive(Debug, Clone, Serialize, Deserialize)]
73#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
74pub struct Split {
75    /// Timestamp (Unix)
76    pub timestamp: i64,
77    /// Numerator of the split ratio
78    pub numerator: f64,
79    /// Denominator of the split ratio
80    pub denominator: f64,
81    /// Split ratio as string (e.g., "2:1", "10:1")
82    pub ratio: String,
83}
84
85/// Public capital gain data
86///
87/// Note: This struct cannot be manually constructed - obtain via `Ticker::capital_gains()`.
88#[non_exhaustive]
89#[derive(Debug, Clone, Serialize, Deserialize)]
90#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
91pub struct CapitalGain {
92    /// Timestamp (Unix)
93    pub timestamp: i64,
94    /// Capital gain amount per share
95    pub amount: f64,
96}
97
98impl ChartEvents {
99    /// Convert to sorted list of dividends
100    pub(crate) fn to_dividends(&self) -> Vec<Dividend> {
101        let mut dividends: Vec<Dividend> = self
102            .dividends
103            .values()
104            .map(|d| Dividend {
105                timestamp: d.date,
106                amount: d.amount,
107            })
108            .collect();
109        dividends.sort_by_key(|d| d.timestamp);
110        dividends
111    }
112
113    /// Convert to sorted list of splits
114    pub(crate) fn to_splits(&self) -> Vec<Split> {
115        let mut splits: Vec<Split> = self
116            .splits
117            .values()
118            .map(|s| Split {
119                timestamp: s.date,
120                numerator: s.numerator,
121                denominator: s.denominator,
122                ratio: s.split_ratio.clone(),
123            })
124            .collect();
125        splits.sort_by_key(|s| s.timestamp);
126        splits
127    }
128
129    /// Convert to sorted list of capital gains
130    pub(crate) fn to_capital_gains(&self) -> Vec<CapitalGain> {
131        let mut gains: Vec<CapitalGain> = self
132            .capital_gains
133            .values()
134            .map(|g| CapitalGain {
135                timestamp: g.date,
136                amount: g.amount,
137            })
138            .collect();
139        gains.sort_by_key(|g| g.timestamp);
140        gains
141    }
142}