Skip to main content

finance_query/models/fundamentals/
etf.rs

1//! ETF profile and holdings models.
2//!
3//! Served through the [`Capability::FUNDAMENTALS`](crate::Capability::FUNDAMENTALS)
4//! route. Alpha Vantage, FMP, and Yahoo all implement it; coverage is ragged
5//! (Alpha Vantage serves fuller profile-level fields, FMP additionally serves
6//! sector/country breakdowns, Yahoo serves fee/holdings/sector data but no
7//! country breakdown or inception date) so gaps default rather than
8//! widening per-provider.
9
10use serde::{Deserialize, Serialize};
11
12/// Profile and composition of an exchange-traded fund.
13#[derive(Debug, Clone, Default, Serialize, Deserialize)]
14#[non_exhaustive]
15pub struct EtfProfile {
16    /// Fund ticker symbol.
17    pub symbol: Option<String>,
18    /// Fund name.
19    pub name: Option<String>,
20    /// Asset type as reported by the provider.
21    pub asset_type: Option<String>,
22    /// Total net assets.
23    pub net_assets: Option<f64>,
24    /// Net expense ratio, as a fraction (0.0003 = 3 bps).
25    pub net_expense_ratio: Option<f64>,
26    /// Annual portfolio turnover, as a fraction.
27    pub portfolio_turnover: Option<f64>,
28    /// Trailing dividend yield, as a fraction.
29    pub dividend_yield: Option<f64>,
30    /// Inception date (`YYYY-MM-DD`).
31    pub inception_date: Option<String>,
32    /// Portfolio holdings, heaviest first.
33    pub holdings: Vec<EtfHolding>,
34    /// Portfolio weight by sector.
35    pub sector_weightings: Vec<EtfSectorWeighting>,
36    /// Portfolio weight by country.
37    pub country_weightings: Vec<EtfCountryWeighting>,
38}
39
40/// One position inside an ETF's portfolio.
41#[derive(Debug, Clone, Default, Serialize, Deserialize)]
42#[non_exhaustive]
43pub struct EtfHolding {
44    /// Ticker symbol of the held security.
45    pub symbol: Option<String>,
46    /// Security description.
47    pub description: Option<String>,
48    /// Portfolio weight, as a fraction of net assets.
49    pub weight: Option<f64>,
50}
51
52/// One sector's weight inside an ETF's portfolio.
53#[derive(Debug, Clone, Default, Serialize, Deserialize)]
54#[non_exhaustive]
55pub struct EtfSectorWeighting {
56    /// Sector name.
57    pub sector: Option<String>,
58    /// Portfolio weight, as a fraction of net assets.
59    pub weight: Option<f64>,
60}
61
62/// One country's weight inside an ETF's portfolio.
63#[derive(Debug, Clone, Default, Serialize, Deserialize)]
64#[non_exhaustive]
65pub struct EtfCountryWeighting {
66    /// Country name.
67    pub country: Option<String>,
68    /// Portfolio weight, as a fraction of net assets.
69    pub weight: Option<f64>,
70}