Bläddra i källkod

chores and code cleanup

Berke 1 år sedan
förälder
incheckning
5d30bcc53e
3 ändrade filer med 185 tillägg och 183 borttagningar
  1. 49 49
      src/charts/heatmap.rs
  2. 60 62
      src/main.rs
  3. 76 72
      src/screen/dashboard.rs

+ 49 - 49
src/charts/heatmap.rs

@@ -50,7 +50,7 @@ impl HeatmapChart {
             chart: CommonChartData::default(),
             data_points: BTreeMap::new(),
             tick_size,
-            y_scaling: 20,
+            y_scaling: 100,
             size_filter: 0.0,
         }
     }
@@ -62,6 +62,10 @@ impl HeatmapChart {
         self.size_filter
     }
 
+    fn price_to_float(&self, price: i64) -> f32 {
+        price as f32 * self.tick_size
+    }
+
     pub fn change_tick_size(&mut self, tick_size: f32) {
         self.tick_size = tick_size;
 
@@ -70,6 +74,50 @@ impl HeatmapChart {
         self.chart.y_labels_cache.clear();
     }
 
+    fn calculate_range(&self) -> (i64, i64, f32, f32) {
+        let timestamp_latest: &i64 = self.data_points.keys().last().unwrap_or(&0);
+
+        let latest: i64 = *timestamp_latest - (self.chart.translation.x*60.0) as i64;
+        let earliest: i64 = latest - (48000.0 / (self.chart.scaling / (self.chart.bounds.width/800.0))) as i64;
+    
+        let mut max_ask_price = f32::MIN;
+        let mut min_bid_price = f32::MAX;
+
+        for (_, (depth, _)) in self.data_points.range(earliest..=latest) {
+            if self.chart.autoscale {
+                max_ask_price = max_ask_price.max(
+                    self.price_to_float(
+                        *depth.asks.keys().last().unwrap_or(&0)
+                    )
+                );
+                min_bid_price = min_bid_price.min(
+                    self.price_to_float(
+                        *depth.bids.keys().next().unwrap_or(&0)
+                    )
+                );
+            } else {
+                max_ask_price = max_ask_price.max(
+                    self.price_to_float(
+                        *depth.asks.keys().nth(self.y_scaling.try_into().unwrap_or(20))
+                            .unwrap_or(depth.asks.keys().last()
+                                .unwrap_or(&0)
+                            )
+                    )
+                );
+                min_bid_price = min_bid_price.min(
+                    self.price_to_float(
+                        *depth.bids.keys().nth_back(self.y_scaling.try_into().unwrap_or(20))
+                            .unwrap_or(depth.bids.keys().next()
+                                .unwrap_or(&0)
+                            )
+                    )
+                );
+            }
+        }
+
+        (latest, earliest, max_ask_price, min_bid_price)
+    }
+
     pub fn insert_datapoint(&mut self, trades_buffer: &[Trade], depth_update: i64, depth: Rc<Depth>) {
         let aggregate_time = 100; // 100 ms
         let rounded_depth_update = (depth_update / aggregate_time) * aggregate_time;
@@ -149,50 +197,6 @@ impl HeatmapChart {
         chart_state.main_cache.clear();   
     }
 
-    fn calculate_range(&self) -> (i64, i64, f32, f32) {
-        let timestamp_latest: &i64 = self.data_points.keys().last().unwrap_or(&0);
-
-        let latest: i64 = *timestamp_latest - (self.chart.translation.x*60.0) as i64;
-        let earliest: i64 = latest - (48000.0 / (self.chart.scaling / (self.chart.bounds.width/800.0))) as i64;
-    
-        let mut max_ask_price = f32::MIN;
-        let mut min_bid_price = f32::MAX;
-
-        for (_, (depth, _)) in self.data_points.range(earliest..=latest) {
-            if self.chart.autoscale {
-                max_ask_price = max_ask_price.max(
-                    self.price_to_float(
-                        *depth.asks.keys().last().unwrap_or(&0)
-                    )
-                );
-                min_bid_price = min_bid_price.min(
-                    self.price_to_float(
-                        *depth.bids.keys().next().unwrap_or(&0)
-                    )
-                );
-            } else {
-                max_ask_price = max_ask_price.max(
-                    self.price_to_float(
-                        *depth.asks.keys().nth(self.y_scaling.try_into().unwrap_or(20))
-                            .unwrap_or(depth.asks.keys().last()
-                                .unwrap_or(&0)
-                            )
-                    )
-                );
-                min_bid_price = min_bid_price.min(
-                    self.price_to_float(
-                        *depth.bids.keys().nth_back(self.y_scaling.try_into().unwrap_or(20))
-                            .unwrap_or(depth.bids.keys().next()
-                                .unwrap_or(&0)
-                            )
-                    )
-                );
-            }
-        }
-
-        (latest, earliest, max_ask_price, min_bid_price)
-    }
-
     pub fn update(&mut self, message: &Message) {
         match message {
             Message::Translated(translation) => {
@@ -270,10 +274,6 @@ impl HeatmapChart {
         }
     }
 
-    fn price_to_float(&self, price: i64) -> f32 {
-        price as f32 * self.tick_size
-    }
-
     pub fn view(&self) -> Element<Message> {
         let chart = Canvas::new(self)
             .width(Length::FillPortion(10))

+ 60 - 62
src/main.rs

@@ -331,7 +331,7 @@ impl State {
 
                 let dashboard = self.get_mut_dashboard();
             
-                match dashboard.pane_change_timeframe(pane_id, timeframe) {
+                match dashboard.set_pane_timeframe(pane_id, timeframe) {
                     Ok(stream_type) => {
                         if let StreamType::Kline { exchange, ticker, timeframe } = stream_type {
                             let stream = *stream_type;
@@ -386,7 +386,7 @@ impl State {
             Message::TicksizeSelected(tick_multiply, pane_id) => {
                 let dashboard = self.get_mut_dashboard();
                 
-                match dashboard.pane_change_ticksize(pane_id, tick_multiply) {
+                match dashboard.set_pane_ticksize(pane_id, tick_multiply) {
                     Ok(_) => {
                         log::info!("Ticksize changed");
             
@@ -404,15 +404,8 @@ impl State {
 
                 match klines {
                     Ok(klines) => {
-                        match pane_stream {
-                            StreamType::Kline { exchange, ticker, timeframe } => {
-                                dashboard.insert_klines_vec(&StreamType::Kline {
-                                    exchange,
-                                    ticker,
-                                    timeframe,
-                                }, &klines, pane_id);
-                            },
-                            _ => {}
+                        if let StreamType::Kline { .. } = pane_stream {
+                            dashboard.insert_klines_vec(&pane_stream, &klines, pane_id);
                         }
                     },
                     Err(err) => {
@@ -679,23 +672,15 @@ impl State {
             Message::SliderChanged(pane_id, value) => {
                 let dashboard = self.get_mut_dashboard();
 
-                match dashboard.pane_set_size_filter(pane_id, value) {
+                match dashboard.set_pane_size_filter(pane_id, value) {
                     Ok(_) => {
-                        match dashboard.get_pane_settings_mut(pane_id) {
-                            Ok(pane_settings) => {
-                                pane_settings.trade_size_filter = Some(value);
-        
-                                Task::none()
-                            },
-                            Err(err) => {
-                                log::error!("Failed to set size filter: {err}");
-        
-                                Task::none()
-                            }
-                        }
+                        log::info!("Size filter set to {value}");
+
+                        Task::none()
                     }
                     Err(err) => {
                         log::error!("{err}");
+                        
                         Task::none()
                     }
                 }
@@ -724,55 +709,41 @@ impl State {
                 let dashboard = self.get_mut_dashboard();
 
                 let mut tasks = vec![];
-                
+                    
                 let pane_content = match content.as_str() {
-                    "Heatmap chart" => PaneContent::Heatmap(HeatmapChart::new(1.0)),
+                    "Heatmap chart" => PaneContent::Heatmap(
+                        HeatmapChart::new(1.0)
+                    ),
                     "Footprint chart" => {
-                        let footprint_chart = FootprintChart::new(1, 1.0, vec![], vec![]);
-                        PaneContent::Footprint(footprint_chart)
+                        PaneContent::Footprint(
+                            FootprintChart::new(1, 1.0, vec![], vec![])
+                        )
                     },
                     "Candlestick chart" => {
-                        let candlestick_chart = CandlestickChart::new(vec![], 1);
-                        PaneContent::Candlestick(candlestick_chart)
+                        PaneContent::Candlestick(
+                            CandlestickChart::new(vec![], 1)
+                        )
                     },
-                    "Time&Sales" => PaneContent::TimeAndSales(TimeAndSales::new()),
+                    "Time&Sales" => PaneContent::TimeAndSales(
+                        TimeAndSales::new()
+                    ),
                     _ => return Task::none(),
                 };
-                
-                if let Ok(vec_streams) = dashboard.get_pane_stream_mut(pane_id) {
-                    *vec_streams = pane_stream.to_vec();
-                } else {
-                    log::error!("No pane found for stream update");
-                }
-            
+
+                // set pane's stream and content identifiers
                 if let Err(err) = dashboard.set_pane_content(pane_id, pane_content) {
                     log::error!("Failed to set pane content: {}", err);
                 } else {
                     log::info!("Pane content set: {content}");
                 }
                 
-                if content == "Footprint chart" || content == "Candlestick chart" || content == "Heatmap chart" {
-                    for stream in pane_stream.iter() {
-                        if let StreamType::Kline { exchange, ticker, timeframe } = stream {
-                            let stream_clone = *stream;
-                
-                            if content == "Candlestick chart" || content == "Footprint chart" {
-                                let fetch_klines = create_fetch_klines_task(exchange, ticker, timeframe, stream_clone, pane_id);
-                                tasks.push(fetch_klines);
-
-                                if content == "Footprint chart" {
-                                    let fetch_ticksize = create_fetch_ticksize_task(exchange, ticker, pane_id);
-                                    tasks.push(fetch_ticksize);
-                                }
-                            }
-                        
-                        } else if let StreamType::DepthAndTrades { exchange, ticker } = stream {
-                            let fetch_ticksize = create_fetch_ticksize_task(exchange, ticker, pane_id);
-                            tasks.push(fetch_ticksize);
-                        }
-                    }
+                if let Err(err) = dashboard.set_pane_stream(pane_id, pane_stream.to_vec()) {
+                    log::error!("Failed to set pane stream: {err}");
+                } else {
+                    log::info!("Pane stream set: {pane_stream:?}");
                 }
             
+                // prepare unique streams for websocket
                 for stream in pane_stream.iter() {
                     match stream {
                         StreamType::Kline { exchange, ticker, .. } | StreamType::DepthAndTrades { exchange, ticker } => {
@@ -788,6 +759,27 @@ impl State {
                 }
             
                 log::info!("{:?}", &self.pane_streams);
+
+                // get fetch tasks for pane's content
+                if ["Footprint chart", "Candlestick chart", "Heatmap chart"].contains(&content.as_str()) {
+                    for stream in pane_stream.iter() {
+                        match stream {
+                            StreamType::Kline { exchange, ticker, timeframe } => {
+                                if ["Candlestick chart", "Footprint chart"].contains(&content.as_str()) {
+                                    tasks.push(create_fetch_klines_task(exchange, ticker, timeframe, *stream, pane_id));
+                                    
+                                    if content == "Footprint chart" {
+                                        tasks.push(create_fetch_ticksize_task(exchange, ticker, pane_id));
+                                    }
+                                }
+                            },
+                            StreamType::DepthAndTrades { exchange, ticker } => {
+                                tasks.push(create_fetch_ticksize_task(exchange, ticker, pane_id));
+                            },
+                            _ => {}
+                        }
+                    }
+                }
                 
                 Task::batch(tasks)
             },
@@ -1452,10 +1444,16 @@ fn view_starter(
                     );
 
                     let pane_stream: Vec<StreamType> = match label {
-                        "Heatmap chart" => vec![StreamType::DepthAndTrades { exchange, ticker }],
-                        "Footprint chart" => vec![StreamType::DepthAndTrades { exchange, ticker }, StreamType::Kline { exchange, ticker, timeframe }],
-                        "Candlestick chart" => vec![StreamType::Kline { exchange, ticker, timeframe }],
-                        "Time&Sales" => vec![StreamType::DepthAndTrades { exchange, ticker }],
+                        "Heatmap chart" | "Time&Sales" => vec![
+                            StreamType::DepthAndTrades { exchange, ticker }
+                        ],
+                        "Footprint chart" => vec![
+                            StreamType::DepthAndTrades { exchange, ticker }, 
+                            StreamType::Kline { exchange, ticker, timeframe }
+                        ],
+                        "Candlestick chart" => vec![
+                            StreamType::Kline { exchange, ticker, timeframe }
+                        ],
                         _ => vec![]
                     };
                 

+ 76 - 72
src/screen/dashboard.rs

@@ -106,56 +106,30 @@ impl Dashboard {
         }
     }
 
-    pub fn update_chart_state(&mut self, pane_id: Uuid, message: Message) -> Result<(), &str> {
+    pub fn get_pane_settings_mut(&mut self, pane_id: Uuid) -> Result<&mut PaneSettings, &str> {
         for (_, pane_state) in self.panes.iter_mut() {
             if pane_state.id == pane_id {
-                match pane_state.content {
-                    PaneContent::Heatmap(ref mut chart) => {
-                        chart.update(&message);
-
-                        return Ok(());
-                    },
-                    PaneContent::Footprint(ref mut chart) => {
-                        chart.update(&message);
-
-                        return Ok(());
-                    },
-                    PaneContent::Candlestick(ref mut chart) => {
-                        chart.update(&message);
-
-                        return Ok(());
-                    },
-                    _ => {
-                        return Err("No chart found");
-                    }
-                }
+                return Ok(&mut pane_state.settings);
             }
         }
         Err("No pane found")
     }
 
-    pub fn get_pane_stream_mut(&mut self, pane_id: Uuid) -> Result<&mut Vec<StreamType>, &str> {
+    pub fn set_pane_content(&mut self, pane_id: Uuid, content: PaneContent) -> Result<(), &str> {
         for (_, pane_state) in self.panes.iter_mut() {
             if pane_state.id == pane_id {
-                return Ok(&mut pane_state.stream);
-            }
-        }
-        Err("No pane found")
-    }
+                pane_state.content = content;
 
-    pub fn get_pane_settings_mut(&mut self, pane_id: Uuid) -> Result<&mut PaneSettings, &str> {
-        for (_, pane_state) in self.panes.iter_mut() {
-            if pane_state.id == pane_id {
-                return Ok(&mut pane_state.settings);
+                return Ok(());
             }
         }
         Err("No pane found")
     }
 
-    pub fn set_pane_content(&mut self, pane_id: Uuid, content: PaneContent) -> Result<(), &str> {
+    pub fn set_pane_stream(&mut self, pane_id: Uuid, stream: Vec<StreamType>) -> Result<(), &str> {
         for (_, pane_state) in self.panes.iter_mut() {
             if pane_state.id == pane_id {
-                pane_state.content = content;
+                pane_state.stream = stream;
 
                 return Ok(());
             }
@@ -163,7 +137,7 @@ impl Dashboard {
         Err("No pane found")
     }
 
-    pub fn pane_change_ticksize(&mut self, pane_id: Uuid, new_tick_multiply: TickMultiplier) -> Result<(), &str> {
+    pub fn set_pane_ticksize(&mut self, pane_id: Uuid, new_tick_multiply: TickMultiplier) -> Result<(), &str> {
         for (_, pane_state) in self.panes.iter_mut() {
             if pane_state.id == pane_id {
                 pane_state.settings.tick_multiply = Some(new_tick_multiply);
@@ -196,7 +170,7 @@ impl Dashboard {
         Err("No pane found")
     }
     
-    pub fn pane_change_timeframe(&mut self, pane_id: Uuid, new_timeframe: Timeframe) -> Result<&StreamType, &str> {
+    pub fn set_pane_timeframe(&mut self, pane_id: Uuid, new_timeframe: Timeframe) -> Result<&StreamType, &str> {
         for (_, pane_state) in self.panes.iter_mut() {
             if pane_state.id == pane_id {
                 pane_state.settings.selected_timeframe = Some(new_timeframe);
@@ -224,13 +198,15 @@ impl Dashboard {
         Err("No pane found")
     }
 
-    pub fn pane_set_size_filter(&mut self, pane_id: Uuid, new_size_filter: f32) -> Result<(), &str> {
+    pub fn set_pane_size_filter(&mut self, pane_id: Uuid, new_size_filter: f32) -> Result<(), &str> {
         for (_, pane_state) in self.panes.iter_mut() {
             if pane_state.id == pane_id {
+                pane_state.settings.trade_size_filter = Some(new_size_filter);
+
                 match pane_state.content {
                     PaneContent::Heatmap(ref mut chart) => {
                         chart.set_size_filter(new_size_filter);
-                        
+
                         return Ok(());
                     },
                     PaneContent::TimeAndSales(ref mut chart) => {
@@ -247,31 +223,32 @@ impl Dashboard {
         Err("No pane found")
     }
 
-    pub fn insert_klines_vec(&mut self, stream_type: &StreamType, klines: &Vec<Kline>, pane_id: Uuid) {
-        for (_, pane_state) in self.panes.iter_mut() {
-            if pane_state.id == pane_id {
-                match stream_type {
-                    StreamType::Kline { timeframe, .. } => {
-                        let timeframe_u16 = timeframe.to_minutes();
+    pub fn find_and_insert_ticksizes(&mut self, stream_type: &StreamType, tick_sizes: f32) -> Result<(), &str> {
+        let mut found_match = false;
 
-                        match &mut pane_state.content {
-                            PaneContent::Candlestick(chart) => {
-                                *chart = CandlestickChart::new(klines.to_vec(), timeframe_u16);
-                            },
-                            PaneContent::Footprint(chart) => {
-                                let raw_trades = chart.get_raw_trades();
+        for (_, pane_state) in self.panes.iter_mut() {
+            if pane_state.matches_stream(stream_type) {
+                match &mut pane_state.content {
+                    PaneContent::Footprint(_) => {
+                        pane_state.settings.min_tick_size = Some(tick_sizes);
 
-                                let tick_size = chart.get_tick_size();
+                        found_match = true;
+                    },
+                    PaneContent::Heatmap(_) => {
+                        pane_state.settings.min_tick_size = Some(tick_sizes);
 
-                                *chart = FootprintChart::new(timeframe_u16, tick_size, klines.to_vec(), raw_trades);
-                            },
-                            _ => {}
-                        }
+                        found_match = true;
                     },
                     _ => {}
                 }
             }
         }
+
+        if found_match {
+            Ok(())
+        } else {
+            Err("No matching pane found for the stream")
+        }
     }
 
     pub fn find_and_insert_klines(&mut self, stream_type: &StreamType, klines: &Vec<Kline>) -> Result<(), &str> {
@@ -313,32 +290,31 @@ impl Dashboard {
         }
     }
 
-    pub fn find_and_insert_ticksizes(&mut self, stream_type: &StreamType, tick_sizes: f32) -> Result<(), &str> {
-        let mut found_match = false;
-
+    pub fn insert_klines_vec(&mut self, stream_type: &StreamType, klines: &Vec<Kline>, pane_id: Uuid) {
         for (_, pane_state) in self.panes.iter_mut() {
-            if pane_state.matches_stream(stream_type) {
-                match &mut pane_state.content {
-                    PaneContent::Footprint(_) => {
-                        pane_state.settings.min_tick_size = Some(tick_sizes);
+            if pane_state.id == pane_id {
+                match stream_type {
+                    StreamType::Kline { timeframe, .. } => {
+                        let timeframe_u16 = timeframe.to_minutes();
 
-                        found_match = true;
-                    },
-                    PaneContent::Heatmap(_) => {
-                        pane_state.settings.min_tick_size = Some(tick_sizes);
+                        match &mut pane_state.content {
+                            PaneContent::Candlestick(chart) => {
+                                *chart = CandlestickChart::new(klines.to_vec(), timeframe_u16);
+                            },
+                            PaneContent::Footprint(chart) => {
+                                let raw_trades = chart.get_raw_trades();
 
-                        found_match = true;
+                                let tick_size = chart.get_tick_size();
+
+                                *chart = FootprintChart::new(timeframe_u16, tick_size, klines.to_vec(), raw_trades);
+                            },
+                            _ => {}
+                        }
                     },
                     _ => {}
                 }
             }
         }
-
-        if found_match {
-            Ok(())
-        } else {
-            Err("No matching pane found for the stream")
-        }
     }
 
     pub fn update_latest_klines(&mut self, stream_type: &StreamType, kline: &Kline) -> Result<(), &str> {
@@ -395,6 +371,34 @@ impl Dashboard {
         }
     }
 
+    pub fn update_chart_state(&mut self, pane_id: Uuid, message: Message) -> Result<(), &str> {
+        for (_, pane_state) in self.panes.iter_mut() {
+            if pane_state.id == pane_id {
+                match pane_state.content {
+                    PaneContent::Heatmap(ref mut chart) => {
+                        chart.update(&message);
+
+                        return Ok(());
+                    },
+                    PaneContent::Footprint(ref mut chart) => {
+                        chart.update(&message);
+
+                        return Ok(());
+                    },
+                    PaneContent::Candlestick(ref mut chart) => {
+                        chart.update(&message);
+
+                        return Ok(());
+                    },
+                    _ => {
+                        return Err("No chart found");
+                    }
+                }
+            }
+        }
+        Err("No pane found")
+    }
+
     pub fn get_all_diff_streams(&self) -> HashMap<Exchange, HashMap<Ticker, HashSet<StreamType>>> {
         let mut pane_streams = HashMap::new();