Fundamental_Analysis/services/yfinance-provider-service/src/yfinance.rs
Lv, Qi 5327e76aaa chore: 提交本轮 Rust 架构迁移相关改动
- docker-compose: 下线 Python backend/config-service,切换至 config-service-rs
- archive: 归档 legacy Python 目录至 archive/python/*
- services: 新增/更新 common-contracts、api-gateway、各 provider、report-generator-service、config-service-rs
- data-persistence-service: API/system 模块与模型/DTO 调整
- frontend: 更新 useApi 与 API 路由
- docs: 更新路线图并勾选光荣退役
- cleanup: 移除 data-distance-service 占位测试
2025-11-16 20:55:46 +08:00

64 lines
2.2 KiB
Rust

use crate::error::AppError;
use crate::mapping::{map_financial_statements, map_profile};
use common_contracts::dtos::{CompanyProfileDto, TimeSeriesFinancialDto};
use anyhow::anyhow;
#[derive(Clone)]
pub struct YFinanceDataProvider {
client: reqwest::Client,
}
impl YFinanceDataProvider {
pub fn new() -> Self {
Self {
client: reqwest::Client::new(),
}
}
pub async fn fetch_all_data(
&self,
symbol: &str,
) -> Result<(CompanyProfileDto, Vec<TimeSeriesFinancialDto>), AppError> {
let (summary_raw, financials_raw) = self.fetch_raw_data(symbol).await?;
let profile = map_profile(&summary_raw, symbol)?;
let financials = map_financial_statements(&financials_raw, symbol)?;
Ok((profile, financials))
}
async fn fetch_raw_data(
&self,
symbol: &str,
) -> Result<(serde_json::Value, serde_json::Value), AppError> {
// Yahoo quoteSummary: assetProfile + quoteType
let summary_url = format!(
"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{}?modules=assetProfile,quoteType",
symbol
);
// Yahoo financials: income/balance/cashflow histories
let financials_url = format!(
"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{}?modules=incomeStatementHistory,balanceSheetHistory,cashflowStatementHistory",
symbol
);
let summary_task = self.client.get(&summary_url).send();
let financials_task = self.client.get(&financials_url).send();
let (summary_res, financials_res) = tokio::try_join!(summary_task, financials_task)
.map_err(|e| AppError::ServiceRequest(e))?;
let summary_res = summary_res.error_for_status()?;
let financials_res = financials_res.error_for_status()?;
let summary_json: serde_json::Value = summary_res
.json()
.await
.map_err(|e| AppError::DataParsing(anyhow!(e)))?;
let financials_json: serde_json::Value = financials_res
.json()
.await
.map_err(|e| AppError::DataParsing(anyhow!(e)))?;
Ok((summary_json, financials_json))
}
}