pub struct DukascopyUrls {
pub datafeed_base: &'static str,
}
impl Default for DukascopyUrls {
fn default() -> Self {
Self {
datafeed_base: "https://datafeed.dukascopy.com/datafeed",
}
}
}
#[derive(Debug, Clone)]
pub enum DukascopyEndpoint {
HistoricalTicks,
}
impl DukascopyEndpoint {
pub fn path_pattern(&self) -> &'static str {
match self {
Self::HistoricalTicks => "/{symbol}/{year}/{month}/{day}/{hour}h_ticks.bi5",
}
}
}
pub fn format_symbol(symbol: &crate::core::types::Symbol) -> String {
format!("{}{}", symbol.base, symbol.quote).to_uppercase()
}
pub fn parse_symbol(api_symbol: &str) -> crate::core::types::Symbol {
if api_symbol.len() == 6 {
crate::core::types::Symbol {
base: api_symbol[0..3].to_string(),
quote: api_symbol[3..6].to_string(),
raw: Some(api_symbol.to_string()),
}
} else if api_symbol.len() == 7 && api_symbol.starts_with("XAU") {
crate::core::types::Symbol {
base: api_symbol[0..3].to_string(),
quote: api_symbol[3..].to_string(),
raw: Some(api_symbol.to_string()),
}
} else {
let base_len = std::cmp::min(3, api_symbol.len() / 2);
crate::core::types::Symbol {
base: api_symbol[0..base_len].to_string(),
quote: api_symbol[base_len..].to_string(),
raw: Some(api_symbol.to_string()),
}
}
}
pub fn build_tick_data_url(
symbol: &str,
year: u32,
month: u32,
day: u32,
hour: u32,
) -> String {
let urls = DukascopyUrls::default();
format!(
"{}/{}/{:04}/{:02}/{:02}/{:02}h_ticks.bi5",
urls.datafeed_base,
symbol.to_uppercase(),
year,
month,
day,
hour
)
}
pub fn get_point_value(symbol: &str) -> f64 {
if symbol.contains("JPY") {
0.001 } else {
0.00001 }
}