浏览代码

add trade qtys as "bubbles" on the line chart

Berke 1 年之前
父节点
当前提交
5b750473a4
共有 1 个文件被更改,包括 28 次插入25 次删除
  1. 28 25
      src/main.rs

+ 28 - 25
src/main.rs

@@ -1,13 +1,11 @@
 mod ws_binance;
-use serde::Deserialize;
 use std::collections::HashMap;
 use chrono::{DateTime, Utc};
 use iced::{
-    executor, font, widget::{
+    executor, widget::{
         Row, button, canvas::{Cache, Frame, Geometry}, pick_list, shader::wgpu::hal::auxil::db, Column, Container, Text
     }, Alignment, Application, Command, Element, Event, Font, Length, Settings, Size, Subscription, Theme
 };
-use ws_binance::Kline;
 use futures::TryFutureExt;
 use plotters::prelude::ChartBuilder;
 use plotters_backend::DrawingBackend;
@@ -157,9 +155,10 @@ impl Application for State {
                     self.ws_state = WsState::Disconnected;
                     Command::none()
                 }
-                ws_binance::Event::TradeReceived(trades_buffer) => {
+                ws_binance::Event::DepthReceived(bids, asks, trades_buffer) => {
+                    let best_bid_price = bids.first().map(|(price, _)| *price).unwrap_or(0.0);
                     if let Some(chart) = &mut self.trades_chart {
-                        chart.update(trades_buffer);
+                        chart.update(trades_buffer, best_bid_price);
                     }
                     Command::none()
                 }
@@ -276,7 +275,6 @@ impl CandlestickChart {
 
 impl Chart<Message> for CandlestickChart {
     type State = ();
-
     #[inline]
     fn draw<R: Renderer, F: Fn(&mut Frame)>(
         &self,
@@ -334,7 +332,7 @@ impl Chart<Message> for CandlestickChart {
 
         chart.draw_series(
             self.data_points.iter().map(|(time, (open, high, low, close))| {
-                CandleStick::new(*time, *open, *high, *low, *close, GREEN.filled(), RED.filled(), 15)
+                CandleStick::new(*time, *open, *high, *low, *close, RGBColor(81, 205, 160).filled(), RGBColor(192, 80, 77).filled(), 15)
             }),
         ).expect("failed to draw chart data");
     }
@@ -342,7 +340,7 @@ impl Chart<Message> for CandlestickChart {
 
 struct LineChart {
     cache: Cache,
-    data_points: VecDeque<(DateTime<Utc>, f32)>,
+    data_points: VecDeque<(DateTime<Utc>, f32, f32, bool)>,
 }
 
 impl LineChart {
@@ -353,11 +351,10 @@ impl LineChart {
         }
     }
 
-    fn update(&mut self, mut trades_buffer: Vec<ws_binance::Trade>) {
+    fn update(&mut self, mut trades_buffer: Vec<ws_binance::Trade>, _best_bid_price: f32) {
         for trade in trades_buffer.drain(..) {
             let time = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(trade.time as i64 / 1000, 0), Utc);
-            let price = trade.price;
-            self.data_points.push_back((time, price));
+            self.data_points.push_back((time, trade.price, trade.qty, trade.is_sell));
         }
 
         while self.data_points.len() > 6000 {
@@ -378,16 +375,6 @@ impl LineChart {
 
 impl Chart<Message> for LineChart {
     type State = ();
-    // fn update(
-    //     &mut self,
-    //     event: Event,
-    //     bounds: Rectangle,
-    //     cursor: Cursor,
-    // ) -> (event::Status, Option<Message>) {
-    //     self.cache.clear();
-    //     (event::Status::Ignored, None)
-    // }
-
     #[inline]
     fn draw<R: Renderer, F: Fn(&mut Frame)>(
         &self,
@@ -413,9 +400,9 @@ impl Chart<Message> for LineChart {
             let oldest_time = newest_time - chrono::Duration::seconds(30);
         
             // y-axis range, acquire price range within the time range
-            let recent_data_points: Vec<_> = self.data_points.iter().filter_map(|&(time, price)| {
+            let recent_data_points: Vec<_> = self.data_points.iter().filter_map(|&(time, price, qty, bool)| {
                 if time >= oldest_time && time <= newest_time {
-                    Some((time, price))
+                    Some((time, price, qty, bool))
                 } else {
                     None
                 }
@@ -423,7 +410,7 @@ impl Chart<Message> for LineChart {
 
             let mut y_min = f32::MAX;
             let mut y_max = f32::MIN;
-            for (_, price) in &recent_data_points {
+            for (_, price, _, _) in &recent_data_points {
                 y_min = y_min.min(*price);
                 y_max = y_max.max(*price);
             }
@@ -463,13 +450,29 @@ impl Chart<Message> for LineChart {
             chart
                 .draw_series(
                     AreaSeries::new(
-                        recent_data_points,
+                        recent_data_points.iter().map(|&(time, price, _, _)| (time, price)),
                         0_f32,
                         PLOT_LINE_COLOR.mix(0.175),
                     )
                     .border_style(ShapeStyle::from(PLOT_LINE_COLOR).stroke_width(2)),
                 )
                 .expect("failed to draw chart data");
+            
+            let qty_min = recent_data_points.iter().map(|&(_, _, qty, _)| qty).fold(f32::MAX, f32::min);
+            let qty_max = recent_data_points.iter().map(|&(_, _, qty, _)| qty).fold(f32::MIN, f32::max);
+            chart
+                .draw_series(
+                    recent_data_points.iter().map(|&(time, price, qty, is_sell)| {
+                        let radius = 1.0 + (qty - qty_min) * (30.0 - 1.0) / (qty_max - qty_min);
+                        let color = if is_sell { RGBColor(192, 80, 77) } else { RGBColor(81, 205, 160)};
+                        Circle::new(
+                            (time, price), 
+                            radius as i32,
+                            ShapeStyle::from(color).filled(),
+                        )
+                    }),
+                )
+                .expect("failed to draw circles");
         }
     }
 }