react-native-vroom-chart 0.14.0 → 0.16.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.
Files changed (47) hide show
  1. package/cpp/VroomChartHostObject.cpp +289 -2
  2. package/cpp/_core_include/vroom/vroom_chart.h +221 -4
  3. package/cpp/_core_src/atr.cpp +67 -0
  4. package/cpp/_core_src/atr.h +44 -0
  5. package/cpp/_core_src/atr_pane.cpp +162 -0
  6. package/cpp/_core_src/atr_pane.h +48 -0
  7. package/cpp/_core_src/chart.cpp +477 -172
  8. package/cpp/_core_src/chart.h +173 -1
  9. package/cpp/_core_src/chart_facade.cpp +317 -23
  10. package/cpp/_core_src/fair_value_gaps.cpp +76 -0
  11. package/cpp/_core_src/fair_value_gaps.h +54 -0
  12. package/cpp/_core_src/footprints.cpp +226 -0
  13. package/cpp/_core_src/footprints.h +45 -0
  14. package/cpp/_core_src/footprints_layout.cpp +140 -0
  15. package/cpp/_core_src/footprints_layout.h +94 -0
  16. package/cpp/_core_src/fvg_overlay.cpp +262 -0
  17. package/cpp/_core_src/fvg_overlay.h +43 -0
  18. package/cpp/_core_src/ichimoku.cpp +65 -0
  19. package/cpp/_core_src/ichimoku.h +45 -0
  20. package/cpp/_core_src/labels.cpp +3 -0
  21. package/cpp/_core_src/line_morph.h +159 -0
  22. package/cpp/_core_src/ma_overlay.cpp +259 -36
  23. package/cpp/_core_src/ma_overlay.h +57 -2
  24. package/cpp/_core_src/macd.cpp +24 -1
  25. package/cpp/_core_src/macd.h +16 -0
  26. package/cpp/_core_src/macd_pane.cpp +71 -62
  27. package/cpp/_core_src/macd_pane.h +13 -1
  28. package/cpp/_core_src/pane_series.h +169 -0
  29. package/cpp/_core_src/rsi.cpp +4 -0
  30. package/cpp/_core_src/rsi.h +7 -0
  31. package/cpp/_core_src/rsi_pane.cpp +85 -29
  32. package/cpp/_core_src/rsi_pane.h +11 -1
  33. package/cpp/_core_src/tip_pulse.h +4 -4
  34. package/cpp/_core_src/viewport.h +35 -0
  35. package/lib/index.d.mts +385 -3
  36. package/lib/index.d.ts +385 -3
  37. package/lib/index.js +305 -7
  38. package/lib/index.js.map +1 -1
  39. package/lib/index.mjs +305 -7
  40. package/lib/index.mjs.map +1 -1
  41. package/package.json +1 -1
  42. package/src/VroomChart.tsx +108 -7
  43. package/src/dataTransitions.ts +47 -0
  44. package/src/index.ts +10 -0
  45. package/src/jsi.d.ts +136 -1
  46. package/src/types.ts +10 -0
  47. package/src/useChartCore.ts +330 -5
@@ -9,6 +9,7 @@
9
9
  #pragma once
10
10
 
11
11
  #include <chrono>
12
+ #include <cstddef>
12
13
  #include <string>
13
14
  #include <vector>
14
15
 
@@ -22,13 +23,33 @@
22
23
  #include "include/core/SkRefCnt.h"
23
24
  #pragma clang diagnostic pop
24
25
 
26
+ #include "fair_value_gaps.h"
27
+ #include "footprints_layout.h"
25
28
  #include "labels.h"
29
+ #include "line_morph.h"
26
30
  #include "price_format.h"
27
31
  #include "theme.h"
28
32
  #include "viewport.h"
29
33
 
30
34
  class SkCanvas;
31
35
 
36
+ namespace vroom {
37
+
38
+ // Which indicator owns a below-chart pane. Panes are otherwise
39
+ // interchangeable: they are all the same height and stack in enable order.
40
+ enum class PaneKind { Rsi, Macd, Atr };
41
+
42
+ // Count of PaneKind values — the most panes that can be stacked at once.
43
+ constexpr int kMaxPanes = 3;
44
+
45
+ // One enabled pane and the sequence number it claimed when it was turned on.
46
+ struct IndicatorPane {
47
+ int order;
48
+ PaneKind kind;
49
+ };
50
+
51
+ } // namespace vroom
52
+
32
53
  struct VroomChart {
33
54
  // --- bridge / lifecycle -------------------------------------------------
34
55
  VroomCallbacks cb{};
@@ -81,6 +102,19 @@ struct VroomChart {
81
102
  std::vector<vroom::CandleSnapshot> morph_from;
82
103
  float interval_morph_t = 1.f; // 1 = not morphing
83
104
  bool interval_morph_fade = false;
105
+ // Set when the capture came from a live update rather than a timeframe
106
+ // switch. Same slot machinery, but the axis holds still: a stream morph
107
+ // only reshapes the last bar, and the ticks it sits between don't move, so
108
+ // running them through the interval envelope would flash the whole axis on
109
+ // every tick (see labels::interval_phase).
110
+ bool morph_is_stream = false;
111
+ // The outgoing shape of every indicator series that was on screen, captured
112
+ // alongside the candles and keyed by identity so a toggle landing in the
113
+ // same commit as the switch can't pair two different lines (see
114
+ // line_morph.h). A timeframe switch invalidates every indicator cache at
115
+ // once, so without this the lines would pop to their new values while the
116
+ // candles under them reshape.
117
+ std::vector<vroom::LineMorph> morph_lines;
84
118
  // The pre-switch price scale and time window. The candle capture above is
85
119
  // normalized against these, and the axes keep rendering their old ticks from
86
120
  // them while fading out (see labels::interval_phase), so a label is never
@@ -122,7 +156,8 @@ struct VroomChart {
122
156
  VroomRSI rsi{0, 14, 70.0, 30.0, 14, 0, 1,
123
157
  0u, -1.f, 1, // RSI line
124
158
  0u, -1.f, // trendline
125
- 0u, 1}; // band rules
159
+ 0u, 1, // band rules
160
+ 1}; // extreme shading
126
161
  std::vector<double> rsi_cache; // RSI per candle (NaN where undefined)
127
162
  std::vector<double> rsi_ma_cache; // MA of rsi_cache (empty if MA off)
128
163
  bool rsi_dirty = true;
@@ -146,11 +181,23 @@ struct VroomChart {
146
181
  // default auto-fit amplitude; >1 zooms in, <1 zooms out. Anchored at zero.
147
182
  double macd_y_scale = 1.0;
148
183
 
184
+ // ATR, drawn in its own pane. atr_cache is aligned to `candles` (NaN
185
+ // warmup), recomputed lazily by ensure_atr() when atr_dirty.
186
+ // Defaults: 14-period true range under Wilder smoothing, style fields on
187
+ // their inherit sentinel.
188
+ VroomATR atr{0, 14, 0, 0u, -1.f};
189
+ std::vector<double> atr_cache;
190
+ bool atr_dirty = true;
191
+ // User y-axis zoom for the ATR pane (drag on its y-axis strip). 1.0 = the
192
+ // default 0..peak fit; >1 zooms in, <1 zooms out. Anchored at the baseline.
193
+ double atr_y_scale = 1.0;
194
+
149
195
  // Stacking order for the indicator panes: each indicator gets the next
150
196
  // sequence number on its off->on transition, so the most recently enabled
151
197
  // pane sorts last (bottom). -1 = not currently enabled.
152
198
  int rsi_order = -1;
153
199
  int macd_order = -1;
200
+ int atr_order = -1;
154
201
  int pane_seq = 0;
155
202
 
156
203
  // Moving-average overlay lines (SMA/EMA) drawn on the price pane. Not panes
@@ -182,6 +229,46 @@ struct VroomChart {
182
229
  std::vector<double> bb_lower_cache;
183
230
  bool bollinger_dirty = true;
184
231
 
232
+ // Ichimoku overlay (price pane; no pane reserved). Caches aligned to
233
+ // `candles` (NaN warmup) and indexed by the bar each value was computed
234
+ // from — displacement is applied when drawing, so the caches survive a
235
+ // change to it. Recomputed lazily by ensure_ichimoku() when ichimoku_dirty.
236
+ // Defaults: the standard 9/26/52/26, blue tenkan / red kijun, green span A
237
+ // over orange span B, teal chikou, 15% cloud.
238
+ VroomIchimoku ichimoku{0, 9, 26, 52, 26,
239
+ 0xff2962ff, 1.f, 1, // tenkan: blue
240
+ 0xffef5350, 1.f, 1, // kijun: red
241
+ 0xff26a69a, 1.f, 1, // senkou A: green
242
+ 0xffff6d00, 1.f, 1, // senkou B: orange
243
+ 0xff00bcd4, 1.f, 1, // chikou: teal
244
+ 1, 0xff26a69a, 0xffef5350, 0.15f};
245
+ std::vector<double> ich_tenkan_cache;
246
+ std::vector<double> ich_kijun_cache;
247
+ std::vector<double> ich_senkou_a_cache;
248
+ std::vector<double> ich_senkou_b_cache;
249
+ std::vector<double> ich_chikou_cache;
250
+ bool ichimoku_dirty = true;
251
+
252
+ // Fair Value Gap overlay (price pane; no pane reserved). The cache holds the
253
+ // detected imbalances in absolute time/price, oldest first, so box geometry
254
+ // and style are free to change without re-scanning — only the detection
255
+ // inputs below dirty it. Recomputed lazily by ensure_fvg() when fvg_dirty.
256
+ //
257
+ // Defaults: 300 bars back, close-settled fills, deleted once filled, 20-slot
258
+ // boxes in green/red at 15%, solid 1px border, labels on.
259
+ VroomFairValueGaps fvg{0, 300, 0, 0, 1, 0, 20,
260
+ 0xff26a69a, 0xffef5350, 0.15f,
261
+ 1, 0, 1.f, 0xff26a69a, 0xffef5350,
262
+ 1, nullptr, 10, 0u, 0.f,
263
+ 0, 0xff26a69a, 0xffef5350, nullptr};
264
+ // Owns the label texts, so the caller may free theirs as soon as the setter
265
+ // returns. `fvg.label` and `fvg.inverse_label` are left null and these are
266
+ // what the renderer reads.
267
+ std::string fvg_label = "FVG";
268
+ std::string fvg_inverse_label = "iFVG";
269
+ std::vector<vroom::fvg::Gap> fvg_cache;
270
+ bool fvg_dirty = true;
271
+
185
272
  // Volume bars (price pane, under the candles). On by default with every
186
273
  // style field left on its inherit sentinel, so an untouched chart looks
187
274
  // exactly as it did before the config existed. No cache — bar heights come
@@ -280,6 +367,28 @@ struct VroomChart {
280
367
  int32_t dragged_price_line = -1;
281
368
  double dragged_price_line_price = 0.0;
282
369
 
370
+ // --- footprints (executed-trade badges) ---------------------------------
371
+ // Kept in the *host's* order so the indices reported by
372
+ // vroom_chart_footprints_at map straight back to its own trade objects.
373
+ std::vector<VroomFootprint> footprints;
374
+ VroomFootprintStyle footprint_style{};
375
+
376
+ // Footprints grouped onto candles, which is what the renderer and hit-test
377
+ // actually walk. Derived from `footprints` + `candles`, so it is rebuilt
378
+ // lazily (see ensure_footprint_buckets) whenever either changes — that
379
+ // rebuild is what re-groups badges onto the right bars after an interval
380
+ // switch, with no involvement from the host.
381
+ std::vector<vroom::footprints::Bucket> footprint_buckets;
382
+ bool footprint_buckets_dirty = true;
383
+
384
+ // Which badge renders highlighted, keyed the way the hit-test reports it.
385
+ // side -1 = none.
386
+ int64_t hovered_footprint_time_ms = 0;
387
+ int32_t hovered_footprint_side = -1;
388
+
389
+ // Rebuilds footprint_buckets if either input changed since the last call.
390
+ void ensure_footprint_buckets();
391
+
283
392
  // --- theme --------------------------------------------------------------
284
393
  vroom::Theme theme;
285
394
 
@@ -325,6 +434,69 @@ struct VroomChart {
325
434
  // indicator is enabled.
326
435
  void ensure_bollinger();
327
436
 
437
+ // Recomputes the Ichimoku caches when ichimoku_dirty and the indicator is
438
+ // enabled.
439
+ void ensure_ichimoku();
440
+
441
+ // Redetects the Fair Value Gaps when fvg_dirty and the indicator is enabled.
442
+ void ensure_fvg();
443
+
444
+ // Recomputes the ATR cache when atr_dirty and the indicator is enabled.
445
+ void ensure_atr();
446
+
447
+ // Fills morph_lines with the outgoing shape of every enabled indicator,
448
+ // normalized the way morph_from is. Called by begin_interval_morph while
449
+ // the pre-switch candles and caches are still resident — after the swap
450
+ // there is nothing left to capture. `range` is the visible slice and
451
+ // `bounds` the price band the capture is taken against, both shared with
452
+ // the candle capture so the two land on the same pixels.
453
+ void capture_morph_lines(const vroom::Layout& lay,
454
+ const vroom::PriceBounds& bounds,
455
+ vroom::IndexRange range, int64_t window_ms);
456
+
457
+ // Source indices whose *displaced* plot time lands in the visible window,
458
+ // for an Ichimoku span drawn at `time_ms + shift_ms`. A bar of padding
459
+ // either side keeps a run reaching the pane edge instead of stopping at the
460
+ // last bar strictly inside it. Shared by the cloud, the lines and the
461
+ // interval-morph capture so all three slice the same bars.
462
+ vroom::IndexRange ichimoku_source_range(int64_t shift_ms) const;
463
+
464
+ // The enabled panes written to `out` top to bottom, returning how many.
465
+ // Both the draw pass and the y-axis hit test read this, so the stack they
466
+ // see can't drift apart.
467
+ int indicator_panes(vroom::IndicatorPane out[vroom::kMaxPanes]) const;
468
+
469
+ // Draws the pane stack into the band below the candles, starting at
470
+ // `pane_top`. Shared by the settled draw and the interval-morph fade, which
471
+ // paint the panes at different points in the z-order.
472
+ void draw_indicator_panes(SkCanvas* canvas, const vroom::Layout& lay,
473
+ const VroomCandle* visible, std::size_t n,
474
+ std::size_t first, int64_t window_ms,
475
+ float candle_right, float pane_top,
476
+ bool use_capture, float morph_t);
477
+
478
+ // The price-pane indicator overlays, split where the candles sit in the
479
+ // z-order: the Bollinger band and Ichimoku cloud go behind them, the moving
480
+ // averages, VWAP, Bollinger and Ichimoku lines over them.
481
+ //
482
+ // `use_capture` and `morph_t` carry the interval morph, on the same terms
483
+ // the candles take it. A transform pairs each series with its capture (see
484
+ // morph_lines) and eases toward the new shape. A fade's outgoing half
485
+ // passes n = 0 with morph_t = 0, replaying the capture alone. A settled
486
+ // frame passes no capture at all.
487
+ void draw_overlay_fills(SkCanvas* canvas, const vroom::Layout& lay,
488
+ const vroom::PriceBounds& bounds,
489
+ const VroomCandle* visible, std::size_t n,
490
+ std::size_t first, int64_t window_ms,
491
+ float candle_right, float candle_area_h,
492
+ bool use_capture, float morph_t);
493
+ void draw_overlay_lines(SkCanvas* canvas, const vroom::Layout& lay,
494
+ const vroom::PriceBounds& bounds,
495
+ const VroomCandle* visible, std::size_t n,
496
+ std::size_t first, int64_t window_ms,
497
+ float candle_right, float candle_area_h,
498
+ bool use_capture, float morph_t);
499
+
328
500
  // The main drawing pass. Calls into the labels and candles modules, and owns
329
501
  // the per-frame animation clock (see begin_frame) so every host gets it —
330
502
  // the web build draws straight through vroom_chart_draw rather than the