finance_query/models/search/
quote.rs

1//! Search Quote Model
2//!
3//! Represents individual stock/symbol search results
4
5use serde::{Deserialize, Serialize};
6use std::ops::Deref;
7
8/// A collection of search quotes with DataFrame support.
9///
10/// This wrapper allows `search_results.quotes.to_dataframe()` syntax while still
11/// acting like a `Vec<SearchQuote>` for iteration, indexing, etc.
12#[derive(Debug, Clone, Default, Serialize, Deserialize)]
13#[serde(transparent)]
14pub struct SearchQuotes(pub Vec<SearchQuote>);
15
16impl Deref for SearchQuotes {
17    type Target = Vec<SearchQuote>;
18
19    fn deref(&self) -> &Self::Target {
20        &self.0
21    }
22}
23
24impl IntoIterator for SearchQuotes {
25    type Item = SearchQuote;
26    type IntoIter = std::vec::IntoIter<SearchQuote>;
27
28    fn into_iter(self) -> Self::IntoIter {
29        self.0.into_iter()
30    }
31}
32
33impl<'a> IntoIterator for &'a SearchQuotes {
34    type Item = &'a SearchQuote;
35    type IntoIter = std::slice::Iter<'a, SearchQuote>;
36
37    fn into_iter(self) -> Self::IntoIter {
38        self.0.iter()
39    }
40}
41
42#[cfg(feature = "dataframe")]
43impl SearchQuotes {
44    /// Converts the quotes to a polars DataFrame.
45    pub fn to_dataframe(&self) -> ::polars::prelude::PolarsResult<::polars::prelude::DataFrame> {
46        SearchQuote::vec_to_dataframe(&self.0)
47    }
48}
49
50/// A quote result from symbol search
51#[derive(Debug, Clone, Serialize, Deserialize)]
52#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
53#[non_exhaustive]
54#[serde(rename_all = "camelCase")]
55pub struct SearchQuote {
56    /// Stock symbol
57    pub symbol: String,
58    /// Short name
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub short_name: Option<String>,
61    /// Long name
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub long_name: Option<String>,
64    /// Quote type (EQUITY, ETF, OPTION, etc.)
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub quote_type: Option<String>,
67    /// Exchange code
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub exchange: Option<String>,
70    /// Exchange display name
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub exch_disp: Option<String>,
73    /// Type display name
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub type_disp: Option<String>,
76    /// Industry classification
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub industry: Option<String>,
79    /// Industry display name
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub industry_disp: Option<String>,
82    /// Sector classification
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub sector: Option<String>,
85    /// Sector display name
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub sector_disp: Option<String>,
88    /// Whether this is a Yahoo Finance listed symbol
89    #[serde(rename = "isYahooFinance")]
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub is_yahoo_finance: Option<bool>,
92    /// Display security industry flag
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub disp_sec_ind_flag: Option<bool>,
95    /// Company logo URL (requires enableLogoUrl=true in search request)
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub logo_url: Option<String>,
98    /// Search relevance score
99    #[serde(skip_serializing_if = "Option::is_none")]
100    pub score: Option<f64>,
101    /// Index identifier
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub index: Option<String>,
104    /// Previous company name (for recent name changes)
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub prev_name: Option<String>,
107    /// Date of name change
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub name_change_date: Option<String>,
110}