Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- **Rust:** Six new `FundamentalContext` methods:
- `business_segments` — GET `/v1/quote/fundamentals/business-segments`: latest business segment breakdown (name, percent).
- `business_segments_history` — GET `/v1/quote/fundamentals/business-segments/history`: historical business and regional segment breakdowns with optional `report` and `cate` filters.
- `institution_rating_views` — GET `/v1/quote/ratings/institutional`: historical rating distribution time-series (buy/over/hold/under/sell/total per date).
- `industry_rank` — GET `/v1/quote/industry/rank`: industry leaderboard for a market with configurable indicator and sort direction.
- `industry_peers` — GET `/v1/quote/industries/peers`: recursive industry peer chain; accepts both symbol-style (`AAPL.US`) and raw counter IDs (`BK/US/123`).
- `financial_report_snapshot` — GET `/v1/quote/financials/earnings-snapshot`: earnings snapshot with forecast (revenue/EBIT/EPS) and reported (P&L, cash-flows, balance-sheet ratios) metrics.
- All new methods are also available on `FundamentalContextSync` (blocking API).

# [4.1.0]

## Breaking changes
Expand Down
69 changes: 69 additions & 0 deletions rust/src/blocking/fundamental.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,73 @@ impl FundamentalContextSync {
self.rt
.call(move |ctx| async move { ctx.ratings(symbol).await })
}

/// Get latest business segment breakdown
pub fn business_segments(
&self,
symbol: impl Into<String> + Send + 'static,
) -> Result<BusinessSegments> {
self.rt
.call(move |ctx| async move { ctx.business_segments(symbol).await })
}

/// Get historical business segment breakdowns
pub fn business_segments_history(
&self,
symbol: impl Into<String> + Send + 'static,
report: Option<&'static str>,
cate: Option<String>,
) -> Result<BusinessSegmentsHistory> {
self.rt.call(
move |ctx| async move { ctx.business_segments_history(symbol, report, cate).await },
)
}

/// Get historical institutional rating views
pub fn institution_rating_views(
&self,
symbol: impl Into<String> + Send + 'static,
) -> Result<InstitutionRatingViews> {
self.rt
.call(move |ctx| async move { ctx.institution_rating_views(symbol).await })
}

/// Get industry rank for a market
pub fn industry_rank(
&self,
market: impl Into<String> + Send + 'static,
indicator: impl Into<String> + Send + 'static,
sort_type: impl Into<String> + Send + 'static,
limit: u32,
) -> Result<IndustryRankResponse> {
self.rt.call(move |ctx| async move {
ctx.industry_rank(market, indicator, sort_type, limit).await
})
}

/// Get industry peer chain
pub fn industry_peers(
&self,
counter_id: impl Into<String> + Send + 'static,
market: impl Into<String> + Send + 'static,
industry_id: Option<String>,
) -> Result<IndustryPeersResponse> {
self.rt.call(
move |ctx| async move { ctx.industry_peers(counter_id, market, industry_id).await },
)
}

/// Get financial report snapshot (earnings snapshot)
pub fn financial_report_snapshot(
&self,
symbol: impl Into<String> + Send + 'static,
report: Option<&'static str>,
fiscal_year: Option<i32>,
fiscal_period: Option<&'static str>,
) -> Result<FinancialReportSnapshot> {
self.rt.call(move |ctx| async move {
ctx.financial_report_snapshot(symbol, report, fiscal_year, fiscal_period)
.await
})
}
}
178 changes: 178 additions & 0 deletions rust/src/fundamental/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,4 +496,182 @@ impl FundamentalContext {
)
.await
}

// ── business_segments ────────────────────────────────────────

/// Get the latest business segment breakdown for a security.
///
/// Path: `GET /v1/quote/fundamentals/business-segments`
pub async fn business_segments(&self, symbol: impl Into<String>) -> Result<BusinessSegments> {
#[derive(Serialize)]
struct Query {
counter_id: String,
}
self.get(
"/v1/quote/fundamentals/business-segments",
Query {
counter_id: symbol_to_counter_id(&symbol.into()),
},
)
.await
}

/// Get historical business segment breakdowns for a security.
///
/// Path: `GET /v1/quote/fundamentals/business-segments/history`
pub async fn business_segments_history(
&self,
symbol: impl Into<String>,
report: Option<&'static str>,
cate: Option<String>,
) -> Result<BusinessSegmentsHistory> {
#[derive(Serialize)]
struct Query {
counter_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
report: Option<&'static str>,
#[serde(skip_serializing_if = "Option::is_none")]
cate: Option<String>,
}
self.get(
"/v1/quote/fundamentals/business-segments/history",
Query {
counter_id: symbol_to_counter_id(&symbol.into()),
report,
cate,
},
)
.await
}

// ── institution_rating_views ──────────────────────────────────

/// Get historical institutional rating view time-series for a security.
///
/// Path: `GET /v1/quote/ratings/institutional`
pub async fn institution_rating_views(
&self,
symbol: impl Into<String>,
) -> Result<InstitutionRatingViews> {
#[derive(Serialize)]
struct Query {
counter_id: String,
}
self.get(
"/v1/quote/ratings/institutional",
Query {
counter_id: symbol_to_counter_id(&symbol.into()),
},
)
.await
}

// ── industry_rank ─────────────────────────────────────────────

/// Get industry rank for a market.
///
/// Path: `GET /v1/quote/industry/rank`
///
/// `indicator` is a numeric string `"0"`–`"7"`;
/// `sort_type` is `"0"` (ascending) or `"1"` (descending).
pub async fn industry_rank(
&self,
market: impl Into<String>,
indicator: impl Into<String>,
sort_type: impl Into<String>,
limit: u32,
) -> Result<IndustryRankResponse> {
#[derive(Serialize)]
struct Query {
market: String,
indicator: String,
sort_type: String,
limit: u32,
}
self.get(
"/v1/quote/industry/rank",
Query {
market: market.into(),
indicator: indicator.into(),
sort_type: sort_type.into(),
limit,
},
)
.await
}

// ── industry_peers ────────────────────────────────────────────

/// Get the industry peer chain for a security or industry.
///
/// Path: `GET /v1/quote/industries/peers`
///
/// `counter_id` may be a regular symbol (e.g. `"AAPL.US"`) or an industry
/// counter ID (e.g. `"BK/US/123"`) — pass it through as-is if it already
/// contains a `/`.
pub async fn industry_peers(
&self,
counter_id: impl Into<String>,
market: impl Into<String>,
industry_id: Option<String>,
) -> Result<IndustryPeersResponse> {
let raw = counter_id.into();
let cid = if raw.contains('/') {
raw
} else {
symbol_to_counter_id(&raw)
};
#[derive(Serialize)]
struct Query {
#[serde(rename = "type")]
kind: &'static str,
market: String,
industry_id: String,
counter_id: String,
}
self.get(
"/v1/quote/industries/peers",
Query {
kind: "1",
market: market.into(),
industry_id: industry_id.unwrap_or_default(),
counter_id: cid,
},
)
.await
}

// ── financial_report_snapshot ─────────────────────────────────

/// Get a financial report snapshot (earnings snapshot) for a security.
///
/// Path: `GET /v1/quote/financials/earnings-snapshot`
pub async fn financial_report_snapshot(
&self,
symbol: impl Into<String>,
report: Option<&'static str>,
fiscal_year: Option<i32>,
fiscal_period: Option<&'static str>,
) -> Result<FinancialReportSnapshot> {
#[derive(Serialize)]
struct Query {
counter_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
report: Option<&'static str>,
#[serde(skip_serializing_if = "Option::is_none")]
fiscal_year: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
fiscal_period: Option<&'static str>,
}
self.get(
"/v1/quote/financials/earnings-snapshot",
Query {
counter_id: symbol_to_counter_id(&symbol.into()),
report,
fiscal_year,
fiscal_period,
},
)
.await
}
}
Loading
Loading