1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/// Marker API for custom chart annotations
///
/// Markers are visual indicators that can be placed at specific data points on the chart.
/// Common use cases: buy/sell signals, events, annotations, alerts, etc.
use crate::tokens::DESIGN_TOKENS;
use chrono::{DateTime, Utc};
use egui::Color32;
use serde::{Deserialize, Serialize};
/// Marker shape
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum MarkerShape {
/// Circle marker - filled circle
#[default]
Circle,
/// Square marker - filled square
Square,
/// Arrow up marker - points upward
ArrowUp,
/// Arrow down marker - points downward
ArrowDown,
/// Triangle up marker - points upward (hollow)
TriangleUp,
/// Triangle down marker - points downward (hollow)
TriangleDown,
/// Diamond marker - filled diamond shape
Diamond,
/// Star marker
Star,
/// Cross marker (X shape)
Cross,
/// Flag marker - for marking important events
Flag,
}
/// Marker position relative to the data point
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum MarkerPos {
/// Above the high price
#[default]
AboveBar,
/// Below the low price
BelowBar,
/// At the data point (on the candle/bar)
InBar,
/// At the top of the chart pane
Top,
/// At the bottom of the chart pane
Bottom,
/// At the left edge of the chart
Left,
/// At the right edge of the chart
Right,
/// Absolute pixel position (up arrow)
AbsoluteUp,
/// Absolute pixel position (down arrow)
AbsoluteDown,
/// Absolute pixel position (centered)
Absolute,
}
/// Marker for chart annotations
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Marker {
/// Time of the marker (matches a data point)
pub time: DateTime<Utc>,
/// Pos relative to the bar
pub position: MarkerPos,
/// Shape of the marker
pub shape: MarkerShape,
/// Color of the marker
#[serde(skip)]
pub color: Color32,
/// Optional text label
pub text: Option<String>,
/// Optional tooltip (shown on hover)
pub tooltip: Option<String>,
/// Size multiplier (1.0 = normal size)
pub size: f32,
/// Unique ID for the marker (for removal/editing)
pub id: Option<String>,
}
impl Marker {
/// Create a new marker at the given time
pub fn new(time: DateTime<Utc>) -> Self {
Self {
time,
position: MarkerPos::default(),
shape: MarkerShape::default(),
color: Color32::WHITE,
text: None,
tooltip: None,
size: 1.0,
id: None,
}
}
/// Set the position
#[must_use]
pub fn with_pos(mut self, position: MarkerPos) -> Self {
self.position = position;
self
}
/// Set the shape
#[must_use]
pub fn with_shape(mut self, shape: MarkerShape) -> Self {
self.shape = shape;
self
}
/// Set the color
#[must_use]
pub fn with_color(mut self, color: Color32) -> Self {
self.color = color;
self
}
/// Set the text label
#[must_use]
pub fn with_text(mut self, text: impl Into<String>) -> Self {
self.text = Some(text.into());
self
}
/// Set the tooltip
#[must_use]
pub fn with_tooltip(mut self, tooltip: impl Into<String>) -> Self {
self.tooltip = Some(tooltip.into());
self
}
/// Set the size
#[must_use]
pub fn with_size(mut self, size: f32) -> Self {
self.size = size;
self
}
/// Set the ID
#[must_use]
pub fn with_id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
}
/// Quick constructor for a buy signal marker (green arrow up)
pub fn buy_signal(time: DateTime<Utc>) -> Self {
Self::new(time)
.with_shape(MarkerShape::ArrowUp)
.with_pos(MarkerPos::BelowBar)
.with_color(DESIGN_TOKENS.semantic.extended.bullish)
.with_text("BUY")
}
/// Quick constructor for a sell signal marker (red arrow down)
pub fn sell_signal(time: DateTime<Utc>) -> Self {
Self::new(time)
.with_shape(MarkerShape::ArrowDown)
.with_pos(MarkerPos::AboveBar)
.with_color(DESIGN_TOKENS.semantic.extended.bearish)
.with_text("SELL")
}
/// Quick constructor for an event marker (blue flag)
pub fn event(time: DateTime<Utc>, text: impl Into<String>) -> Self {
Self::new(time)
.with_shape(MarkerShape::Flag)
.with_pos(MarkerPos::AboveBar)
.with_color(DESIGN_TOKENS.semantic.extended.info)
.with_text(text)
}
}