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}