Skip to main content

egui_charts/ui/trading/
format.rs

1//! The text of the numbers the trading panels show, per symbol.
2
3use super::widgets::grouped;
4
5/// Host text for the numbers of the order ticket, the depth ladder and the account tables.
6///
7/// Every method receives the symbol the number belongs to, so differently formatted instruments
8/// keep their own text. Return `None` to keep the built-in text: the symbol's price decimals for
9/// prices, spreads and pip values, and the decimals of the quantity step for quantities.
10/// Install it with [`Trading::set_formatter`](super::Trading::set_formatter).
11pub trait TradingFormatter: Send + Sync {
12    /// A price, such as a limit price, a bid or an average price.
13    fn price(&self, _symbol: &str, _price: f64) -> Option<String> {
14        None
15    }
16
17    /// A quantity, in the symbol's trading units.
18    fn quantity(&self, _symbol: &str, _quantity: f64) -> Option<String> {
19        None
20    }
21
22    /// The difference between the ask and the bid, in price units.
23    fn spread(&self, _symbol: &str, _spread: f64) -> Option<String> {
24        None
25    }
26
27    /// The value of one pip of the order in the account's currency.
28    fn pip_value(&self, _symbol: &str, _value: f64) -> Option<String> {
29        None
30    }
31}
32
33/// How the numbers of one symbol are written.
34#[derive(Clone, Copy)]
35pub(super) struct Numbers<'a> {
36    pub symbol: &'a str,
37    /// Decimals of the symbol's prices.
38    pub decimals: usize,
39    pub formatter: Option<&'a dyn TradingFormatter>,
40}
41
42impl Numbers<'_> {
43    pub fn price(&self, price: f64) -> String {
44        self.formatter
45            .and_then(|formatter| formatter.price(self.symbol, price))
46            .unwrap_or_else(|| grouped(price, self.decimals, false))
47    }
48
49    /// `quantity` at `decimals`, unless the formatter writes it.
50    pub fn quantity(&self, quantity: f64, decimals: usize) -> String {
51        self.formatter
52            .and_then(|formatter| formatter.quantity(self.symbol, quantity))
53            .unwrap_or_else(|| grouped(quantity, decimals, false))
54    }
55
56    pub fn spread(&self, spread: f64) -> String {
57        self.formatter
58            .and_then(|formatter| formatter.spread(self.symbol, spread))
59            .unwrap_or_else(|| grouped(spread, self.decimals, false))
60    }
61
62    pub fn pip_value(&self, value: f64) -> String {
63        self.formatter
64            .and_then(|formatter| formatter.pip_value(self.symbol, value))
65            .unwrap_or_else(|| grouped(value, self.decimals.max(2), false))
66    }
67}