1use crate::tokens::DESIGN_TOKENS;
7use chrono::{DateTime, Utc};
8use egui::Color32;
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
13pub enum MarkerShape {
14 #[default]
16 Circle,
17 Square,
19 ArrowUp,
21 ArrowDown,
23 TriangleUp,
25 TriangleDown,
27 Diamond,
29 Star,
31 Cross,
33 Flag,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
39pub enum MarkerPos {
40 #[default]
42 AboveBar,
43 BelowBar,
45 InBar,
47 Top,
49 Bottom,
51 Left,
53 Right,
55 AbsoluteUp,
57 AbsoluteDown,
59 Absolute,
61 AtPriceTop,
63 AtPriceBottom,
65 AtPriceMiddle,
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
71pub enum MarkerZOrder {
72 #[default]
74 Normal,
75 AboveSeries,
77 Top,
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
83pub struct MarkerOptions {
84 pub auto_scale: bool,
88 pub z_order: MarkerZOrder,
90}
91
92impl Default for MarkerOptions {
93 fn default() -> Self {
94 Self {
95 auto_scale: true,
96 z_order: MarkerZOrder::default(),
97 }
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct Marker {
104 pub time: DateTime<Utc>,
106 pub position: MarkerPos,
108 pub shape: MarkerShape,
110 #[serde(default)]
113 pub color: Color32,
114 pub text: Option<String>,
116 pub tooltip: Option<String>,
118 pub size: f32,
120 pub id: Option<String>,
122 pub price: Option<f64>,
124}
125
126impl Marker {
127 pub fn new(time: DateTime<Utc>) -> Self {
129 Self {
130 time,
131 position: MarkerPos::default(),
132 shape: MarkerShape::default(),
133 color: Color32::PLACEHOLDER,
134 text: None,
135 tooltip: None,
136 size: 1.0,
137 id: None,
138 price: None,
139 }
140 }
141
142 #[must_use]
144 pub fn with_pos(mut self, position: MarkerPos) -> Self {
145 self.position = position;
146 self
147 }
148
149 #[must_use]
151 pub fn with_shape(mut self, shape: MarkerShape) -> Self {
152 self.shape = shape;
153 self
154 }
155
156 #[must_use]
158 pub fn with_color(mut self, color: Color32) -> Self {
159 self.color = color;
160 self
161 }
162
163 #[must_use]
165 pub fn with_text(mut self, text: impl Into<String>) -> Self {
166 self.text = Some(text.into());
167 self
168 }
169
170 #[must_use]
172 pub fn with_tooltip(mut self, tooltip: impl Into<String>) -> Self {
173 self.tooltip = Some(tooltip.into());
174 self
175 }
176
177 #[must_use]
179 pub fn with_size(mut self, size: f32) -> Self {
180 self.size = size;
181 self
182 }
183
184 #[must_use]
186 pub fn with_id(mut self, id: impl Into<String>) -> Self {
187 self.id = Some(id.into());
188 self
189 }
190
191 #[must_use]
193 pub fn at_price(mut self, price: f64, position: MarkerPos) -> Self {
194 self.price = Some(price);
195 self.position = position;
196 self
197 }
198
199 pub fn buy_signal(time: DateTime<Utc>) -> Self {
201 Self::new(time)
202 .with_shape(MarkerShape::ArrowUp)
203 .with_pos(MarkerPos::BelowBar)
204 .with_color(DESIGN_TOKENS.semantic.extended.bullish)
205 .with_text("BUY")
206 }
207
208 pub fn sell_signal(time: DateTime<Utc>) -> Self {
210 Self::new(time)
211 .with_shape(MarkerShape::ArrowDown)
212 .with_pos(MarkerPos::AboveBar)
213 .with_color(DESIGN_TOKENS.semantic.extended.bearish)
214 .with_text("SELL")
215 }
216
217 pub fn event(time: DateTime<Utc>, text: impl Into<String>) -> Self {
219 Self::new(time)
220 .with_shape(MarkerShape::Flag)
221 .with_pos(MarkerPos::AboveBar)
222 .with_color(DESIGN_TOKENS.semantic.extended.info)
223 .with_text(text)
224 }
225}
226
227#[derive(Debug, Clone, Copy, PartialEq)]
230pub struct ChangeMarkers {
231 pub up_color: Color32,
233 pub down_color: Color32,
235 pub duration: std::time::Duration,
239}
240
241impl Default for ChangeMarkers {
242 fn default() -> Self {
243 Self {
244 up_color: DESIGN_TOKENS.semantic.extended.bullish,
245 down_color: DESIGN_TOKENS.semantic.extended.bearish,
246 duration: std::time::Duration::from_secs(5),
247 }
248 }
249}
250
251#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash, Serialize, Deserialize)]
253pub enum LineStyle {
254 #[default]
256 Solid,
257 Dashed,
259 Dotted,
261 LargeDashed,
263 SparseDotted,
265}
266
267impl LineStyle {
268 #[inline]
271 pub fn dash_pattern(&self) -> Option<(f32, f32)> {
272 match self {
273 LineStyle::Solid => None,
274 LineStyle::Dashed => Some((8.0, 4.0)),
275 LineStyle::Dotted => Some((2.0, 3.0)),
276 LineStyle::LargeDashed => Some((16.0, 8.0)),
277 LineStyle::SparseDotted => Some((2.0, 8.0)),
278 }
279 }
280
281 #[cfg(feature = "widget")]
284 #[inline]
285 pub(crate) fn hairline_pattern(&self) -> Option<(f32, f32)> {
286 match self {
287 LineStyle::Solid => None,
288 LineStyle::Dashed => Some((4.0, 4.0)),
289 LineStyle::Dotted => Some((1.0, 3.0)),
290 LineStyle::LargeDashed => Some((8.0, 8.0)),
291 LineStyle::SparseDotted => Some((1.0, 7.0)),
292 }
293 }
294
295 pub fn all() -> &'static [LineStyle] {
297 &[
298 LineStyle::Solid,
299 LineStyle::Dashed,
300 LineStyle::Dotted,
301 LineStyle::LargeDashed,
302 LineStyle::SparseDotted,
303 ]
304 }
305
306 pub fn name(&self) -> &'static str {
308 match self {
309 LineStyle::Solid => "Solid",
310 LineStyle::Dashed => "Dashed",
311 LineStyle::Dotted => "Dotted",
312 LineStyle::LargeDashed => "Large dashed",
313 LineStyle::SparseDotted => "Sparse dotted",
314 }
315 }
316}
317
318#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
320pub struct PriceLine {
321 pub price: f64,
323 pub color: Color32,
325 pub width: f32,
327 pub style: LineStyle,
329 pub title: Option<String>,
331 pub axis_label: bool,
333 pub axis_label_color: Option<Color32>,
335 pub axis_label_text_color: Option<Color32>,
337 pub title_color: Option<Color32>,
339}
340
341impl PriceLine {
342 pub fn new(price: f64, color: Color32) -> Self {
344 Self {
345 price,
346 color,
347 width: 1.0,
348 style: LineStyle::Dashed,
349 title: None,
350 axis_label: true,
351 axis_label_color: None,
352 axis_label_text_color: None,
353 title_color: None,
354 }
355 }
356
357 #[must_use]
359 pub fn with_width(mut self, width: f32) -> Self {
360 self.width = width;
361 self
362 }
363
364 #[must_use]
366 pub fn with_style(mut self, style: LineStyle) -> Self {
367 self.style = style;
368 self
369 }
370
371 #[must_use]
373 pub fn with_title(mut self, title: impl Into<String>) -> Self {
374 self.title = Some(title.into());
375 self
376 }
377
378 #[must_use]
380 pub fn with_axis_label(mut self, show: bool) -> Self {
381 self.axis_label = show;
382 self
383 }
384
385 #[must_use]
387 pub fn with_axis_label_colors(mut self, fill: Color32, text: Color32) -> Self {
388 self.axis_label_color = Some(fill);
389 self.axis_label_text_color = Some(text);
390 self
391 }
392
393 #[must_use]
395 pub fn with_title_color(mut self, color: Color32) -> Self {
396 self.title_color = Some(color);
397 self
398 }
399}