-
-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathchart_renderer.rs
More file actions
136 lines (112 loc) · 4.57 KB
/
chart_renderer.rs
File metadata and controls
136 lines (112 loc) · 4.57 KB
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
use crate::{chart::CandleType, y_axis::YAxis, Candle, Chart};
use colored::*;
pub struct ChartRenderer {
pub bearish_color: (u8, u8, u8),
pub bullish_color: (u8, u8, u8),
}
impl ChartRenderer {
const UNICODE_VOID: char = ' ';
const UNICODE_BODY: char = '┃';
const UNICODE_HALF_BODY_BOTTOM: char = '╻';
const UNICODE_HALF_BODY_TOP: char = '╹';
const UNICODE_WICK: char = '│';
const UNICODE_TOP: char = '╽';
const UNICODE_BOTTOM: char = '╿';
const UNICODE_UPPER_WICK: char = '╷';
const UNICODE_LOWER_WICK: char = '╵';
pub const MARGIN_TOP: i64 = 3;
pub fn new() -> ChartRenderer {
#[cfg(target_os = "windows")]
{
if let Err(err) = control::set_virtual_terminal(true) {
eprintln!(
"Warning: Failed to enable virtual terminal processing: {}",
err
);
}
}
ChartRenderer {
bullish_color: (52, 208, 88),
bearish_color: (234, 74, 90),
}
}
fn colorize(&self, candle_type: &CandleType, string: &str) -> String {
let (ar, ag, ab) = self.bearish_color;
let (br, bg, bb) = self.bullish_color;
match candle_type {
CandleType::Bearish => format!("{}", string.truecolor(ar, ag, ab)),
CandleType::Bullish => format!("{}", string.truecolor(br, bg, bb)),
}
}
fn render_candle(&self, candle: &Candle, y: i32, y_axis: &YAxis) -> String {
let height_unit = y as f64;
let high_y = y_axis.price_to_height(candle.high);
let low_y = y_axis.price_to_height(candle.low);
let max_y = y_axis.price_to_height(candle.open.max(candle.close));
let min_y = y_axis.price_to_height(candle.close.min(candle.open));
let mut output = ChartRenderer::UNICODE_VOID;
if high_y.ceil() >= height_unit && height_unit >= max_y.floor() {
if max_y - height_unit > 0.75 {
output = ChartRenderer::UNICODE_BODY;
} else if (max_y - height_unit) > 0.25 {
if (high_y - height_unit) > 0.75 {
output = ChartRenderer::UNICODE_TOP;
} else {
output = ChartRenderer::UNICODE_HALF_BODY_BOTTOM;
}
} else if (high_y - height_unit) > 0.75 {
output = ChartRenderer::UNICODE_WICK;
} else if (high_y - height_unit) > 0.25 {
output = ChartRenderer::UNICODE_UPPER_WICK;
}
} else if max_y.floor() >= height_unit && height_unit >= min_y.ceil() {
output = ChartRenderer::UNICODE_BODY;
} else if min_y.ceil() >= height_unit && height_unit >= low_y.floor() {
if (min_y - height_unit) < 0.25 {
output = ChartRenderer::UNICODE_BODY;
} else if (min_y - height_unit) < 0.75 {
if (low_y - height_unit) < 0.25 {
output = ChartRenderer::UNICODE_BOTTOM;
} else {
output = ChartRenderer::UNICODE_HALF_BODY_TOP;
}
} else if low_y - height_unit < 0.25 {
output = ChartRenderer::UNICODE_WICK;
} else if low_y - height_unit < 0.75 {
output = ChartRenderer::UNICODE_LOWER_WICK;
}
}
let candle_type = candle.get_type();
self.colorize(&candle_type, &output.to_string())
}
pub fn render(&self, chart: &Chart) {
let mut output_str = "".to_owned();
let mut chart_data = chart.chart_data.borrow_mut();
chart_data.compute_height(&chart.volume_pane);
drop(chart_data);
let chart_data = chart.chart_data.borrow();
for y in (1..chart_data.height as u16).rev() {
output_str += "\n";
output_str += &chart.y_axis.render_line(y);
for candle in chart_data.visible_candle_set.candles.iter() {
output_str += &self.render_candle(candle, y.into(), &chart.y_axis);
}
}
if chart.volume_pane.enabled {
for y in (1..chart.volume_pane.height + 1).rev() {
output_str += "\n";
output_str += &chart.y_axis.render_empty();
for candle in chart_data.visible_candle_set.candles.iter() {
output_str += &chart.volume_pane.render(candle, y);
}
}
}
output_str += &chart.info_bar.render();
println!("{}", output_str)
}
}
impl Default for ChartRenderer {
fn default() -> Self {
Self::new()
}
}