shape_runtime/data/
provider.rs1use super::{DataFrame, DataQuery, Timeframe};
7use std::sync::Arc;
8use thiserror::Error;
9
10#[derive(Debug, Error)]
12pub enum DataError {
13 #[error("Symbol not found: {0}")]
14 SymbolNotFound(String),
15
16 #[error("No data available for timeframe: {0}")]
17 TimeframeNotAvailable(String),
18
19 #[error("No data in requested range")]
20 NoDataInRange,
21
22 #[error("IO error: {0}")]
23 Io(#[from] std::io::Error),
24
25 #[error("Provider error: {0}")]
26 Provider(String),
27
28 #[error("Configuration error: {0}")]
29 Config(String),
30}
31
32pub trait DataProvider: Send + Sync {
38 fn load(&self, query: &DataQuery) -> Result<DataFrame, DataError>;
43
44 fn has_data(&self, symbol: &str, timeframe: &Timeframe) -> bool;
46
47 fn symbols(&self) -> Vec<String>;
49
50 fn timeframes(&self, symbol: &str) -> Vec<Timeframe> {
52 let _ = symbol;
54 Vec::new()
55 }
56}
57
58#[derive(Debug, Clone, Default)]
62pub struct NullProvider;
63
64impl DataProvider for NullProvider {
65 fn load(&self, query: &DataQuery) -> Result<DataFrame, DataError> {
66 Err(DataError::SymbolNotFound(query.id.clone()))
67 }
68
69 fn has_data(&self, _symbol: &str, _timeframe: &Timeframe) -> bool {
70 false
71 }
72
73 fn symbols(&self) -> Vec<String> {
74 Vec::new()
75 }
76}
77
78pub type SharedDataProvider = Arc<dyn DataProvider>;
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_null_provider() {
87 let provider = NullProvider;
88 let query = DataQuery::new("TEST", Timeframe::d1());
89
90 assert!(!provider.has_data("TEST", &Timeframe::d1()));
91 assert!(provider.symbols().is_empty());
92 assert!(provider.load(&query).is_err());
93 }
94}