ccharts 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/ccharts/extconf.rb +20 -0
- data/ext/ccharts/vendor/ccharts.h +3088 -0
- data/ext/ccharts/vendor/ccharts_abi.c +620 -0
- data/ext/ccharts/vendor/ccharts_abi.h +483 -0
- data/lib/ccharts/chart.rb +253 -0
- data/lib/ccharts/color.rb +46 -0
- data/lib/ccharts/ffi.rb +217 -0
- data/lib/ccharts/settings.rb +365 -0
- data/lib/ccharts/version.rb +7 -0
- data/lib/ccharts.rb +50 -0
- metadata +73 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ccharts
|
|
4
|
+
# Settings builders for each chart type. Every field is optional — unset
|
|
5
|
+
# fields take the C library's defaults (which is what the conformance suite
|
|
6
|
+
# checks byte-for-byte), and `plain` forces no ANSI escapes at all.
|
|
7
|
+
#
|
|
8
|
+
# Each builder has a {#to_ffi} that materialises the matching C struct and
|
|
9
|
+
# returns [struct, keepalive], where keepalive holds every backing
|
|
10
|
+
# Fiddle::Pointer (labels, color escapes, ...) alive across the render call.
|
|
11
|
+
module Settings
|
|
12
|
+
# line / candle
|
|
13
|
+
class ChartSettings
|
|
14
|
+
def initialize
|
|
15
|
+
@rise = @fall = @bg = @area = nil
|
|
16
|
+
@single_color = false
|
|
17
|
+
@show_prices = false
|
|
18
|
+
@show_times = false
|
|
19
|
+
@plain = false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def rise(v); @rise = v; self; end
|
|
23
|
+
def fall(v); @fall = v; self; end
|
|
24
|
+
def background(v); @bg = v; self; end
|
|
25
|
+
def area(v); @area = v; self; end
|
|
26
|
+
def single_color(v); @single_color = !!v; self; end
|
|
27
|
+
def show_prices(v); @show_prices = !!v; self; end
|
|
28
|
+
def show_times(v); @show_times = !!v; self; end
|
|
29
|
+
def plain(v); @plain = !!v; self; end
|
|
30
|
+
|
|
31
|
+
def to_ffi
|
|
32
|
+
s = FFI::Settings.malloc
|
|
33
|
+
keep = []
|
|
34
|
+
set = lambda do |field, val|
|
|
35
|
+
p = FFI.color_ptr(val, @plain)
|
|
36
|
+
keep << p
|
|
37
|
+
s[field] = p.to_i
|
|
38
|
+
end
|
|
39
|
+
set.call(:rise_color, @rise)
|
|
40
|
+
set.call(:fall_color, @fall)
|
|
41
|
+
set.call(:bg_color, @bg)
|
|
42
|
+
set.call(:area_color, @area)
|
|
43
|
+
s[:single_color] = @single_color ? 1 : 0
|
|
44
|
+
s[:show_prices] = @show_prices ? 1 : 0
|
|
45
|
+
s[:show_times] = @show_times ? 1 : 0
|
|
46
|
+
[s, keep]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# pie
|
|
51
|
+
class PieSettings
|
|
52
|
+
def initialize
|
|
53
|
+
@donut = false
|
|
54
|
+
@colors = nil
|
|
55
|
+
@show_legend = true
|
|
56
|
+
@show_pct = false
|
|
57
|
+
@slice_gap = 0.0
|
|
58
|
+
@inner_radius_ratio = -1.0
|
|
59
|
+
@legend_format = 0
|
|
60
|
+
@start_angle = -1.0
|
|
61
|
+
@counter_clockwise = false
|
|
62
|
+
@center_text = nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def donut(v); @donut = !!v; self; end
|
|
66
|
+
def colors(v); @colors = v; self; end
|
|
67
|
+
def show_legend(v); @show_legend = !!v; self; end
|
|
68
|
+
def show_pct(v); @show_pct = !!v; self; end
|
|
69
|
+
def slice_gap(v); @slice_gap = v; self; end
|
|
70
|
+
def inner_radius_ratio(v); @inner_radius_ratio = v; self; end
|
|
71
|
+
def legend_format(v); @legend_format = v; self; end
|
|
72
|
+
def start_angle(v); @start_angle = v; self; end
|
|
73
|
+
def counter_clockwise(v); @counter_clockwise = !!v; self; end
|
|
74
|
+
def center_text(v); @center_text = v; self; end
|
|
75
|
+
|
|
76
|
+
# Packed scalar arguments in ccharts_pie_from_slices order (the settings
|
|
77
|
+
# struct has no pie-specific fields; they are flat function arguments).
|
|
78
|
+
def _scalars
|
|
79
|
+
[@donut ? 1 : 0, @show_legend ? 1 : 0, @show_pct ? 1 : 0,
|
|
80
|
+
@slice_gap, @inner_radius_ratio, @legend_format, @start_angle,
|
|
81
|
+
@counter_clockwise ? 1 : 0]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def colors_count
|
|
85
|
+
@colors ? @colors.length : 0
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def center_text_ptr(keep)
|
|
89
|
+
return Fiddle::NULL if @center_text.nil?
|
|
90
|
+
p = FFI.cstr(@center_text)
|
|
91
|
+
keep << p
|
|
92
|
+
p
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Array of color escape pointers (index mod count), or Fiddle::NULL.
|
|
96
|
+
def colors_ptr(keep)
|
|
97
|
+
return Fiddle::NULL if @colors.nil? || @colors.empty?
|
|
98
|
+
ptrs = @colors.map do |c|
|
|
99
|
+
p = FFI.color_ptr(c, false)
|
|
100
|
+
keep << p
|
|
101
|
+
p
|
|
102
|
+
end
|
|
103
|
+
Fiddle::Pointer[ptrs.pack("Q*")]
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# histogram
|
|
108
|
+
class HistSettings
|
|
109
|
+
def initialize
|
|
110
|
+
@rise = nil
|
|
111
|
+
@bg = nil
|
|
112
|
+
@bin_count = 0
|
|
113
|
+
@min_value = Float::NAN
|
|
114
|
+
@max_value = Float::NAN
|
|
115
|
+
@show_bins = false
|
|
116
|
+
@show_prices = false
|
|
117
|
+
@plain = false
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def rise(v); @rise = v; self; end
|
|
121
|
+
def background(v); @bg = v; self; end
|
|
122
|
+
def bin_count(v); @bin_count = v; self; end
|
|
123
|
+
def min_value(v); @min_value = v; self; end
|
|
124
|
+
def max_value(v); @max_value = v; self; end
|
|
125
|
+
def show_bins(v); @show_bins = !!v; self; end
|
|
126
|
+
def show_prices(v); @show_prices = !!v; self; end
|
|
127
|
+
def plain(v); @plain = !!v; self; end
|
|
128
|
+
|
|
129
|
+
def to_ffi
|
|
130
|
+
s = FFI::HistSettings.malloc
|
|
131
|
+
keep = []
|
|
132
|
+
set = lambda do |field, val|
|
|
133
|
+
p = FFI.color_ptr(val, @plain)
|
|
134
|
+
keep << p
|
|
135
|
+
s[field] = p.to_i
|
|
136
|
+
end
|
|
137
|
+
set.call(:rise_color, @rise)
|
|
138
|
+
set.call(:bg_color, @bg)
|
|
139
|
+
s[:bin_count] = @bin_count
|
|
140
|
+
s[:min_value] = @min_value
|
|
141
|
+
s[:max_value] = @max_value
|
|
142
|
+
s[:show_bins] = @show_bins ? 1 : 0
|
|
143
|
+
s[:show_prices] = @show_prices ? 1 : 0
|
|
144
|
+
[s, keep]
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# sparkline
|
|
149
|
+
class SparkSettings
|
|
150
|
+
def initialize
|
|
151
|
+
@rise = nil
|
|
152
|
+
@area = nil
|
|
153
|
+
@min_above = 0
|
|
154
|
+
@min_below = 0
|
|
155
|
+
@plain = false
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def rise(v); @rise = v; self; end
|
|
159
|
+
def area(v); @area = v; self; end
|
|
160
|
+
def min_above(v); @min_above = v; self; end
|
|
161
|
+
def min_below(v); @min_below = v; self; end
|
|
162
|
+
def plain(v); @plain = !!v; self; end
|
|
163
|
+
|
|
164
|
+
def to_ffi
|
|
165
|
+
s = FFI::SparkSettings.malloc
|
|
166
|
+
keep = []
|
|
167
|
+
set = lambda do |field, val|
|
|
168
|
+
p = FFI.color_ptr(val, @plain)
|
|
169
|
+
keep << p
|
|
170
|
+
s[field] = p.to_i
|
|
171
|
+
end
|
|
172
|
+
set.call(:rise_color, @rise)
|
|
173
|
+
set.call(:area_color, @area)
|
|
174
|
+
s[:min_above] = @min_above
|
|
175
|
+
s[:min_below] = @min_below
|
|
176
|
+
[s, keep]
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# bar
|
|
181
|
+
class BarSettings
|
|
182
|
+
def initialize
|
|
183
|
+
@rise = nil
|
|
184
|
+
@bg = nil
|
|
185
|
+
@show_labels = false
|
|
186
|
+
@show_prices = false
|
|
187
|
+
@plain = false
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def rise(v); @rise = v; self; end
|
|
191
|
+
def background(v); @bg = v; self; end
|
|
192
|
+
def show_labels(v); @show_labels = !!v; self; end
|
|
193
|
+
def show_prices(v); @show_prices = !!v; self; end
|
|
194
|
+
def plain(v); @plain = !!v; self; end
|
|
195
|
+
|
|
196
|
+
def to_ffi
|
|
197
|
+
s = FFI::BarSettings.malloc
|
|
198
|
+
keep = []
|
|
199
|
+
set = lambda do |field, val|
|
|
200
|
+
p = FFI.color_ptr(val, @plain)
|
|
201
|
+
keep << p
|
|
202
|
+
s[field] = p.to_i
|
|
203
|
+
end
|
|
204
|
+
set.call(:rise_color, @rise)
|
|
205
|
+
set.call(:bg_color, @bg)
|
|
206
|
+
s[:show_labels] = @show_labels ? 1 : 0
|
|
207
|
+
s[:show_prices] = @show_prices ? 1 : 0
|
|
208
|
+
[s, keep]
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# stacked bar
|
|
213
|
+
class StackSettings
|
|
214
|
+
def initialize
|
|
215
|
+
@colors = nil
|
|
216
|
+
@bg = nil
|
|
217
|
+
@cat_labels = nil
|
|
218
|
+
@show_labels = false
|
|
219
|
+
@show_prices = false
|
|
220
|
+
@plain = false
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def colors(v); @colors = v; self; end
|
|
224
|
+
def background(v); @bg = v; self; end
|
|
225
|
+
def category_labels(v); @cat_labels = v; self; end
|
|
226
|
+
def show_labels(v); @show_labels = !!v; self; end
|
|
227
|
+
def show_prices(v); @show_prices = !!v; self; end
|
|
228
|
+
def plain(v); @plain = !!v; self; end
|
|
229
|
+
|
|
230
|
+
# inject the series/category counts known only at render time
|
|
231
|
+
def counts(series_count, cats_count)
|
|
232
|
+
@series_count = series_count
|
|
233
|
+
@cats_count = cats_count
|
|
234
|
+
self
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def to_ffi
|
|
238
|
+
s = FFI::StackSettings.malloc
|
|
239
|
+
keep = []
|
|
240
|
+
|
|
241
|
+
# NULL-terminated per-series color pointer array.
|
|
242
|
+
color_ptrs = []
|
|
243
|
+
if @plain
|
|
244
|
+
@series_count.times { color_ptrs << FFI::EMPTY.to_i }
|
|
245
|
+
elsif @colors && !@colors.empty?
|
|
246
|
+
@colors.each do |c|
|
|
247
|
+
p = FFI.color_ptr(c, false)
|
|
248
|
+
keep << p
|
|
249
|
+
color_ptrs << p.to_i
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
colors_addr = if color_ptrs.empty?
|
|
253
|
+
Fiddle::NULL
|
|
254
|
+
else
|
|
255
|
+
Fiddle::Pointer[(color_ptrs + [0]).pack("Q*")].to_i
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
bgp = FFI.color_ptr(@bg, @plain)
|
|
259
|
+
keep << bgp
|
|
260
|
+
|
|
261
|
+
cat_ptrs = []
|
|
262
|
+
if @cat_labels && !@cat_labels.empty?
|
|
263
|
+
@cat_labels.each do |l|
|
|
264
|
+
p = FFI.cstr(l)
|
|
265
|
+
keep << p
|
|
266
|
+
cat_ptrs << p.to_i
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
cat_addr = cat_ptrs.empty? ? Fiddle::NULL : Fiddle::Pointer[cat_ptrs.pack("Q*")].to_i
|
|
270
|
+
|
|
271
|
+
s.colors = colors_addr
|
|
272
|
+
s.bg_color = bgp.to_i
|
|
273
|
+
s.cat_labels = cat_addr
|
|
274
|
+
s.series = @series_count
|
|
275
|
+
s.cats = @cats_count
|
|
276
|
+
s.show_labels = @show_labels ? 1 : 0
|
|
277
|
+
s.show_prices = @show_prices ? 1 : 0
|
|
278
|
+
[s, keep]
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# heatmap
|
|
283
|
+
class HeatSettings
|
|
284
|
+
def initialize
|
|
285
|
+
@low = nil
|
|
286
|
+
@high = nil
|
|
287
|
+
@mid = nil
|
|
288
|
+
@bg = nil
|
|
289
|
+
@row_labels = nil
|
|
290
|
+
@col_labels = nil
|
|
291
|
+
@show_labels = false
|
|
292
|
+
@plain = false
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def low_color(v); @low = v; self; end
|
|
296
|
+
def high_color(v); @high = v; self; end
|
|
297
|
+
def mid_color(v); @mid = v; self; end
|
|
298
|
+
def background(v); @bg = v; self; end
|
|
299
|
+
def row_labels(v); @row_labels = v; self; end
|
|
300
|
+
def col_labels(v); @col_labels = v; self; end
|
|
301
|
+
def show_labels(v); @show_labels = !!v; self; end
|
|
302
|
+
def plain(v); @plain = !!v; self; end
|
|
303
|
+
|
|
304
|
+
def label_ptr_array(labels, keep)
|
|
305
|
+
return Fiddle::NULL if labels.nil? || labels.empty?
|
|
306
|
+
ptrs = labels.map do |l|
|
|
307
|
+
p = FFI.cstr(l)
|
|
308
|
+
keep << p
|
|
309
|
+
p.to_i
|
|
310
|
+
end
|
|
311
|
+
Fiddle::Pointer[ptrs.pack("Q*")]
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def to_ffi
|
|
315
|
+
s = FFI::HeatSettings.malloc
|
|
316
|
+
keep = []
|
|
317
|
+
set = lambda do |field, val|
|
|
318
|
+
p = FFI.color_ptr(val, @plain)
|
|
319
|
+
keep << p
|
|
320
|
+
s[field] = p.to_i
|
|
321
|
+
end
|
|
322
|
+
set.call(:low_color, @low)
|
|
323
|
+
set.call(:high_color, @high)
|
|
324
|
+
set.call(:mid_color, @mid)
|
|
325
|
+
set.call(:bg_color, @bg)
|
|
326
|
+
s[:row_labels] = label_ptr_array(@row_labels, keep).to_i
|
|
327
|
+
s[:col_labels] = label_ptr_array(@col_labels, keep).to_i
|
|
328
|
+
s[:show_labels] = @show_labels ? 1 : 0
|
|
329
|
+
[s, keep]
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# box plot
|
|
334
|
+
class BoxSettings
|
|
335
|
+
def initialize
|
|
336
|
+
@rise = nil
|
|
337
|
+
@area = nil
|
|
338
|
+
@bg = nil
|
|
339
|
+
@show_prices = false
|
|
340
|
+
@plain = false
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def rise(v); @rise = v; self; end
|
|
344
|
+
def area(v); @area = v; self; end
|
|
345
|
+
def background(v); @bg = v; self; end
|
|
346
|
+
def show_prices(v); @show_prices = !!v; self; end
|
|
347
|
+
def plain(v); @plain = !!v; self; end
|
|
348
|
+
|
|
349
|
+
def to_ffi
|
|
350
|
+
s = FFI::BoxSettings.malloc
|
|
351
|
+
keep = []
|
|
352
|
+
set = lambda do |field, val|
|
|
353
|
+
p = FFI.color_ptr(val, @plain)
|
|
354
|
+
keep << p
|
|
355
|
+
s[field] = p.to_i
|
|
356
|
+
end
|
|
357
|
+
set.call(:rise_color, @rise)
|
|
358
|
+
set.call(:area_color, @area)
|
|
359
|
+
set.call(:bg_color, @bg)
|
|
360
|
+
s[:show_prices] = @show_prices ? 1 : 0
|
|
361
|
+
[s, keep]
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
end
|
data/lib/ccharts.rb
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# ccharts — financial OHLC data as a string.
|
|
4
|
+
#
|
|
5
|
+
# Draws line, candlestick, pie/donut, histogram, sparkline, bar, stacked-bar,
|
|
6
|
+
# heatmap and box-plot charts with Unicode block characters and optional ANSI
|
|
7
|
+
# color. Ships the vendored C ABI (ext/ccharts/vendor) which is compiled from
|
|
8
|
+
# source by mkmf and driven through Fiddle, so the runtime is dependency-free.
|
|
9
|
+
#
|
|
10
|
+
# chart = Ccharts::Chart.from_arrays(open: [...], high: [...], low: [...], close: [...])
|
|
11
|
+
# puts chart.line(60, 8)
|
|
12
|
+
# puts Ccharts::Chart.pie([{ label: "A", value: 40 }, { label: "B", value: 60 }], 24, 10)
|
|
13
|
+
require_relative "ccharts/version"
|
|
14
|
+
require_relative "ccharts/color"
|
|
15
|
+
require_relative "ccharts/ffi"
|
|
16
|
+
require_relative "ccharts/settings"
|
|
17
|
+
require_relative "ccharts/chart"
|
|
18
|
+
|
|
19
|
+
require "fiddle"
|
|
20
|
+
|
|
21
|
+
module Ccharts
|
|
22
|
+
# Raised when the C layer reports a non-OK status, carrying the library's
|
|
23
|
+
# human-readable message.
|
|
24
|
+
class Error < StandardError
|
|
25
|
+
def self.for_status(status)
|
|
26
|
+
msg = FFI.read_cstr(FFI::ERROR_MSG.call(status)) || "unknown ccharts error"
|
|
27
|
+
new("#{msg} (status #{status})")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Raise if `status` is not CCHARTS_OK.
|
|
32
|
+
def self.raise_on(status)
|
|
33
|
+
return if status == 0
|
|
34
|
+
raise Error.for_status(status)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Version of the underlying C library.
|
|
38
|
+
def self.version
|
|
39
|
+
FFI.read_cstr(FFI::VERSION.call)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# CC_MAX_DIM / CC_MAX_CELLS limits exposed by the ABI.
|
|
43
|
+
def self.max_dim
|
|
44
|
+
FFI::MAX_DIM.call
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.max_cells
|
|
48
|
+
FFI::MAX_CELLS.call
|
|
49
|
+
end
|
|
50
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ccharts
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 3.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- ccharts contributors
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-08-25 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rake
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '13.0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '13.0'
|
|
27
|
+
description: A Ruby binding to the ccharts single-header C library. Turns OHLC / sample
|
|
28
|
+
data into text charts (line, candle, pie/donut, histogram, sparkline, bar, stacked
|
|
29
|
+
bar, heatmap, box plot). The vendored C ABI is compiled from source by mkmf and
|
|
30
|
+
driven through Fiddle, so there are no runtime dependencies beyond the Ruby standard
|
|
31
|
+
library.
|
|
32
|
+
email:
|
|
33
|
+
executables: []
|
|
34
|
+
extensions:
|
|
35
|
+
- ext/ccharts/extconf.rb
|
|
36
|
+
extra_rdoc_files: []
|
|
37
|
+
files:
|
|
38
|
+
- ext/ccharts/extconf.rb
|
|
39
|
+
- ext/ccharts/vendor/ccharts.h
|
|
40
|
+
- ext/ccharts/vendor/ccharts_abi.c
|
|
41
|
+
- ext/ccharts/vendor/ccharts_abi.h
|
|
42
|
+
- lib/ccharts.rb
|
|
43
|
+
- lib/ccharts/chart.rb
|
|
44
|
+
- lib/ccharts/color.rb
|
|
45
|
+
- lib/ccharts/ffi.rb
|
|
46
|
+
- lib/ccharts/settings.rb
|
|
47
|
+
- lib/ccharts/version.rb
|
|
48
|
+
homepage: https://github.com/dethrandir/ccharts
|
|
49
|
+
licenses:
|
|
50
|
+
- MIT
|
|
51
|
+
metadata: {}
|
|
52
|
+
post_install_message:
|
|
53
|
+
rdoc_options: []
|
|
54
|
+
require_paths:
|
|
55
|
+
- lib
|
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 2.7.0
|
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - ">="
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '0'
|
|
66
|
+
requirements: []
|
|
67
|
+
rubygems_version: 3.5.22
|
|
68
|
+
signing_key:
|
|
69
|
+
specification_version: 4
|
|
70
|
+
summary: Financial OHLC data as a string — line, candle, pie, histogram, sparkline,
|
|
71
|
+
bar, stacked-bar, heatmap and box-plot charts drawn with Unicode block characters
|
|
72
|
+
and optional ANSI color.
|
|
73
|
+
test_files: []
|