storing data for multiple exchanges for a single isin

This commit is contained in:
2025-11-24 18:33:13 +01:00
parent 9cfcae84ea
commit bbc19f2110
6 changed files with 473 additions and 106 deletions

View File

@@ -17,7 +17,7 @@ pub async fn load_existing_events() -> anyhow::Result<HashMap<String, CompanyEve
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("json") {
let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
if name.starts_with("events_") && name.len() == 17 { // events_yyyy-mm.json
if name.starts_with("events_") && name.len() == 17 {
let content = fs::read_to_string(&path).await?;
let events: Vec<CompanyEvent> = serde_json::from_str(&content)?;
for event in events {
@@ -33,7 +33,6 @@ pub async fn save_optimized_events(events: HashMap<String, CompanyEvent>) -> any
let dir = std::path::Path::new("corporate_events");
fs::create_dir_all(dir).await?;
// Delete old files
let mut entries = fs::read_dir(dir).await?;
while let Some(entry) = entries.next_entry().await? {
let path = entry.path();
@@ -91,10 +90,7 @@ pub async fn save_prices_for_ticker(ticker: &str, timeframe: &str, mut prices: V
let company_dir = base_dir.join(ticker.replace(".", "_"));
let timeframe_dir = company_dir.join(timeframe);
// Ensure directories exist
fs::create_dir_all(&timeframe_dir).await?;
// File name includes timeframe (e.g., prices.json)
let path = timeframe_dir.join("prices.json");
prices.sort_by_key(|p| (p.date.clone(), p.time.clone()));
@@ -178,6 +174,7 @@ pub async fn save_prices_by_source(
Ok(())
}
/// Update available_exchanges.json with fetch results
pub async fn update_available_exchange(
isin: &str,
ticker: &str,
@@ -186,21 +183,64 @@ pub async fn update_available_exchange(
has_5min: bool,
) -> anyhow::Result<()> {
let mut exchanges = load_available_exchanges(isin).await?;
let today = chrono::Local::now().format("%Y-%m-%d").to_string();
if let Some(entry) = exchanges.iter_mut().find(|e| e.ticker == ticker) {
entry.has_daily |= has_daily;
entry.has_5min |= has_5min;
entry.last_successful_fetch = Some(today);
// Update existing entry
entry.record_success(has_daily, has_5min);
} else {
exchanges.push(AvailableExchange {
exchange_mic: exchange_mic.to_string(),
ticker: ticker.to_string(),
has_daily,
has_5min,
last_successful_fetch: Some(today),
});
// Create new entry - need to get currency from somewhere
// Try to infer from the ticker or use a default
let currency = infer_currency_from_ticker(ticker);
let mut new_entry = AvailableExchange::new(
ticker.to_string(),
exchange_mic.to_string(),
currency,
);
new_entry.record_success(has_daily, has_5min);
exchanges.push(new_entry);
}
save_available_exchanges(isin, exchanges).await
}
/// Add a newly discovered exchange before fetching
pub async fn add_discovered_exchange(
isin: &str,
ticker_info: &TickerInfo,
) -> anyhow::Result<()> {
let mut exchanges = load_available_exchanges(isin).await?;
// Only add if not already present
if !exchanges.iter().any(|e| e.ticker == ticker_info.ticker) {
let new_entry = AvailableExchange::new(
ticker_info.ticker.clone(),
ticker_info.exchange_mic.clone(),
ticker_info.currency.clone(),
);
exchanges.push(new_entry);
save_available_exchanges(isin, exchanges).await?;
}
Ok(())
}
/// Infer currency from ticker suffix
fn infer_currency_from_ticker(ticker: &str) -> String {
if ticker.ends_with(".L") { return "GBP".to_string(); }
if ticker.ends_with(".PA") { return "EUR".to_string(); }
if ticker.ends_with(".DE") { return "EUR".to_string(); }
if ticker.ends_with(".AS") { return "EUR".to_string(); }
if ticker.ends_with(".MI") { return "EUR".to_string(); }
if ticker.ends_with(".SW") { return "CHF".to_string(); }
if ticker.ends_with(".T") { return "JPY".to_string(); }
if ticker.ends_with(".HK") { return "HKD".to_string(); }
if ticker.ends_with(".SS") { return "CNY".to_string(); }
if ticker.ends_with(".SZ") { return "CNY".to_string(); }
if ticker.ends_with(".TO") { return "CAD".to_string(); }
if ticker.ends_with(".AX") { return "AUD".to_string(); }
if ticker.ends_with(".SA") { return "BRL".to_string(); }
if ticker.ends_with(".MC") { return "EUR".to_string(); }
if ticker.ends_with(".BO") || ticker.ends_with(".NS") { return "INR".to_string(); }
"USD".to_string() // Default
}