Skip to main content

egui_charts/ui/widget_bar/panels/
market_details.rs

1//! Host-supplied market detail: period returns and seasonality for a symbol, and the earnings,
2//! dividends and news the wide watchlist lists. The library asks and shows; the host answers.
3
4use crate::data::{CalendarEvent, NewsStory};
5
6/// What the host has answered for one section, until it answers again.
7#[derive(Clone, Debug, Default, PartialEq)]
8#[non_exhaustive]
9pub enum MarketDetail<T> {
10    /// The request is out.
11    Loading,
12    /// The answer. An empty one shows that there is nothing to list.
13    Ready(T),
14    /// The host does not supply this section.
15    #[default]
16    Unavailable,
17    /// The request failed with this message.
18    Failed(String),
19}
20
21/// A request for the symbol details panel's market detail, from
22/// [`SymbolDetailsPanel::take_market_requests`](super::SymbolDetailsPanel::take_market_requests).
23/// Answer with [`set_period_returns`](super::SymbolDetailsPanel::set_period_returns) or
24/// [`set_seasonality`](super::SymbolDetailsPanel::set_seasonality) for the same symbol.
25#[derive(Clone, Debug, PartialEq, Eq)]
26#[non_exhaustive]
27pub enum MarketDetailRequest {
28    /// The returns of this symbol over the usual look-back periods.
29    PeriodReturns(String),
30    /// The average return of this symbol in each calendar month.
31    Seasonality(String),
32}
33
34/// The return over one look-back period.
35#[derive(Clone, Debug, PartialEq)]
36#[non_exhaustive]
37pub struct PeriodReturn {
38    /// The period as the host names it, such as `"1M"` or `"YTD"`.
39    pub period: String,
40    /// The return in percent, or `None` when the history does not cover the period.
41    pub percent: Option<f64>,
42}
43
44impl PeriodReturn {
45    /// The return of `period`, `percent` when known.
46    pub fn new(period: impl Into<String>, percent: Option<f64>) -> Self {
47        Self {
48            period: period.into(),
49            percent,
50        }
51    }
52}
53
54/// How one calendar month has performed over the years of history.
55#[derive(Clone, Debug, PartialEq)]
56#[non_exhaustive]
57pub struct SeasonalityMonth {
58    /// The month, 1 for January to 12 for December.
59    pub month: u8,
60    /// The average return of the month in percent, or `None` without history.
61    pub average_percent: Option<f64>,
62    /// The share of years with a positive return in the month, from 0 to 1.
63    pub positive_share: Option<f64>,
64}
65
66impl SeasonalityMonth {
67    /// The summary of `month`.
68    pub fn new(month: u8, average_percent: Option<f64>, positive_share: Option<f64>) -> Self {
69        Self {
70            month,
71            average_percent,
72            positive_share,
73        }
74    }
75}
76
77/// The monthly seasonality of a symbol.
78#[derive(Clone, Debug, PartialEq)]
79#[non_exhaustive]
80pub struct Seasonality {
81    /// The years of history the figures cover.
82    pub years: u32,
83    /// The months that have a summary, in calendar order.
84    pub months: Vec<SeasonalityMonth>,
85}
86
87impl Seasonality {
88    /// The summaries of `months` over `years` of history.
89    pub fn new(years: u32, months: Vec<SeasonalityMonth>) -> Self {
90        Self { years, months }
91    }
92}
93
94/// The sections of the wide watchlist beyond its table, as the host answered them. The panel
95/// lists the rows of the symbols it shows; earnings and dividends are the events of
96/// [`CalendarKind::Earnings`](crate::data::CalendarKind::Earnings) and
97/// [`CalendarKind::Dividends`](crate::data::CalendarKind::Dividends) with a symbol, and news
98/// the stories that name one. By default every section is unavailable.
99#[derive(Clone, Debug, Default, PartialEq)]
100#[non_exhaustive]
101pub struct WatchlistDetails {
102    /// Upcoming and reported earnings.
103    pub earnings: MarketDetail<Vec<CalendarEvent>>,
104    /// Ex-dividend dates and amounts.
105    pub dividends: MarketDetail<Vec<CalendarEvent>>,
106    /// Stories about the symbols.
107    pub news: MarketDetail<Vec<NewsStory>>,
108}