added function aggregating multiple ticker data
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
// src/corporate/storage.rs
|
||||
use super::types::{CompanyEvent, CompanyPrice, CompanyEventChange};
|
||||
use super::helpers::*;
|
||||
use super::{types::*, helpers::*};
|
||||
use tokio::fs;
|
||||
use chrono::{Datelike, NaiveDate};
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub async fn load_existing_events() -> anyhow::Result<HashMap<String, CompanyEvent>> {
|
||||
let mut map = HashMap::new();
|
||||
@@ -87,13 +87,120 @@ pub async fn save_changes(changes: &[CompanyEventChange]) -> anyhow::Result<()>
|
||||
}
|
||||
|
||||
pub async fn save_prices_for_ticker(ticker: &str, timeframe: &str, mut prices: Vec<CompanyPrice>) -> anyhow::Result<()> {
|
||||
let dir = std::path::Path::new("corporate_prices");
|
||||
fs::create_dir_all(dir).await?;
|
||||
let path = dir.join(format!("{}_{}.json", ticker.replace(".", "_"), timeframe));
|
||||
let base_dir = Path::new("corporate_prices");
|
||||
let company_dir = base_dir.join(ticker.replace(".", "_"));
|
||||
let timeframe_dir = company_dir.join(timeframe);
|
||||
|
||||
prices.sort_by_key(|p| p.date.clone());
|
||||
// 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()));
|
||||
|
||||
let json = serde_json::to_string_pretty(&prices)?;
|
||||
fs::write(&path, json).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn load_companies() -> Result<Vec<CompanyMetadata>, anyhow::Error> {
|
||||
let path = Path::new("src/data/companies.json");
|
||||
if !path.exists() {
|
||||
println!("Missing companies.json file at src/data/companies.json");
|
||||
return Ok(vec![]);
|
||||
}
|
||||
let content = fs::read_to_string(path).await?;
|
||||
let companies: Vec<CompanyMetadata> = serde_json::from_str(&content)?;
|
||||
Ok(companies)
|
||||
}
|
||||
|
||||
pub fn get_company_dir(isin: &str) -> PathBuf {
|
||||
PathBuf::from("corporate_prices").join(isin)
|
||||
}
|
||||
|
||||
pub async fn ensure_company_dirs(isin: &str) -> anyhow::Result<()> {
|
||||
let base = get_company_dir(isin);
|
||||
let paths = [
|
||||
base.clone(),
|
||||
base.join("5min"),
|
||||
base.join("daily"),
|
||||
base.join("aggregated").join("5min"),
|
||||
base.join("aggregated").join("daily"),
|
||||
];
|
||||
for p in paths {
|
||||
fs::create_dir_all(&p).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn save_company_metadata(company: &CompanyMetadata) -> anyhow::Result<()> {
|
||||
let dir = get_company_dir(&company.isin);
|
||||
fs::create_dir_all(&dir).await?;
|
||||
let path = dir.join("metadata.json");
|
||||
fs::write(path, serde_json::to_string_pretty(company)?).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn save_available_exchanges(isin: &str, exchanges: Vec<AvailableExchange>) -> anyhow::Result<()> {
|
||||
let dir = get_company_dir(isin);
|
||||
fs::create_dir_all(&dir).await?;
|
||||
let path = dir.join("available_exchanges.json");
|
||||
fs::write(&path, serde_json::to_string_pretty(&exchanges)?).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn load_available_exchanges(isin: &str) -> anyhow::Result<Vec<AvailableExchange>> {
|
||||
let path = get_company_dir(isin).join("available_exchanges.json");
|
||||
if path.exists() {
|
||||
let content = fs::read_to_string(&path).await?;
|
||||
Ok(serde_json::from_str(&content)?)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn save_prices_by_source(
|
||||
isin: &str,
|
||||
source_ticker: &str,
|
||||
timeframe: &str,
|
||||
prices: Vec<CompanyPrice>,
|
||||
) -> anyhow::Result<()> {
|
||||
let source_safe = source_ticker.replace(".", "_").replace("/", "_");
|
||||
let dir = get_company_dir(isin).join(timeframe).join(&source_safe);
|
||||
fs::create_dir_all(&dir).await?;
|
||||
let path = dir.join("prices.json");
|
||||
|
||||
let mut prices = prices;
|
||||
prices.sort_by_key(|p| (p.date.clone(), p.time.clone()));
|
||||
|
||||
fs::write(&path, serde_json::to_string_pretty(&prices)?).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_available_exchange(
|
||||
isin: &str,
|
||||
ticker: &str,
|
||||
exchange_mic: &str,
|
||||
has_daily: bool,
|
||||
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);
|
||||
} else {
|
||||
exchanges.push(AvailableExchange {
|
||||
exchange_mic: exchange_mic.to_string(),
|
||||
ticker: ticker.to_string(),
|
||||
has_daily,
|
||||
has_5min,
|
||||
last_successful_fetch: Some(today),
|
||||
});
|
||||
}
|
||||
|
||||
save_available_exchanges(isin, exchanges).await
|
||||
}
|
||||
Reference in New Issue
Block a user