use super::urls::api;
use crate::client::YahooClient;
use crate::constants::{Interval, TimeRange};
use crate::error::Result;
use tracing::info;
pub async fn fetch(
client: &YahooClient,
symbols: &[&str],
interval: Interval,
range: TimeRange,
) -> Result<serde_json::Value> {
if symbols.is_empty() {
return Err(crate::error::FinanceError::InvalidParameter {
param: "symbols".to_string(),
reason: "At least one symbol is required".to_string(),
});
}
for symbol in symbols {
super::common::validate_symbol(symbol)?;
}
let symbols_joined = symbols.join(",");
info!(
"Fetching spark for {} symbols ({}, {})",
symbols.len(),
interval.as_str(),
range.as_str()
);
let url = api::SPARK;
let params = [
("symbols", symbols_joined.as_str()),
("interval", interval.as_str()),
("range", range.as_str()),
("indicators", "close"),
("includeTimestamps", "true"),
("includePrePost", "false"),
];
let response = client.request_with_params(url, ¶ms).await?;
Ok(response.json().await?)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::client::ClientConfig;
#[tokio::test]
#[ignore = "requires network access"]
async fn test_fetch_spark() {
let client = YahooClient::new(ClientConfig::default()).await.unwrap();
let result = fetch(
&client,
&["AAPL", "MSFT"],
Interval::FiveMinutes,
TimeRange::OneDay,
)
.await;
assert!(result.is_ok());
let json = result.unwrap();
assert!(json.get("spark").is_some());
}
#[tokio::test]
async fn test_empty_symbols() {
let client = YahooClient::new(ClientConfig::default()).await.unwrap();
let result = fetch(&client, &[], Interval::FiveMinutes, TimeRange::OneDay).await;
assert!(result.is_err());
}
}