barter_instrument/
lib.rs

1#![forbid(unsafe_code)]
2#![warn(
3    unused,
4    clippy::cognitive_complexity,
5    unused_crate_dependencies,
6    unused_extern_crates,
7    clippy::unused_self,
8    clippy::useless_let_if_seq,
9    missing_debug_implementations,
10    rust_2018_idioms,
11    rust_2024_compatibility
12)]
13#![allow(clippy::type_complexity, clippy::too_many_arguments, type_alias_bounds)]
14
15//! # Barter-Instrument
16//! Barter-Instrument contains core Exchange, Instrument and Asset data structures and associated utilities.
17//!
18//! ## Examples
19//! For a comprehensive collection of examples, see the Barter core Engine /examples directory.
20
21use derive_more::Constructor;
22use serde::{Deserialize, Serialize};
23use std::fmt::{Display, Formatter};
24
25/// Defines a global [`ExchangeId`](exchange::ExchangeId) enum covering all exchanges.
26pub mod exchange;
27
28/// [`Asset`](asset::Asset) related data structures.
29///
30/// eg/ `AssetKind`, `AssetNameInternal`, etc.
31pub mod asset;
32
33/// [`Instrument`](instrument::Instrument) related data structures.
34///
35/// eg/ `InstrumentKind`, `OptionContract``, etc.
36pub mod instrument;
37
38/// Indexed collection of exchanges, assets, and instruments. Provides a builder utility for
39/// indexing non-indexed collections.
40pub mod index;
41
42/// A keyed value.
43///
44/// eg/ Keyed<InstrumentIndex, Instrument>
45#[derive(
46    Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Constructor,
47)]
48pub struct Keyed<Key, Value> {
49    pub key: Key,
50    pub value: Value,
51}
52
53impl<Key, Value> AsRef<Value> for Keyed<Key, Value> {
54    fn as_ref(&self) -> &Value {
55        &self.value
56    }
57}
58
59impl<Key, Value> Display for Keyed<Key, Value>
60where
61    Key: Display,
62    Value: Display,
63{
64    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
65        write!(f, "{}, {}", self.key, self.value)
66    }
67}
68
69/// Instrument Underlying containing a base and quote asset.
70///
71/// eg/ Underlying { base: "btc", quote: "usdt" }
72#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
73pub struct Underlying<AssetKey> {
74    pub base: AssetKey,
75    pub quote: AssetKey,
76}
77
78impl<AssetKey> Underlying<AssetKey> {
79    pub fn new<A>(base: A, quote: A) -> Self
80    where
81        A: Into<AssetKey>,
82    {
83        Self {
84            base: base.into(),
85            quote: quote.into(),
86        }
87    }
88}
89
90/// [`Side`] of a trade or position - Buy or Sell.
91#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
92pub enum Side {
93    #[serde(alias = "buy", alias = "BUY", alias = "b")]
94    Buy,
95    #[serde(alias = "sell", alias = "SELL", alias = "s")]
96    Sell,
97}
98
99impl Display for Side {
100    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
101        write!(
102            f,
103            "{}",
104            match self {
105                Side::Buy => "buy",
106                Side::Sell => "sell",
107            }
108        )
109    }
110}
111
112pub mod test_utils {
113    use crate::{
114        Underlying,
115        asset::{
116            Asset, ExchangeAsset,
117            name::{AssetNameExchange, AssetNameInternal},
118        },
119        exchange::ExchangeId,
120        instrument::{
121            Instrument,
122            kind::InstrumentKind,
123            name::{InstrumentNameExchange, InstrumentNameInternal},
124            quote::InstrumentQuoteAsset,
125        },
126    };
127
128    pub fn exchange_asset(exchange: ExchangeId, symbol: &str) -> ExchangeAsset<Asset> {
129        ExchangeAsset {
130            exchange,
131            asset: asset(symbol),
132        }
133    }
134
135    pub fn asset(symbol: &str) -> Asset {
136        Asset {
137            name_internal: AssetNameInternal::from(symbol),
138            name_exchange: AssetNameExchange::from(symbol),
139        }
140    }
141
142    pub fn instrument(
143        exchange: ExchangeId,
144        base: &str,
145        quote: &str,
146    ) -> Instrument<ExchangeId, Asset> {
147        let name_exchange = InstrumentNameExchange::from(format!("{base}_{quote}"));
148        let name_internal =
149            InstrumentNameInternal::new_from_exchange(exchange, name_exchange.clone());
150        let base_asset = asset(base);
151        let quote_asset = asset(quote);
152
153        Instrument::new(
154            exchange,
155            name_internal,
156            name_exchange,
157            Underlying::new(base_asset, quote_asset),
158            InstrumentQuoteAsset::UnderlyingQuote,
159            InstrumentKind::Spot,
160            None,
161        )
162    }
163}