use crate::symbology::{market::ExchangeMarketKind, Cpty, MarketKind, MarketRef};
use anyhow::{anyhow, bail, Result};
use api::{marketdata::NetidxFeedPaths, symbology::CptyId, ComponentId};
use fxhash::{FxHashMap, FxHashSet};
use netidx::path::Path;
#[derive(Debug, Clone)]
pub struct Paths {
pub hosted_base: Path,
pub local_base: Path,
pub core_base: Path,
pub local_components: FxHashSet<ComponentId>,
pub remote_components: FxHashMap<ComponentId, Path>,
pub component_kind: FxHashMap<ComponentId, String>,
pub use_local_symbology: bool,
pub use_local_licensedb: bool,
pub use_local_marketdata: FxHashSet<CptyId>,
pub use_legacy_marketdata: FxHashSet<CptyId>,
pub use_legacy_hist_marketdata: FxHashSet<CptyId>,
}
impl Paths {
pub fn sym(&self) -> Path {
let base =
if self.use_local_symbology { &self.local_base } else { &self.hosted_base };
base.append("sym")
}
pub fn marketdata(&self, cpty: Cpty, hist: bool) -> Path {
let use_local = self.use_local_marketdata.contains(&cpty.id());
let use_legacy = self.use_legacy_marketdata.contains(&cpty.id())
|| (hist && self.use_legacy_hist_marketdata.contains(&cpty.id()));
let base = if use_local { &self.local_base } else { &self.hosted_base };
if use_legacy {
base.append("qf")
} else {
base.append("marketdata")
}
}
pub fn marketdata_rt(&self, cpty: Cpty) -> Path {
self.marketdata(cpty, false)
.append("rt")
.append(&cpty.venue.name)
.append(&cpty.route.name)
}
pub fn marketdata_rt_by_id(&self, market: MarketRef) -> Path {
let cpty = market.cpty();
if self.use_legacy_marketdata.contains(&cpty.id()) {
self.marketdata(cpty, false)
.append("rt")
.append("by-id")
.append(&market.id.to_string())
} else {
market.path_by_id(&self.marketdata_rt(cpty))
}
}
pub fn marketdata_rt_by_name(&self, market: MarketRef) -> Path {
let cpty = market.cpty();
if self.use_legacy_marketdata.contains(&cpty.id()) {
match market.kind {
MarketKind::Exchange(ExchangeMarketKind { base, quote }) => self
.marketdata(cpty, false)
.append("rt")
.append("by-name")
.append(&market.venue.name)
.append(&market.route.name)
.append(base.name.as_str())
.append(quote.name.as_str()),
_ => {
panic!("legacy_marketdata_paths only supported for Exchange markets");
}
}
} else {
market.path_by_name(&self.marketdata_rt(cpty))
}
}
pub fn marketdata_ohlc(&self, cpty: Cpty) -> Path {
self.marketdata(cpty, false)
.append("ohlc")
.append(&cpty.venue.name)
.append(&cpty.route.name)
}
pub fn marketdata_ohlc_by_name(&self, market: MarketRef, hist: bool) -> Path {
let cpty = market.cpty();
if self.use_legacy_marketdata.contains(&cpty.id())
|| (hist && self.use_legacy_hist_marketdata.contains(&cpty.id()))
{
match market.kind {
MarketKind::Exchange(ExchangeMarketKind { base, quote }) => self
.marketdata(cpty, hist)
.append("ohlc")
.append("by-name")
.append(&market.venue.name)
.append(&market.route.name)
.append(base.name.as_str())
.append(quote.name.as_str()),
_ => {
panic!("legacy_marketdata_paths only supported for Exchange markets");
}
}
} else {
let base = self.marketdata_ohlc(cpty);
market.path_by_name(&base)
}
}
pub fn marketdata_hist_ohlc(&self, cpty: Cpty) -> Path {
if self.use_legacy_marketdata.contains(&cpty.id())
|| self.use_legacy_hist_marketdata.contains(&cpty.id())
{
self.marketdata(cpty, true)
.append("hist")
.append("ohlc")
.append("by-name")
.append(&cpty.venue.name)
.append(&cpty.route.name)
} else {
self.marketdata(cpty, true)
.append("hist")
.append("ohlc")
.append(&cpty.venue.name)
.append(&cpty.route.name)
}
}
pub fn marketdata_api(&self, cpty: Cpty) -> Path {
self.marketdata(cpty, false)
.append("api")
.append(&cpty.venue.name)
.append(&cpty.route.name)
}
pub fn historical_marketdata_api(&self) -> Path {
let use_local = true;
let base = if use_local { &self.local_base } else { &self.hosted_base };
base.append("marketdata").append("historical-api")
}
pub fn marketdata_rfq(&self, cpty: Cpty) -> Path {
self.marketdata(cpty, false)
.append("rfq")
.append(&cpty.venue.name)
.append(&cpty.route.name)
}
pub fn marketdata_snapshots(&self, local: bool) -> Path {
let base = if local { &self.local_base } else { &self.hosted_base };
base.append("marketdata").append("snapshots")
}
pub fn marketdata_marks(&self) -> Path {
self.local_base.append("qf").append("marks")
}
pub fn core(&self) -> Path {
self.core_base.clone()
}
pub fn channel(&self, com: Option<ComponentId>) -> Result<Path> {
match com {
None => Ok(self.core_base.append("channel")),
Some(com) => {
if self.local_components.contains(&com) {
Ok(self.core_base.append("channel"))
} else if let Some(base) = self.remote_components.get(&com) {
Ok(base.append("channel"))
} else {
bail!("no path to component {}", com);
}
}
}
}
pub fn in_channel(&self) -> Path {
self.core_base.append("in-channel")
}
pub fn component(&self, com: ComponentId) -> Result<(Path, Path)> {
let kind = self
.component_kind
.get(&com)
.ok_or_else(|| anyhow!("BUG: unknown component kind for {}", com))?;
let base = if self.local_components.contains(&com) {
self.local_base.clone()
} else if let Some(_base) = self.remote_components.get(&com) {
self.local_base.clone()
} else {
bail!("BUG: unknown component {}", com);
};
Ok((
base.append("components").append(&com.to_string()),
base.append("components").append(kind).append(&com.to_string()),
))
}
pub fn licensedb(&self) -> Path {
let base =
if self.use_local_licensedb { &self.local_base } else { &self.hosted_base };
base.append("licensedb")
}
}