rusty_model/instruments/
mod.rs

1use crate::venues::Venue;
2use rusty_common::SmartString;
3use serde::{Deserialize, Serialize};
4use std::any::Any;
5use std::fmt::{Debug, Display, Formatter};
6
7/// Instrument trait for representing tradable assets on exchanges
8pub trait Instrument: 'static + Send + Sync + Debug {
9    /// Get the instrument ID
10    fn id(&self) -> InstrumentId;
11
12    /// Get the symbol (shorthand for id().symbol)
13    fn symbol(&self) -> SmartString {
14        self.id().symbol
15    }
16
17    /// Get the venue (shorthand for id().venue)
18    fn venue(&self) -> Venue {
19        self.id().venue
20    }
21
22    /// Convert to Any for downcasting
23    fn as_any(&self) -> &dyn Any;
24
25    /// Clone this instrument into a new box
26    fn clone_box(&self) -> Box<dyn Instrument>;
27}
28
29/// A unique identifier for a trading instrument.
30#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
31pub struct InstrumentId {
32    /// The trading symbol for the instrument (e.g., "BTC-USDT").
33    pub symbol: SmartString, // Trading symbol (BTCUSD ..)
34    /// The exchange or venue where the instrument is traded.
35    pub venue: Venue,
36}
37
38impl InstrumentId {
39    /// Creates a new `InstrumentId`.
40    #[must_use]
41    pub fn new(symbol: impl AsRef<str>, venue: Venue) -> Self {
42        Self {
43            symbol: symbol.as_ref().into(),
44            venue,
45        }
46    }
47}
48
49impl Display for InstrumentId {
50    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
51        write!(
52            f,
53            "InstrumentId(symbol: {}, venue: {:?})",
54            self.symbol, self.venue
55        )
56    }
57}
58
59/// `SpotInstrument` represents a spot market instrument
60#[derive(Debug, Clone)]
61pub struct SpotInstrument {
62    id: InstrumentId,
63    base_currency: SmartString,
64    quote_currency: SmartString,
65}
66
67impl SpotInstrument {
68    /// Creates a new `SpotInstrument`.
69    #[must_use]
70    pub fn new(
71        symbol: impl AsRef<str>,
72        base_currency: impl AsRef<str>,
73        quote_currency: impl AsRef<str>,
74        venue: Venue,
75    ) -> Self {
76        Self {
77            id: InstrumentId::new(symbol, venue),
78            base_currency: base_currency.as_ref().into(),
79            quote_currency: quote_currency.as_ref().into(),
80        }
81    }
82
83    /// Returns the base currency of the instrument.
84    #[must_use]
85    pub fn base_currency(&self) -> &str {
86        &self.base_currency
87    }
88
89    /// Returns the quote currency of the instrument.
90    #[must_use]
91    pub fn quote_currency(&self) -> &str {
92        &self.quote_currency
93    }
94}
95
96impl Instrument for SpotInstrument {
97    fn id(&self) -> InstrumentId {
98        self.id.clone()
99    }
100
101    fn as_any(&self) -> &dyn Any {
102        self
103    }
104
105    fn clone_box(&self) -> Box<dyn Instrument> {
106        Box::new(self.clone())
107    }
108}