use std::collections::HashMap;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use crate::{
quotes::{
quote::{Quote, QuoteDetails, QuoteLevels},
quoteselector::QuoteSelector,
},
time::date::Date,
utils::errors::QSError,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuoteRecord {
pub identifier: String,
#[serde(default)]
pub mid: Option<f64>,
#[serde(default)]
pub bid: Option<f64>,
#[serde(default)]
pub ask: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuoteStoreRecords {
pub reference_date: Date,
pub quotes: Vec<QuoteRecord>,
}
impl TryFrom<QuoteStoreRecords> for QuoteStore {
type Error = QSError;
fn try_from(records: QuoteStoreRecords) -> Result<Self, Self::Error> {
let mut store = Self::new(records.reference_date);
for rec in records.quotes {
let details = QuoteDetails::from_str(&rec.identifier)?;
let levels = QuoteLevels::new(rec.mid, rec.bid, rec.ask);
store.add_quote(Quote::new(details, levels));
}
Ok(store)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct QuoteStore {
reference_date: Date,
quotes: HashMap<String, Quote>,
}
impl QuoteStore {
#[must_use]
pub fn new(reference_date: Date) -> Self {
Self {
reference_date,
quotes: HashMap::new(),
}
}
#[must_use]
pub const fn reference_date(&self) -> Date {
self.reference_date
}
pub fn add_quote(&mut self, quote: Quote) {
let id = quote.details().identifier();
self.quotes.insert(id, quote);
}
#[must_use]
pub fn quote(&self, identifier: &str) -> Option<&Quote> {
self.quotes.get(identifier)
}
#[must_use]
pub const fn quotes(&self) -> &HashMap<String, Quote> {
&self.quotes
}
}
impl QuoteSelector for QuoteStore {
fn select(&self, identifier: &str) -> Option<Quote> {
self.quotes.get(identifier).cloned()
}
fn reference_date(&self) -> Date {
self.reference_date
}
}