flowsurface_data/
chart.rs1pub mod comparison;
2pub mod heatmap;
3pub mod indicator;
4pub mod kline;
5
6use exchange::Timeframe;
7use serde::{Deserialize, Serialize};
8
9use super::aggr::{
10 self,
11 ticks::TickAggr,
12 time::{DataPoint, TimeSeries},
13};
14pub use kline::KlineChartKind;
15
16pub enum PlotData<D: DataPoint> {
17 TimeBased(TimeSeries<D>),
18 TickBased(TickAggr),
19}
20
21impl<D: DataPoint> PlotData<D> {
22 pub fn latest_y_midpoint(&self, calculate_target_y: impl Fn(exchange::Kline) -> f32) -> f32 {
23 match self {
24 PlotData::TimeBased(timeseries) => timeseries
25 .latest_kline()
26 .map_or(0.0, |kline| calculate_target_y(*kline)),
27 PlotData::TickBased(tick_aggr) => tick_aggr
28 .latest_dp()
29 .map_or(0.0, |(dp, _)| calculate_target_y(dp.kline)),
30 }
31 }
32
33 pub fn visible_price_range(
34 &self,
35 start_interval: u64,
36 end_interval: u64,
37 ) -> Option<(f32, f32)> {
38 match self {
39 PlotData::TimeBased(timeseries) => {
40 timeseries.min_max_price_in_range(start_interval, end_interval)
41 }
42 PlotData::TickBased(tick_aggr) => {
43 tick_aggr.min_max_price_in_range(start_interval as usize, end_interval as usize)
44 }
45 }
46 }
47}
48
49#[derive(Debug, Clone, Deserialize, Serialize, Default)]
50pub struct ViewConfig {
51 pub splits: Vec<f32>,
52 pub autoscale: Option<Autoscale>,
53}
54
55#[derive(Debug, Clone, Copy, Deserialize, Serialize, Default, PartialEq)]
56pub enum Autoscale {
57 #[default]
58 CenterLatest,
59 FitToVisible,
60}
61
62#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
64pub enum Basis {
65 Time(exchange::Timeframe),
67
68 Tick(aggr::TickCount),
72}
73
74impl Basis {
75 pub fn is_time(&self) -> bool {
76 matches!(self, Basis::Time(_))
77 }
78
79 pub fn default_heatmap_time(ticker_info: Option<exchange::TickerInfo>) -> Self {
80 let fallback = Timeframe::MS500;
81
82 let interval = ticker_info.map_or(fallback, |info| {
83 let ex = info.exchange();
84 Timeframe::HEATMAP
85 .iter()
86 .copied()
87 .find(|tf| ex.supports_heatmap_timeframe(*tf))
88 .unwrap_or(fallback)
89 });
90
91 interval.into()
92 }
93}
94
95impl std::fmt::Display for Basis {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 match self {
98 Basis::Time(timeframe) => write!(f, "{timeframe}"),
99 Basis::Tick(count) => write!(f, "{count}"),
100 }
101 }
102}
103
104impl From<exchange::Timeframe> for Basis {
105 fn from(timeframe: exchange::Timeframe) -> Self {
106 Self::Time(timeframe)
107 }
108}
109
110#[derive(Debug, Clone, Deserialize, Serialize)]
111pub enum Study {
112 Heatmap(Vec<heatmap::HeatmapStudy>),
113 Footprint(Vec<kline::FootprintStudy>),
114}