Skip to main content

finance_query/models/screeners/
quote.rs

1use crate::models::quote::FormattedValue;
2use serde::{Deserialize, Serialize};
3
4/// Quote data from a Yahoo Finance screener
5///
6/// This struct contains the fields returned by Yahoo Finance's predefined
7/// screener endpoint. It includes comprehensive quote data for filtering
8/// and displaying screened stocks/funds.
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
11#[serde(rename_all = "camelCase")]
12pub struct ScreenerQuote {
13    // Core identification
14    /// Stock symbol (e.g., "NVDA")
15    pub symbol: String,
16    /// Short display name (e.g., "NVIDIA Corporation")
17    #[serde(default, alias = "companyshortname")]
18    pub short_name: String,
19    /// Full company name
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub long_name: Option<String>,
22    /// Display name for UI purposes
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub display_name: Option<String>,
25    /// Type of quote (e.g., "EQUITY", "ETF", "CRYPTOCURRENCY")
26    pub quote_type: String,
27    /// Exchange code (e.g., "NMS" for NASDAQ)
28    pub exchange: String,
29
30    // Price information
31    /// Current regular market price
32    pub regular_market_price: FormattedValue<f64>,
33    /// Change in price from previous close
34    pub regular_market_change: FormattedValue<f64>,
35    /// Percent change from previous close
36    pub regular_market_change_percent: FormattedValue<f64>,
37    /// Regular market open price
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub regular_market_open: Option<FormattedValue<f64>>,
40    /// Day's high price
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub regular_market_day_high: Option<FormattedValue<f64>>,
43    /// Day's low price
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub regular_market_day_low: Option<FormattedValue<f64>>,
46    /// Previous close price
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub regular_market_previous_close: Option<FormattedValue<f64>>,
49    /// Regular market timestamp
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub regular_market_time: Option<FormattedValue<i64>>,
52
53    // Volume & Market Cap
54    /// Regular market volume (may be None for funds)
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub regular_market_volume: Option<FormattedValue<i64>>,
57    /// Average daily volume over 3 months
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub average_daily_volume3_month: Option<FormattedValue<i64>>,
60    /// Average daily volume over 10 days
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub average_daily_volume10_day: Option<FormattedValue<i64>>,
63    /// Market capitalization
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub market_cap: Option<FormattedValue<i64>>,
66    /// Outstanding shares
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub shares_outstanding: Option<FormattedValue<i64>>,
69
70    // 52-Week Range
71    /// 52-week high price
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub fifty_two_week_high: Option<FormattedValue<f64>>,
74    /// 52-week low price
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub fifty_two_week_low: Option<FormattedValue<f64>>,
77    /// Change from 52-week low
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub fifty_two_week_change: Option<FormattedValue<f64>>,
80    /// Percent change from 52-week low
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub fifty_two_week_change_percent: Option<FormattedValue<f64>>,
83
84    // Moving Averages
85    /// 50-day moving average
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub fifty_day_average: Option<FormattedValue<f64>>,
88    /// Change from 50-day average
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub fifty_day_average_change: Option<FormattedValue<f64>>,
91    /// Percent change from 50-day average
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub fifty_day_average_change_percent: Option<FormattedValue<f64>>,
94    /// 200-day moving average
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub two_hundred_day_average: Option<FormattedValue<f64>>,
97    /// Change from 200-day average
98    #[serde(skip_serializing_if = "Option::is_none")]
99    pub two_hundred_day_average_change: Option<FormattedValue<f64>>,
100    /// Percent change from 200-day average
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub two_hundred_day_average_change_percent: Option<FormattedValue<f64>>,
103
104    // Valuation Metrics
105    /// Average analyst rating (e.g., "1.3 - Strong Buy")
106    #[serde(skip_serializing_if = "Option::is_none")]
107    pub average_analyst_rating: Option<String>,
108    /// Trailing 12-month P/E ratio
109    #[serde(rename = "trailingPE", skip_serializing_if = "Option::is_none")]
110    pub trailing_pe: Option<FormattedValue<f64>>,
111    /// Forward P/E ratio
112    #[serde(rename = "forwardPE", skip_serializing_if = "Option::is_none")]
113    pub forward_pe: Option<FormattedValue<f64>>,
114    /// Price to book ratio
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub price_to_book: Option<FormattedValue<f64>>,
117    /// Book value per share
118    #[serde(skip_serializing_if = "Option::is_none")]
119    pub book_value: Option<FormattedValue<f64>>,
120
121    // Earnings Per Share
122    /// Trailing 12-month EPS
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub eps_trailing_twelve_months: Option<FormattedValue<f64>>,
125    /// Forward EPS
126    #[serde(skip_serializing_if = "Option::is_none")]
127    pub eps_forward: Option<FormattedValue<f64>>,
128    /// Current year EPS
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub eps_current_year: Option<FormattedValue<f64>>,
131    /// Price to current year EPS
132    #[serde(skip_serializing_if = "Option::is_none")]
133    pub price_eps_current_year: Option<FormattedValue<f64>>,
134
135    // Dividend Information
136    /// Dividend yield
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub dividend_yield: Option<FormattedValue<f64>>,
139    /// Dividend rate
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub dividend_rate: Option<FormattedValue<f64>>,
142    /// Ex-dividend date timestamp
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub dividend_date: Option<FormattedValue<i64>>,
145    /// Trailing annual dividend rate
146    #[serde(skip_serializing_if = "Option::is_none")]
147    pub trailing_annual_dividend_rate: Option<FormattedValue<f64>>,
148    /// Trailing annual dividend yield
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub trailing_annual_dividend_yield: Option<FormattedValue<f64>>,
151
152    // Bid/Ask
153    /// Current bid price
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub bid: Option<FormattedValue<f64>>,
156    /// Bid size
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub bid_size: Option<FormattedValue<i64>>,
159    /// Current ask price
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub ask: Option<FormattedValue<f64>>,
162    /// Ask size
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub ask_size: Option<FormattedValue<i64>>,
165
166    // Post/Pre Market (Optional)
167    /// Post-market price
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub post_market_price: Option<FormattedValue<f64>>,
170    /// Post-market price change
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub post_market_change: Option<FormattedValue<f64>>,
173    /// Post-market percent change
174    #[serde(skip_serializing_if = "Option::is_none")]
175    pub post_market_change_percent: Option<FormattedValue<f64>>,
176    /// Post-market timestamp
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub post_market_time: Option<FormattedValue<i64>>,
179    /// Pre-market price
180    #[serde(skip_serializing_if = "Option::is_none")]
181    pub pre_market_price: Option<FormattedValue<f64>>,
182    /// Pre-market price change
183    #[serde(skip_serializing_if = "Option::is_none")]
184    pub pre_market_change: Option<FormattedValue<f64>>,
185    /// Pre-market percent change
186    #[serde(skip_serializing_if = "Option::is_none")]
187    pub pre_market_change_percent: Option<FormattedValue<f64>>,
188    /// Pre-market timestamp
189    #[serde(skip_serializing_if = "Option::is_none")]
190    pub pre_market_time: Option<FormattedValue<i64>>,
191
192    // Earnings Dates
193    /// Earnings timestamp
194    #[serde(skip_serializing_if = "Option::is_none")]
195    pub earnings_timestamp: Option<FormattedValue<i64>>,
196    /// Earnings timestamp start
197    #[serde(skip_serializing_if = "Option::is_none")]
198    pub earnings_timestamp_start: Option<FormattedValue<i64>>,
199    /// Earnings timestamp end
200    #[serde(skip_serializing_if = "Option::is_none")]
201    pub earnings_timestamp_end: Option<FormattedValue<i64>>,
202
203    // Additional Fields
204    /// Currency code (e.g., "USD")
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub currency: Option<String>,
207}