Skip to main content

alpaca_data/options/
convenience.rs

1use std::collections::HashMap;
2
3use rust_decimal::Decimal;
4
5use super::{OptionsFeed, Snapshot};
6
7impl Snapshot {
8    #[must_use]
9    pub fn timestamp(&self) -> Option<&str> {
10        [
11            self.latest_trade
12                .as_ref()
13                .and_then(|trade| trade.t.as_deref()),
14            self.latest_quote
15                .as_ref()
16                .and_then(|quote| quote.t.as_deref()),
17            self.minute_bar.as_ref().and_then(|bar| bar.t.as_deref()),
18            self.daily_bar.as_ref().and_then(|bar| bar.t.as_deref()),
19            self.prev_daily_bar
20                .as_ref()
21                .and_then(|bar| bar.t.as_deref()),
22        ]
23        .into_iter()
24        .flatten()
25        .filter(|value| !value.trim().is_empty())
26        .max()
27    }
28
29    #[must_use]
30    pub fn bid_price(&self) -> Option<Decimal> {
31        self.latest_quote.as_ref().and_then(|quote| quote.bp)
32    }
33
34    #[must_use]
35    pub fn ask_price(&self) -> Option<Decimal> {
36        self.latest_quote.as_ref().and_then(|quote| quote.ap)
37    }
38
39    #[must_use]
40    pub fn last_price(&self) -> Option<Decimal> {
41        self.latest_trade.as_ref().and_then(|trade| trade.p)
42    }
43
44    #[must_use]
45    pub fn minute_volume(&self) -> Option<u64> {
46        self.minute_bar.as_ref().and_then(|bar| bar.v)
47    }
48
49    #[must_use]
50    pub fn daily_volume(&self) -> Option<u64> {
51        self.daily_bar.as_ref().and_then(|bar| bar.v)
52    }
53
54    #[must_use]
55    pub fn latest_trade_size(&self) -> Option<u64> {
56        self.latest_trade.as_ref().and_then(|trade| trade.s)
57    }
58
59    #[must_use]
60    pub fn bid_size(&self) -> Option<u64> {
61        self.latest_quote.as_ref().and_then(|quote| quote.bs)
62    }
63
64    #[must_use]
65    pub fn ask_size(&self) -> Option<u64> {
66        self.latest_quote.as_ref().and_then(|quote| quote.r#as)
67    }
68
69    #[must_use]
70    pub fn mark_price(&self) -> Option<Decimal> {
71        match (self.bid_price(), self.ask_price()) {
72            (Some(bid), Some(ask)) => Some((bid + ask) / Decimal::from(2u8)),
73            (Some(bid), None) => Some(bid),
74            (None, Some(ask)) => Some(ask),
75            (None, None) => None,
76        }
77    }
78}
79
80#[must_use]
81pub fn ordered_snapshots(snapshots: &HashMap<String, Snapshot>) -> Vec<(&str, &Snapshot)> {
82    let mut symbols = snapshots.keys().map(String::as_str).collect::<Vec<_>>();
83    symbols.sort_unstable();
84    symbols
85        .into_iter()
86        .filter_map(|symbol| {
87            snapshots
88                .get_key_value(symbol)
89                .map(|(symbol, snapshot)| (symbol.as_str(), snapshot))
90        })
91        .collect()
92}
93
94#[must_use]
95pub fn preferred_feed() -> OptionsFeed {
96    OptionsFeed::Opra
97}