ig_client/application/services/
types.rs

1use crate::application::models::market::{MarketData, MarketNode};
2use crate::error::AppError;
3use crate::impl_json_display;
4use crate::presentation::InstrumentType;
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8/// Result type for listener operations that don't return a value but may return an error
9pub type ListenerResult = Result<(), AppError>;
10
11/// A data structure representing an entry in the database, containing details about a financial trading instrument.
12///
13/// # Fields
14///
15/// * `symbol` - The unique identifier or trading symbol for this financial instrument.
16/// * `epic` - The Epic identifier as provided by the exchange for this instrument.
17/// * `name` - A human-readable name that describes the financial instrument.
18/// * `instrument_type` - The classification or type of the financial instrument (e.g., stock, bond, future, etc.).
19/// * `exchange` - The name of the exchange where this instrument is traded.
20/// * `expiry` - The expiration date and time of the instrument, if applicable.
21/// * `last_update` - The `DateTime` indicating when this record was last updated.
22///
23/// This structure includes traits such as `Debug`, `Clone`, `Serialize`, `Deserialize`, `PartialEq`, `Eq`, `Hash`, and `Default`
24/// for ease of use, serialization, comparison, and hashing operations.
25#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
26pub struct DBEntry {
27    /// The trading symbol identifier
28    pub symbol: String,
29    /// The Epic identifier used by the exchange
30    pub epic: String,
31    /// Human-readable name of the instrument
32    pub name: String,
33    /// Instrument type classification
34    pub instrument_type: InstrumentType,
35    /// The exchange where this instrument is traded
36    pub exchange: String,
37    /// Expiration date and time for the instrument
38    pub expiry: String,
39    /// Timestamp of the last update to this record
40    pub last_update: DateTime<Utc>,
41}
42
43impl_json_display!(DBEntry);
44
45impl From<MarketNode> for DBEntry {
46    fn from(value: MarketNode) -> Self {
47        let mut entry = DBEntry::default();
48        if !value.markets.is_empty() {
49            let market = &value.markets[0];
50            entry.symbol = market
51                .epic
52                .split('.')
53                .nth(2)
54                .unwrap_or_default()
55                .to_string();
56            entry.epic = market.epic.clone();
57            entry.name = market.instrument_name.clone();
58            entry.instrument_type = market.instrument_type;
59            entry.exchange = "IG".to_string();
60            entry.expiry = market.expiry.clone();
61            entry.last_update = Utc::now();
62        }
63        entry
64    }
65}
66
67impl From<MarketData> for DBEntry {
68    fn from(market: MarketData) -> Self {
69        DBEntry {
70            symbol: market
71                .epic
72                .split('.')
73                .nth(2)
74                .unwrap_or_default()
75                .to_string(),
76            epic: market.epic.clone(),
77            name: market.instrument_name.clone(),
78            instrument_type: market.instrument_type,
79            exchange: "IG".to_string(),
80            expiry: market.expiry.clone(),
81            last_update: Utc::now(),
82        }
83    }
84}
85
86impl From<&MarketNode> for DBEntry {
87    fn from(value: &MarketNode) -> Self {
88        DBEntry::from(value.clone())
89    }
90}
91
92impl From<&MarketData> for DBEntry {
93    fn from(market: &MarketData) -> Self {
94        DBEntry::from(market.clone())
95    }
96}