emilk / egui_plot

2D plotting library in Rust for egui
Apache License 2.0
65 stars 23 forks source link

How to implement candlestick for plot? #9

Open olehbozhok opened 2 years ago

olehbozhok commented 2 years ago

Does it possible implement candlestick for plot?

I think if trait PlotItem set as public, I can create my own implementation for candlestick.

And it would be nice if it possiple to set custom lablex to x axis. But I don`t understand how.

Bromeon commented 2 years ago

Candle sticks can be easily implemented using BoxPlot with whisker_width = 0. Green/red can be set in the fill and stroke fields, depending on whether open < close or not.

In the long term, it might make sense to add a dedicated plot type, but the API for box-plots and bar-charts is relatively fresh and likely to evolve a bit depending on user feedback. So it might make sense to make these two more robust first.

emilk commented 2 years ago

I don't know what the difference is between the current "Box Plot" demo and candlesticks. Can you be more specific what is lacking?

Screen Shot 2022-04-16 at 22 02 29

mikael-nilsson-github commented 1 year ago

In case this may be helpful for others.

image

fn candlestick_chart(ui: &mut egui::Ui) {
    let red = Color32::from_rgb(255,0,0);
    let green = Color32::from_rgb(0,255,0);
    let mut data = BoxPlot::new(vec![
        BoxElem::new(1.0, BoxSpread::new(1.5, 2.2, 2.2, 2.6, 3.1)).whisker_width(0.0).fill(green).stroke(Stroke::new(2.0, green)),
        BoxElem::new(1.5, BoxSpread::new(1.5, 2.4, 2.4, 2.8, 3.5)).whisker_width(0.0).fill(green).stroke(Stroke::new(2.0, green)),
        BoxElem::new(2.0, BoxSpread::new(1.8, 2.0, 2.4, 2.5, 2.7)).whisker_width(0.0).fill(red).stroke(Stroke::new(2.0, red)),
        BoxElem::new(2.5, BoxSpread::new(1.5, 1.8, 1.8, 2.1, 2.2)).whisker_width(0.0).fill(red).stroke(Stroke::new(2.0, red)),
        BoxElem::new(3.0, BoxSpread::new(1.4, 1.6, 1.6, 1.8, 2.1)).whisker_width(0.0).fill(red).stroke(Stroke::new(2.0, red)),
        BoxElem::new(3.5, BoxSpread::new(0.5, 1.5, 1.5, 1.6, 1.7)).whisker_width(0.0).fill(red).stroke(Stroke::new(2.0, red)),
        BoxElem::new(4.0, BoxSpread::new(1.2, 1.4, 1.4, 2.9, 3.2)).whisker_width(0.0).fill(green).stroke(Stroke::new(2.0, green)),
        BoxElem::new(4.5, BoxSpread::new(2.1, 2.3, 2.3, 2.6, 2.7)).whisker_width(0.0).fill(green).stroke(Stroke::new(2.0, green)),
        BoxElem::new(5.0, BoxSpread::new(1.9, 2.1, 2.1, 2.7, 3.5)).whisker_width(0.0).fill(red).stroke(Stroke::new(2.0, red)),
        BoxElem::new(5.5, BoxSpread::new(2.0, 2.1, 2.1, 2.9, 3.3)).whisker_width(0.0).fill(green).stroke(Stroke::new(2.0, green)),
        BoxElem::new(6.0, BoxSpread::new(2.3, 2.9, 2.9, 3.7, 4.1)).whisker_width(0.0).fill(green).stroke(Stroke::new(2.0, green)),
        BoxElem::new(6.5, BoxSpread::new(3.1, 3.4, 3.4, 4.0, 4.2)).whisker_width(0.0).fill(red).stroke(Stroke::new(2.0, red)),
    ]);

    let plot = Plot::new("candlestick chart")
        .legend(Legend::default())
        .view_aspect(2.0);

    plot.show(ui, |plot_ui| {
            plot_ui.box_plot(data);
    });
}
olehbozhok commented 1 year ago

Thanks @mikael-nilsson-github this is good example. And need set custom label to x axis, need set info about time.

olehbozhok commented 1 year ago

I hope egui team make trait public

pub(super) trait RectElement

because I want to write an implementation with duplicate many of code BoxElem impl RectElement for BoxElem { }