use chrono::{Duration, Utc};
use egui_charts::ChartType;
use egui_charts::model::{Bar, BarData};
use egui_charts::theme::Theme;
use egui_charts::widget::Chart;
fn main() -> eframe::Result {
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_inner_size([1280.0, 720.0]),
..Default::default()
};
eframe::run_native(
"egui-charts: Basic Chart",
options,
Box::new(|_cc| Ok(Box::new(BasicChartApp::new()))),
)
}
struct BasicChartApp {
chart: Chart,
}
impl BasicChartApp {
fn new() -> Self {
let bars = generate_synthetic_bars(200, 100.0);
let data = BarData::from_bars(bars);
let mut chart = Chart::new(data);
chart.set_chart_type(ChartType::Candles);
chart.set_visible_bars(100);
chart.set_symbol("SYNTH");
chart.set_timeframe_label("1h");
Self { chart }
}
}
impl eframe::App for BasicChartApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let theme = Theme::dark();
egui_charts::theme::apply_to_egui(ctx, &theme);
egui::CentralPanel::default().show(ctx, |ui| {
self.chart.show(ui);
});
}
}
fn generate_synthetic_bars(count: usize, base_price: f64) -> Vec<Bar> {
use rand::RngExt;
let mut rng = rand::rng();
let mut bars = Vec::with_capacity(count);
let mut price = base_price;
let now = Utc::now();
let interval = Duration::hours(1);
for i in 0..count {
let change_pct = rng.random_range(-0.02_f64..0.02);
let close = price * (1.0 + change_pct);
let open = price;
let high = open.max(close) * (1.0 + rng.random_range(0.001..0.01));
let low = open.min(close) * (1.0 - rng.random_range(0.001..0.01));
let volume = 1000.0 + rng.random_range(0.0..5000.0) * (1.0 + change_pct.abs() * 10.0);
let time = now - interval * (count - i) as i32;
bars.push(Bar::new(time, open, high, low, close, volume));
price = close;
}
bars
}