#![forbid(unsafe_code)]
#![deny(
clippy::unwrap_used,
clippy::expect_used,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
#![warn(
unused,
clippy::cognitive_complexity,
unused_crate_dependencies,
unused_extern_crates,
clippy::unused_self,
clippy::useless_let_if_seq,
missing_debug_implementations,
rust_2018_idioms
)]
#![allow(clippy::type_complexity, clippy::too_many_arguments, type_alias_bounds)]
use derive_more::Constructor;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
pub mod exchange;
pub mod asset;
pub mod instrument;
pub mod index;
#[cfg(feature = "ibkr")]
pub mod ibkr;
#[derive(
Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Constructor,
)]
pub struct Keyed<Key, Value> {
pub key: Key,
pub value: Value,
}
impl<Key, Value> AsRef<Value> for Keyed<Key, Value> {
fn as_ref(&self) -> &Value {
&self.value
}
}
impl<Key, Value> Display for Keyed<Key, Value>
where
Key: Display,
Value: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}, {}", self.key, self.value)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
pub struct Underlying<AssetKey> {
pub base: AssetKey,
pub quote: AssetKey,
}
impl<AssetKey> Underlying<AssetKey> {
pub fn new<A>(base: A, quote: A) -> Self
where
A: Into<AssetKey>,
{
Self {
base: base.into(),
quote: quote.into(),
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
pub enum Side {
#[serde(alias = "buy", alias = "BUY", alias = "b")]
Buy,
#[serde(alias = "sell", alias = "SELL", alias = "s")]
Sell,
}
impl Display for Side {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Side::Buy => "buy",
Side::Sell => "sell",
}
)
}
}
pub mod test_utils {
use crate::{
Underlying,
asset::{
Asset, ExchangeAsset,
name::{AssetNameExchange, AssetNameInternal},
},
exchange::ExchangeId,
instrument::{
Instrument,
kind::InstrumentKind,
name::{InstrumentNameExchange, InstrumentNameInternal},
quote::InstrumentQuoteAsset,
},
};
pub fn exchange_asset(exchange: ExchangeId, symbol: &str) -> ExchangeAsset<Asset> {
ExchangeAsset {
exchange,
asset: asset(symbol),
}
}
pub fn asset(symbol: &str) -> Asset {
Asset {
name_internal: AssetNameInternal::from(symbol),
name_exchange: AssetNameExchange::from(symbol),
}
}
pub fn instrument(
exchange: ExchangeId,
base: &str,
quote: &str,
) -> Instrument<ExchangeId, Asset> {
let name_exchange = InstrumentNameExchange::from(format!("{base}_{quote}"));
let name_internal =
InstrumentNameInternal::new_from_exchange(exchange, name_exchange.clone());
let base_asset = asset(base);
let quote_asset = asset(quote);
Instrument::new(
exchange,
name_internal,
name_exchange,
Underlying::new(base_asset, quote_asset),
InstrumentQuoteAsset::UnderlyingQuote,
InstrumentKind::Spot,
None,
)
}
}