Skip to main content

finance_query/adapters/polygon/
etf.rs

1//! ETF Global partner data: analytics, constituents, fund flows, profiles, taxonomies.
2
3use serde::{Deserialize, Serialize};
4
5use crate::adapters::common::encode_path_segment;
6use crate::error::Result;
7
8use super::build_client;
9use super::models::PaginatedResponse;
10
11/// ETF analytics data.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[non_exhaustive]
14pub struct EtfAnalytics {
15    /// Ticker.
16    pub ticker: Option<String>,
17    /// Name.
18    pub name: Option<String>,
19    /// Performance data.
20    #[serde(flatten)]
21    pub data: std::collections::HashMap<String, serde_json::Value>,
22}
23
24/// ETF constituent/holding.
25#[derive(Debug, Clone, Serialize, Deserialize)]
26#[non_exhaustive]
27pub struct EtfConstituent {
28    /// Holding ticker.
29    pub ticker: Option<String>,
30    /// Holding name.
31    pub name: Option<String>,
32    /// Weight in portfolio.
33    pub weight: Option<f64>,
34    /// Market value.
35    pub market_value: Option<f64>,
36    /// Share count.
37    pub shares: Option<f64>,
38}
39
40/// ETF fund flow.
41#[derive(Debug, Clone, Serialize, Deserialize)]
42#[non_exhaustive]
43pub struct EtfFundFlow {
44    /// Ticker.
45    pub ticker: Option<String>,
46    /// Date.
47    pub date: Option<String>,
48    /// Flow amount.
49    pub flow: Option<f64>,
50}
51
52/// ETF profile.
53#[derive(Debug, Clone, Serialize, Deserialize)]
54#[non_exhaustive]
55pub struct EtfProfileData {
56    /// Ticker.
57    pub ticker: Option<String>,
58    /// Name.
59    pub name: Option<String>,
60    /// Issuer.
61    pub issuer: Option<String>,
62    /// Expense ratio.
63    pub expense_ratio: Option<f64>,
64    /// Inception date.
65    pub inception_date: Option<String>,
66    /// Asset class.
67    pub asset_class: Option<String>,
68    /// Sector.
69    pub sector: Option<String>,
70    /// Region.
71    pub region: Option<String>,
72}
73
74/// ETF taxonomy.
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[non_exhaustive]
77pub struct EtfTaxonomy {
78    /// Category.
79    pub category: Option<String>,
80    /// Subcategory.
81    pub subcategory: Option<String>,
82    /// Description.
83    pub description: Option<String>,
84}
85
86/// Fetch ETF analytics.
87pub async fn etf_analytics(params: &[(&str, &str)]) -> Result<PaginatedResponse<EtfAnalytics>> {
88    let client = build_client()?;
89    client.get("/v3/reference/etfs/analytics", params).await
90}
91
92/// Fetch ETF constituents/holdings.
93pub async fn etf_constituents(
94    ticker: &str,
95    params: &[(&str, &str)],
96) -> Result<PaginatedResponse<EtfConstituent>> {
97    let client = build_client()?;
98    let path = format!(
99        "/v3/reference/etfs/{}/constituents",
100        encode_path_segment(ticker)
101    );
102    client.get(&path, params).await
103}
104
105/// Fetch ETF fund flows.
106pub async fn etf_fund_flows(params: &[(&str, &str)]) -> Result<PaginatedResponse<EtfFundFlow>> {
107    let client = build_client()?;
108    client.get("/v3/reference/etfs/fund-flows", params).await
109}
110
111/// Fetch ETF profiles/exposure.
112pub async fn etf_profiles(params: &[(&str, &str)]) -> Result<PaginatedResponse<EtfProfileData>> {
113    let client = build_client()?;
114    client.get("/v3/reference/etfs/profiles", params).await
115}
116
117/// Fetch ETF taxonomies.
118pub async fn etf_taxonomies(params: &[(&str, &str)]) -> Result<PaginatedResponse<EtfTaxonomy>> {
119    let client = build_client()?;
120    client.get("/v3/reference/etfs/taxonomies", params).await
121}