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}