PineForge unreleased
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
ta.hpp
Go to the documentation of this file.
1#pragma once
2#include "na.hpp"
3#include "series.hpp"
4#include "window_sum.hpp"
5#include <deque>
6#include <cmath>
7#include <vector>
8#include <string>
9
10namespace pineforge {
11
12namespace ta {
13
14// How an ``EMA`` seeds its recursion. A per-instance option
15// (``EMA(length, seeding)``); an instance that names none latches the
16// ambient default below on its first ``compute()``.
17enum class EmaSeeding : unsigned char {
18 // ``ema := src`` on the first finite input, so the output is never na.
19 // The default, and byte-identical to every EMA before the option existed.
21 // na until ``length`` finite inputs have accumulated, then their simple
22 // average, then the ordinary recursion: an SMA-seeded EMA, warming up the
23 // way ``RMA`` and ``SMA`` already do (na for the whole warm-up window).
25};
26
27// Ambient default seeding for ``EMA`` instances constructed without one
28// (thread-local; ``false`` = ``EmaSeeding::FirstValue``, ``true`` =
29// ``EmaSeeding::SimpleAverage``; default ``false``).
30//
31// An instance reads it once, on its first ``compute()``, and keeps that
32// seeding for life, so a host that wants the instances of one evaluation
33// context SMA-seeded without naming the seeding at each construction raises
34// the reference around that context and restores it on exit (an RAII scope;
35// the restore must also run during unwinding). Thread-local so parallel
36// in-process engines never cross-contaminate. Nothing in the kernel raises
37// it: with the default, every EMA that names no seeding is the first-value
38// recursion, byte-identical to the behaviour before the option existed.
40
41// Per-context bar index for bar-addressed window state (thread-local).
42//
43// TradingView keeps the source history of a window call site (``ta.highest``,
44// ``ta.lowest``, ``ta.highestbars``, ``ta.lowestbars``) in a ring of
45// ``K = length + 1`` slots addressed by ``bar_index % K``. A call on bar ``b``
46// writes ``slot[b % K] = src`` and returns the extremum over the WRITTEN slots
47// ``(b - k) % K``, ``k in [0, length)``. For a call that executes every bar
48// that is the plain positional window. For a call that executes
49// CONDITIONALLY (inside an ``if`` block that does not run every bar) the slots
50// not rewritten keep their stale values from earlier executions, never-written
51// slots are skipped, and the result is na iff ``bar_index < length - 1`` — NOT
52// until ``length`` executions have accumulated. Pinned 2026-09-03 with
53// ``lab tv`` on NYSE:F 1D (``if bar_index % 7 == 3: v = ta.highest(high, 5)``
54// 39/39 entry sizes exact, cadence 9 30/30; a third-party SMA strategy on
55// F@1D 31/31 only with K = 6). ``ta.sma`` inside ``if`` is NOT ring-addressed
56// (per-execution buffer, pinned separately) and is untouched.
57//
58// The engine installs the executing context's bar index around every dispatch
59// of generated code: the chart's Pine ``bar_index`` around ``on_bar`` and the
60// requested context's evaluated-bar index around each ``evaluate_security``
61// (HTF / lower-tf / auxiliary feeds). ``origin`` is the first bar index the
62// context has data for — the warmup reference — so a feed that starts after
63// TradingView's hidden first chart bar (``bar_index_offset``) still warms up
64// over its own first ``length`` bars, exactly as before. With no context
65// installed (the default — unit tests, standalone use) every ``compute()`` is
66// its own bar and the objects are byte-identical to the previous positional
67// deque.
68//
69// The ring is read through a cached extremum with an implied bar. Each call
70// site keeps ``{value, bar}``: the first call caches ``(src, b)``; a call on
71// bar ``b`` with ``b - bar < length`` only compares ``src`` against the cache
72// (strict — ties never displace the cached member); the new-extremum test
73// comes FIRST, so a bar whose ``src`` beats the cache takes it without
74// reading the slots even when the cache has aged out; otherwise, once the
75// cached extremum has aged out (``b - bar >= length`` — by bars, not calls)
76// the slots are rescanned, oldest first, and the cache becomes
77// ``(best, b - k_best)``; otherwise the cache is kept. The output is the
78// cached value (the *Bars offset is ``b - bar``). Pinned 2026-09-04 with 8
79// ``lab tv`` tapes on NYSE:F 1D (696/696 entries), the BINANCE:ETHUSDT.P
80// geometry pin (82/82) and a third-party BBWP ETH replay (593/593):
81// ``m = bar_index % 49; if m < 4 or 37 <= m < 47 or m == 48: v =
82// ta.lowest(low, 10)`` can answer synthetic 25.00 from bar 42 on bars 48..51
83// although bar 3's stale 24.00 sits one slot behind bar 48 — the plain ring
84// would say 24.00 — and rescans to 24.00 on bar 52 once the cache has aged;
85// a synthetic ETH run-start low of 2000.00 below an expired cache of 2010.00
86// answers its own low and never reads the aliased slot the plain ring
87// returned. For an every-bar caller the cache is exactly the positional
88// window, so nothing changes there.
89//
90// Never-written slots read 0 in a rescan, for every source kind (pinned
91// 2026-09-04 on BINANCE:BTCUSDT 1D and OANDA:XAUUSD 1D, cadence 13 / length
92// 10: ``low``, ``close - 2000``, ``sma(close, 5)``, ``low[1]``, ``hl2`` and
93// the sign-mixed ``sma(close, 5) - close`` each 13/13). A slot WRITTEN with
94// na POISONS the ring (pinned 2026-09-04 on OANDA:XAUUSD 1D, scratchpad
95// r6/pins/ringkind: leading-na sites 7 x 13/13, the market-logic replica
96// 32/32; and the every-bar NYSE:F 1D gap tape pin-lowest-na-everybar, 20/20;
97// ledger log-20260904t112527z-ea13dfcd): the rescan walks oldest first and a
98// written-na slot resets the running extremum, so the answer is the extremum
99// over the slots NEWER than the newest na slot in the window (never-written
100// 0 slots among them included) and na when the newest slot is itself na; the
101// na write also poisons the cache to ``(na, b)``, so the next valid call
102// restarts from its own src without reading the slots. ``ta.lowest(
103// sma(close, 14), 10)`` at cadence 13 can answer na (bar 5 writes na), then 2000
104// (bar 18: restart on src, the never-written slot behind it unread), 0, 0,
105// 0, 0 (rescans: never-written slots newer than the na slot), 2200 (bar
106// 83: the na slot re-entered at k = 1, src is the only live member), 2100
107// (new minimum), 2000, 2000, 2000, 2000 (the stale first valid write, once
108// newer than the na slot), 2050. Every-bar ``x = bar_index % 4 == 0 ? na :
109// low``: ``ta.lowest(x, 5) == ta.highest(x, 5)`` on the bar after every na
110// bar — a single live member — where the old "skip the gap" reading kept
111// the pre-gap extremum (synthetic bar 9: 25.00, the untouched cache 24.00).
113 bool installed = false;
114 long long bar_index = 0; // ring address: the context's current bar index
115 long long origin = 0; // warmup reference: the context's first bar index
116 // All retained fields are inline scalars (or scalar-only aggregates).
117 void observe_owned_storage(OwnedStorage&) const noexcept {}
118};
120
121// RAII installer: sets the thread-local BarContext for the enclosed dispatch
122// and restores the previous one on exit (also during stack unwinding), so
123// chart and request.security evaluation never see each other's index.
125 BarContext previous_;
126
127public:
128 BarContextScope(long long bar_index, long long origin);
132public:
133 // All retained fields are inline scalars (or scalar-only aggregates).
134 void observe_owned_storage(OwnedStorage&) const noexcept {}
135};
136
137// Bar-addressed extremum ring shared by Highest / Lowest / HighestBars /
138// LowestBars — the TradingView rule documented at bar_context() above.
140public:
141 struct Result {
142 double value; // na: window not formed yet, or no written non-na member
143 int bars_back; // k of the extremum slot (0 = the current bar)
144 };
146 // advance = true -> compute(): records src for the context's current bar
147 // advance = false -> recompute(): rewrites the current bar's slot
148 // An na src is WRITTEN: it answers na, poisons the cache and, in every
149 // later rescan, resets the running extremum (the poison rule documented
150 // at bar_context()). The composites (Stoch, WPR, Range) share the ring
151 // and the rule: their only oracle (finding 331, a stochRSI whose RSI is
152 // na for its warmup only) is a leading-na series, on which the poison
153 // answers exactly what "live over the non-na members" did.
154 // Ties resolve to the OLDEST member (strict comparison, oldest slot first).
155 Result update(double src, bool advance, bool want_max);
156 WindowCacheStats cache_stats() const { return values_.cache_stats(); }
157
158private:
159 int length_;
160 // Unwritten slots read zero; writing na stores that poison explicitly.
162 long long own_bar_ = -1; // cadence when no context is installed
163 bool has_written_ = false;
164 // TradingView's cached extremum with an implied bar (bar_context() docs):
165 // the value the site last answered and the bar it is attributed to.
166 bool cached_ = false;
167 double cval_ = 0.0;
168 long long cbar_ = 0;
169 // The cache as it stood BEFORE the current bar's first tick, so a
170 // recompute() (same bar, advance=false) restores it and re-applies.
171 long long cache_seen_bar_ = -1;
172 bool saved_cached_ = false;
173 double saved_cval_ = 0.0;
174 long long saved_cbar_ = 0;
175public:
176 void observe_owned_storage(OwnedStorage& out) const noexcept {
177 observe_owned_members(out, values_);
178 }
179};
180
181class RMA {
182 double output_val;
183 double sum;
184 int length;
185 int bar_count;
186
187 // saved state for recompute
188 double saved_output_val_;
189 double saved_sum_;
190 int saved_bar_count_;
191
192public:
193 explicit RMA(int length);
194 double compute(double src);
195 void save();
196 void restore();
197 double recompute(double src);
198public:
199 // All retained fields are inline scalars (or scalar-only aggregates).
200 void observe_owned_storage(OwnedStorage&) const noexcept {}
201};
202
203class RSI {
204 RMA rma_up;
205 RMA rma_down;
206 double prev_src;
207 int bar_count;
208
209 // saved state for recompute
210 double saved_prev_src_;
211 int saved_bar_count_;
212
213public:
214 explicit RSI(int length);
215 double compute(double src);
216 double recompute(double src);
217public:
218 void observe_owned_storage(OwnedStorage& out) const noexcept {
219 observe_owned_members(out, rma_up, rma_down);
220 }
221};
222
224 double prev_a;
225 double prev_b;
226
227 double saved_prev_a_, saved_prev_b_;
228
229public:
231 bool compute(double a, double b);
232 bool recompute(double a, double b);
233public:
234 // All retained fields are inline scalars (or scalar-only aggregates).
235 void observe_owned_storage(OwnedStorage&) const noexcept {}
236};
237
239 double prev_a;
240 double prev_b;
241
242 double saved_prev_a_, saved_prev_b_;
243
244public:
246 bool compute(double a, double b);
247 bool recompute(double a, double b);
248public:
249 // All retained fields are inline scalars (or scalar-only aggregates).
250 void observe_owned_storage(OwnedStorage&) const noexcept {}
251};
252
253// --- SMA ---
254
255class SMA {
256 KahanWindowSum window_;
257 int length;
258 int bar_count;
259
260public:
261 explicit SMA(int length);
262 double compute(double src);
263 double recompute(double src);
264public:
265 void observe_owned_storage(OwnedStorage& out) const noexcept {
266 observe_owned_members(out, window_);
267 }
268};
269
270// --- EMA ---
271
272class EMA {
273 double output_val;
274 double alpha;
275 double sum;
276 int bar_count;
277 // Read only by EmaSeeding::SimpleAverage, which counts `length` finite
278 // inputs before seeding with their mean. The FirstValue recursion uses
279 // `alpha` alone and never reads this.
280 int length_;
281
282 // saved state for recompute
283 double saved_output_val_;
284 double saved_sum_;
285 int saved_bar_count_;
286
287 // The instance's seeding (true = EmaSeeding::SimpleAverage): named by the
288 // two-argument constructor, or latched from ema_na_warmup_flag() on the
289 // first compute() and never revisited, so recompute()'s restore() (which
290 // only rewinds output_val/sum/bar_count) cannot flip the seeding
291 // mid-series. Deliberately NOT part of save()/restore().
292 bool na_warmup_ = false;
293 bool warmup_latched_ = false;
294
295public:
296 explicit EMA(int length);
297 // Names the seeding at construction; the ambient default is never read.
298 EMA(int length, EmaSeeding seeding);
299 double compute(double src);
300 void save();
301 void restore();
302 double recompute(double src);
303public:
304 // All retained fields are inline scalars (or scalar-only aggregates).
305 void observe_owned_storage(OwnedStorage&) const noexcept {}
306};
307
308// --- MACD ---
309
311 double macd_line;
313 double histogram;
314 // All retained fields are inline scalars (or scalar-only aggregates).
315 void observe_owned_storage(OwnedStorage&) const noexcept {}
316};
317
318class MACD {
319 EMA fast_ema;
320 EMA slow_ema;
321 EMA signal_ema;
322
323public:
324 MACD(int fast_length, int slow_length, int signal_length);
325 MACDResult compute(double src);
327public:
328 void observe_owned_storage(OwnedStorage& out) const noexcept {
329 observe_owned_members(out, fast_ema, slow_ema, signal_ema);
330 }
331};
332
333// --- Highest ---
334
335class Highest {
336 ExtremeRing ring_;
337
338public:
339 explicit Highest(int length);
340 double compute(double src);
341 double recompute(double src);
342public:
343 void observe_owned_storage(OwnedStorage& out) const noexcept {
344 observe_owned_members(out, ring_);
345 }
346};
347
348// --- Lowest ---
349
350class Lowest {
351 ExtremeRing ring_;
352
353public:
354 explicit Lowest(int length);
355 double compute(double src);
356 double recompute(double src);
357public:
358 void observe_owned_storage(OwnedStorage& out) const noexcept {
359 observe_owned_members(out, ring_);
360 }
361};
362
363// --- ATR ---
364
365class ATR {
366 RMA rma;
367 double prev_close;
368 int bar_count;
369
370 double saved_prev_close_;
371 int saved_bar_count_;
372
373public:
374 explicit ATR(int length);
375 double compute(double high, double low, double close);
376 double recompute(double high, double low, double close);
377 // issue #178 (pinned 2026-09-06, lab tv i178-sparse-atr-sense,
378 // BINANCE:BTCUSDT 60, 398/398 executions): TradingView's ta.atr called
379 // inside a block that does not execute every bar advances its RMA on
380 // the EXECUTIONS only, but the true range always reads the previous
381 // CHART bar's close (close[1]), never the close of the previous
382 // execution. The 3-arg path keeps the per-call prev_close for callers
383 // that run every bar (identical there); a sparse call site must pass
384 // the chart's previous close (BacktestEngine::prev_chart_close()).
385 double compute(double high, double low, double close, double prev_chart_close);
386 double recompute(double high, double low, double close, double prev_chart_close);
387public:
388 void observe_owned_storage(OwnedStorage& out) const noexcept {
389 observe_owned_members(out, rma);
390 }
391};
392
393// --- Stoch ---
394
395class Stoch {
396 Highest highest;
397 Lowest lowest;
398
399public:
400 explicit Stoch(int length);
401 double compute(double src, double high, double low);
402 double recompute(double src, double high, double low);
403public:
404 void observe_owned_storage(OwnedStorage& out) const noexcept {
405 observe_owned_members(out, highest, lowest);
406 }
407};
408
409// --- Change ---
410
411class Change {
412 OwnedDeque<double> history;
413 int max_length_;
414
415public:
416 explicit Change(int max_length = 1);
417 double compute(double src, int length = 1);
418 double recompute(double src, int length = 1);
419public:
420 void observe_owned_storage(OwnedStorage& out) const noexcept {
421 observe_owned_members(out, history);
422 }
423};
424
425// --- Cross ---
426
427class Cross {
428 double prev_a;
429 double prev_b;
430 // Skip-tie state: TV's `ta.cross` tracks the last NON-TIED sign of
431 // (a - b) so that intermediate "tied" bars (a == b) are transparent.
432 // ta.crossover/ta.crossunder use the simpler immediate-prev rule and
433 // need no skip-tie state.
434 int last_nonzero_sign_; // -1, 0 (uninitialised), +1
435
436 double saved_prev_a_, saved_prev_b_;
437 int saved_last_nonzero_sign_;
438
439public:
441 bool compute(double a, double b);
442 bool recompute(double a, double b);
443public:
444 // All retained fields are inline scalars (or scalar-only aggregates).
445 void observe_owned_storage(OwnedStorage&) const noexcept {}
446};
447
448// --- WMA (Weighted Moving Average) ---
449
450class WMA {
451 int length_;
452 // Ring buffer (capacity == length_) instead of std::deque to avoid
453 // per-bar node allocation. Newest sample at offset 0, oldest at
454 // offset length_-1. The per-bar O(length) weighted-sum recompute is
455 // unchanged — see WMA::compute for the oldest→newest weight 1..length
456 // accumulation order that parity depends on.
458
459public:
460 explicit WMA(int length, WindowCacheCapacity cache = window_cache_capacity());
461 double compute(double src);
462 double recompute(double src);
463 WindowCacheStats cache_stats() const { return buffer_.cache_stats(); }
464public:
465 void observe_owned_storage(OwnedStorage& out) const noexcept {
466 observe_owned_members(out, buffer_);
467 }
468};
469
470// --- HMA (Hull Moving Average) ---
471
472class HMA {
473 WMA wma_half_;
474 WMA wma_full_;
475 WMA wma_sqrt_;
476
477public:
478 explicit HMA(int length);
479 double compute(double src);
480 double recompute(double src);
481public:
482 void observe_owned_storage(OwnedStorage& out) const noexcept {
483 observe_owned_members(out, wma_half_, wma_full_, wma_sqrt_);
484 }
485};
486
487// --- StdDev (Standard Deviation) ---
488// TradingView's ta.stdev (biased, the default) is NOT the two-pass
489// sum-of-squared-deviations of its documentation: it is
490// sqrt(Sxx / n - m * m), m = Sx / n,
491// with Sx = math.sum(src, n) and Sxx = math.sum(src * src, n) the same
492// sliding-window Kahan sums as ta.sma (window_sum.hpp) -- so the value carries
493// the cancellation error of that form and of those running sums. Pinned
494// 2026-09-05 (round 9, family W) on a full-precision NYSE:F@15 oracle
495// (pineforge-workflow famw-f15-sd-*: 7,029/7,029 bars bit-exact; the
496// two-pass form is exact on none of them). The unbiased variant
497// (biased = false) is unpinned and keeps the two-pass window arithmetic.
498class StdDev {
499 int length_;
500 bool biased_;
501 OwnedDeque<double> buffer_; // unbiased path only
502 KahanWindowSum sum_x_; // Sx (biased path)
503 KahanWindowSum sum_xx_; // Sxx (biased path)
504 int bar_count_;
505
506public:
507 explicit StdDev(int length, bool biased = true);
508 double compute(double src);
509 double recompute(double src);
510
511private:
512 double held_stdev() const;
513 double biased_value() const;
514public:
515 void observe_owned_storage(OwnedStorage& out) const noexcept {
516 observe_owned_members(out, buffer_, sum_x_, sum_xx_);
517 }
518};
519
520// --- Supertrend ---
521
523 double value;
524 double direction;
525 // All retained fields are inline scalars (or scalar-only aggregates).
526 void observe_owned_storage(OwnedStorage&) const noexcept {}
527};
528
530 double factor_;
531 ATR atr_;
532 double prev_upper_, prev_lower_, prev_st_;
533 double prev_direction_;
534 double prev_close_;
535 bool initialized_;
536
537 // saved state
538 double saved_prev_upper_, saved_prev_lower_, saved_prev_st_;
539 double saved_prev_direction_, saved_prev_close_;
540 bool saved_initialized_;
541
542public:
543 Supertrend(double factor, int atr_period);
544 SupertrendResult compute(double high, double low, double close);
545 SupertrendResult recompute(double high, double low, double close);
546
547private:
548 SupertrendResult step(double high, double low, double close, bool again);
549public:
550 void observe_owned_storage(OwnedStorage& out) const noexcept {
551 observe_owned_members(out, atr_);
552 }
553};
554
555// --- DMI (Directional Movement Index) ---
556
557struct DMIResult {
558 double diplus;
559 double diminus;
560 double adx;
561 // All retained fields are inline scalars (or scalar-only aggregates).
562 void observe_owned_storage(OwnedStorage&) const noexcept {}
563};
564
565class DMI {
566 RMA rma_plus_, rma_minus_, rma_tr_;
567 RMA rma_adx_;
568 double prev_high_, prev_low_, prev_close_;
569 bool first_bar_;
570
571 // saved state
572 double saved_prev_high_, saved_prev_low_, saved_prev_close_;
573 bool saved_first_bar_;
574
575public:
576 DMI(int di_length, int adx_smoothing);
577 DMIResult compute(double high, double low, double close);
578 DMIResult recompute(double high, double low, double close);
579public:
580 void observe_owned_storage(OwnedStorage& out) const noexcept {
581 observe_owned_members(out, rma_plus_, rma_minus_, rma_tr_, rma_adx_);
582 }
583};
584
585// --- SAR (Parabolic SAR) ---
586
587class SAR {
588 double start_, increment_, maximum_;
589 double af_, ep_, sar_;
590 bool is_long_;
591 bool initialized_;
592 double prev_high_, prev_low_, prev_close_;
593 double prev_prev_high_, prev_prev_low_;
594
595 // saved state
596 double saved_af_, saved_ep_, saved_sar_;
597 bool saved_is_long_, saved_initialized_;
598 double saved_prev_high_, saved_prev_low_, saved_prev_close_;
599 double saved_prev_prev_high_, saved_prev_prev_low_;
600
601public:
602 SAR(double start, double increment, double maximum);
603 double compute(double high, double low, double close);
604 double recompute(double high, double low, double close);
605public:
606 // All retained fields are inline scalars (or scalar-only aggregates).
607 void observe_owned_storage(OwnedStorage&) const noexcept {}
608};
609
610// --- BB (Bollinger Bands) ---
611
612struct BBResult {
613 double middle;
614 double upper;
615 double lower;
616 // All retained fields are inline scalars (or scalar-only aggregates).
617 void observe_owned_storage(OwnedStorage&) const noexcept {}
618};
619
620class BB {
621 double mult_;
622 SMA sma_;
623 StdDev stdev_;
624
625public:
626 BB(int length, double mult);
627 BBResult compute(double src);
628 BBResult recompute(double src);
629public:
630 void observe_owned_storage(OwnedStorage& out) const noexcept {
631 observe_owned_members(out, sma_, stdev_);
632 }
633};
634
635// --- KC (Keltner Channels) ---
636
637struct KCResult {
638 double middle;
639 double upper;
640 double lower;
641 // All retained fields are inline scalars (or scalar-only aggregates).
642 void observe_owned_storage(OwnedStorage&) const noexcept {}
643};
644
645// middle = EMA(src); the bands are middle +/- mult * EMA(range), where the
646// range is the true range against the previous bar's close (na where that
647// close is) or, with use_true_range = false, high - low. Omitting the flag is
648// the true range, value for value.
649class KC {
650 double mult_;
651 bool use_true_range_;
652 EMA ema_;
653 EMA range_ema_;
654 double prev_close_ = na<double>();
655 double saved_prev_close_ = na<double>();
656
657 double range_of(double high, double low) const;
658
659public:
660 KC(int length, double mult, bool use_true_range = true);
661 KCResult compute(double src, double high, double low, double close);
662 KCResult recompute(double src, double high, double low, double close);
663public:
664 void observe_owned_storage(OwnedStorage& out) const noexcept {
665 observe_owned_members(out, ema_, range_ema_);
666 }
667};
668
669// --- PivotHigh ---
670
672 int left_bars_, right_bars_;
673 OwnedDeque<double> buffer_;
674
675public:
676 PivotHigh(int left_bars, int right_bars);
677 double compute(double src);
678 double recompute(double src);
679public:
680 void observe_owned_storage(OwnedStorage& out) const noexcept {
681 observe_owned_members(out, buffer_);
682 }
683};
684
685// --- PivotLow ---
686
687class PivotLow {
688 int left_bars_, right_bars_;
689 OwnedDeque<double> buffer_;
690
691public:
692 PivotLow(int left_bars, int right_bars);
693 double compute(double src);
694 double recompute(double src);
695public:
696 void observe_owned_storage(OwnedStorage& out) const noexcept {
697 observe_owned_members(out, buffer_);
698 }
699};
700
701// --- Linreg (Linear Regression) ---
702
703class Linreg {
704 int length_;
705 OwnedDeque<double> buffer_;
706
707public:
708 explicit Linreg(int length);
709 double compute(double src, double offset);
710 double recompute(double src, double offset);
711public:
712 void observe_owned_storage(OwnedStorage& out) const noexcept {
713 observe_owned_members(out, buffer_);
714 }
715};
716
717// --- PercentRank ---
718
720 int length_;
721 OwnedDeque<double> buffer_;
722
723public:
724 explicit PercentRank(int length);
725 double compute(double src);
726 double recompute(double src);
727public:
728 void observe_owned_storage(OwnedStorage& out) const noexcept {
729 observe_owned_members(out, buffer_);
730 }
731};
732
733// --- VWMA (Volume-Weighted Moving Average) ---
734
735class VWMA {
736 int length_;
737 OwnedDeque<double> sv_buffer_;
738 OwnedDeque<double> v_buffer_;
739 double sv_sum_, v_sum_;
740
741public:
742 explicit VWMA(int length);
743 double compute(double src, double vol);
744 double recompute(double src, double vol);
745public:
746 void observe_owned_storage(OwnedStorage& out) const noexcept {
747 observe_owned_members(out, sv_buffer_, v_buffer_);
748 }
749};
750
751// --- Mom (Momentum) ---
752
753class Mom {
754 int length_;
755 OwnedDeque<double> buffer_;
756
757public:
758 explicit Mom(int length);
759 double compute(double src);
760 double recompute(double src);
761public:
762 void observe_owned_storage(OwnedStorage& out) const noexcept {
763 observe_owned_members(out, buffer_);
764 }
765};
766
767// --- ROC (Rate of Change) ---
768
769class ROC {
770 int length_;
771 OwnedDeque<double> buffer_;
772
773public:
774 explicit ROC(int length);
775 double compute(double src);
776 double recompute(double src);
777public:
778 void observe_owned_storage(OwnedStorage& out) const noexcept {
779 observe_owned_members(out, buffer_);
780 }
781};
782
783// --- Rising ---
784
785class Rising {
786 int length_;
787 OwnedDeque<double> buffer_;
788
789public:
790 explicit Rising(int length);
791 double compute(double src);
792 double recompute(double src);
793public:
794 void observe_owned_storage(OwnedStorage& out) const noexcept {
795 observe_owned_members(out, buffer_);
796 }
797};
798
799// --- Falling ---
800
801class Falling {
802 int length_;
803 OwnedDeque<double> buffer_;
804
805public:
806 explicit Falling(int length);
807 double compute(double src);
808 double recompute(double src);
809public:
810 void observe_owned_storage(OwnedStorage& out) const noexcept {
811 observe_owned_members(out, buffer_);
812 }
813};
814
815// --- CCI (Commodity Channel Index) ---
816
817class CCI {
818 int length_;
819 OwnedDeque<double> buffer_;
820
821public:
822 explicit CCI(int length);
823 double compute(double src);
824 double recompute(double src);
825public:
826 void observe_owned_storage(OwnedStorage& out) const noexcept {
827 observe_owned_members(out, buffer_);
828 }
829};
830
831// --- Cum (Cumulative Sum) ---
832
833class Cum {
834 double sum_;
835
836 double saved_sum_;
837
838public:
840 double compute(double src);
841 double recompute(double src);
842public:
843 // All retained fields are inline scalars (or scalar-only aggregates).
844 void observe_owned_storage(OwnedStorage&) const noexcept {}
845};
846
847// --- Chart all-time max/min of a series (ta.max / ta.min single-arg) ---
848
850 double max_;
851 bool has_;
852
853 double saved_max_;
854 bool saved_has_;
855
856public:
858 double compute(double src);
859 double recompute(double src);
860public:
861 // All retained fields are inline scalars (or scalar-only aggregates).
862 void observe_owned_storage(OwnedStorage&) const noexcept {}
863};
864
866 double min_;
867 bool has_;
868
869 double saved_min_;
870 bool saved_has_;
871
872public:
874 double compute(double src);
875 double recompute(double src);
876public:
877 // All retained fields are inline scalars (or scalar-only aggregates).
878 void observe_owned_storage(OwnedStorage&) const noexcept {}
879};
880
881// --- RCI (Rank Correlation Index, Spearman × 100) ---
882
883class RCI {
884 int length_;
885 OwnedDeque<double> buffer_;
886 std::vector<double> prices_;
887 std::vector<int> order_;
888 std::vector<double> price_rank_;
889
890 double calculate();
891
892public:
893 explicit RCI(int length);
894 double compute(double src);
895 double recompute(double src);
896public:
897 void observe_owned_storage(OwnedStorage& out) const noexcept {
898 observe_owned_members(out, buffer_, prices_, order_, price_rank_);
899 }
900};
901
902// --- Variance ---
903
904class Variance {
905 int length_;
906 bool biased_;
907 OwnedDeque<double> buffer_;
908
909public:
910 explicit Variance(int length, bool biased = true);
911 double compute(double src);
912 double recompute(double src);
913public:
914 void observe_owned_storage(OwnedStorage& out) const noexcept {
915 observe_owned_members(out, buffer_);
916 }
917};
918
919// --- Median ---
920
921class Median {
922 int length_;
923 OwnedDeque<double> buffer_;
924 std::vector<double> scratch_;
925
926 double calculate();
927
928public:
929 explicit Median(int length);
930 double compute(double src);
931 double recompute(double src);
932public:
933 void observe_owned_storage(OwnedStorage& out) const noexcept {
934 observe_owned_members(out, buffer_, scratch_);
935 }
936};
937
938// --- HighestBars ---
939
941 ExtremeRing ring_;
942
943public:
944 explicit HighestBars(int length);
945 double compute(double src);
946 double recompute(double src);
947public:
948 void observe_owned_storage(OwnedStorage& out) const noexcept {
949 observe_owned_members(out, ring_);
950 }
951};
952
953// --- LowestBars ---
954
956 ExtremeRing ring_;
957
958public:
959 explicit LowestBars(int length);
960 double compute(double src);
961 double recompute(double src);
962public:
963 void observe_owned_storage(OwnedStorage& out) const noexcept {
964 observe_owned_members(out, ring_);
965 }
966};
967
968// --- ALMA (Arnaud Legoux Moving Average) ---
969// The Gaussian's centre is m = offset * (length - 1); with `floor` it is
970// floor(offset * (length - 1)) ("whether the offset calculation is floored
971// before ALMA is calculated", default false). Omitting floor is the unfloored
972// ALMA, value for value.
973class ALMA {
974 int length_;
975 double offset_, sigma_;
976 bool floor_;
977 OwnedDeque<double> buffer_;
978 std::vector<double> weights_;
979
980public:
981 ALMA(int length, double offset = 0.85, double sigma = 6.0, bool floor = false);
982 double compute(double src);
983 double recompute(double src);
984public:
985 void observe_owned_storage(OwnedStorage& out) const noexcept {
986 observe_owned_members(out, buffer_, weights_);
987 }
988};
989
990// Feature macro: ALMA takes the floor input (a fourth constructor argument).
991#define PF_ALMA_HAS_FLOOR 1
992
993// --- SWMA (Symmetrically Weighted Moving Average, period=4) ---
994
995class SWMA {
996 OwnedDeque<double> buffer_;
997
998public:
1000 double compute(double src);
1001 double recompute(double src);
1002public:
1003 void observe_owned_storage(OwnedStorage& out) const noexcept {
1004 observe_owned_members(out, buffer_);
1005 }
1006};
1007
1008// --- MFI (Money Flow Index) ---
1009
1010class MFI {
1011 int length_;
1012 DynamicRingBuffer<double> pos_buffer_, neg_buffer_;
1013 double prev_src_;
1014 int bar_count_;
1015
1016 // saved state for recompute
1017 double saved_prev_src_;
1018 int saved_bar_count_;
1019 DynamicRingBuffer<double> saved_pos_buffer_, saved_neg_buffer_;
1020
1021public:
1022 explicit MFI(int length);
1023 double compute(double src, double vol);
1024 double recompute(double src, double vol);
1025public:
1026 void observe_owned_storage(OwnedStorage& out) const noexcept {
1027 observe_owned_members(out, pos_buffer_, neg_buffer_, saved_pos_buffer_, saved_neg_buffer_);
1028 }
1029};
1030
1031// --- CMO (Chande Momentum Oscillator) ---
1032
1033class CMO {
1034 int length_;
1035 DynamicRingBuffer<double> up_buffer_, down_buffer_;
1036 double prev_src_;
1037 int bar_count_;
1038
1039 // saved state for recompute
1040 double saved_prev_src_;
1041 int saved_bar_count_;
1042 DynamicRingBuffer<double> saved_up_buffer_, saved_down_buffer_;
1043
1044public:
1045 explicit CMO(int length);
1046 double compute(double src);
1047 double recompute(double src);
1048public:
1049 void observe_owned_storage(OwnedStorage& out) const noexcept {
1050 observe_owned_members(out, up_buffer_, down_buffer_, saved_up_buffer_, saved_down_buffer_);
1051 }
1052};
1053
1054// --- TSI (True Strength Index) ---
1055
1056class TSI {
1057 EMA ema_long_;
1058 EMA ema_short_;
1059 EMA ema_abs_long_;
1060 EMA ema_abs_short_;
1061 double prev_src_;
1062 int bar_count_;
1063
1064 double saved_prev_src_;
1065 int saved_bar_count_;
1066
1067public:
1068 TSI(int short_length, int long_length);
1069 double compute(double src);
1070 double recompute(double src);
1071public:
1072 void observe_owned_storage(OwnedStorage& out) const noexcept {
1073 observe_owned_members(out, ema_long_, ema_short_, ema_abs_long_, ema_abs_short_);
1074 }
1075};
1076
1077// --- WPR (Williams %R) ---
1078
1079class WPR {
1080 Highest highest_;
1081 Lowest lowest_;
1082
1083public:
1084 explicit WPR(int length);
1085 double compute(double close, double high, double low);
1086 double recompute(double close, double high, double low);
1087public:
1088 void observe_owned_storage(OwnedStorage& out) const noexcept {
1089 observe_owned_members(out, highest_, lowest_);
1090 }
1091};
1092
1093// --- COG (Center of Gravity) ---
1094
1095class COG {
1096 int length_;
1097 OwnedDeque<double> buffer_;
1098
1099public:
1100 explicit COG(int length);
1101 double compute(double src);
1102 double recompute(double src);
1103public:
1104 void observe_owned_storage(OwnedStorage& out) const noexcept {
1105 observe_owned_members(out, buffer_);
1106 }
1107};
1108
1109// --- BBW (Bollinger Bands Width) ---
1110
1111class BBW {
1112 BB bb_;
1113
1114public:
1115 BBW(int length, double mult);
1116 double compute(double src);
1117 double recompute(double src);
1118public:
1119 void observe_owned_storage(OwnedStorage& out) const noexcept {
1120 observe_owned_members(out, bb_);
1121 }
1122};
1123
1124// --- KCW (Keltner Channel Width) ---
1125
1126class KCW {
1127 KC kc_;
1128
1129public:
1130 KCW(int length, double mult, bool use_true_range = true);
1131 double compute(double src, double high, double low, double close);
1132 double recompute(double src, double high, double low, double close);
1133public:
1134 void observe_owned_storage(OwnedStorage& out) const noexcept {
1135 observe_owned_members(out, kc_);
1136 }
1137};
1138
1139// Feature macro: KC and KCW take the range choice (a third constructor
1140// argument, use_true_range).
1141#define PF_KC_HAS_USE_TRUE_RANGE 1
1142
1143// --- BarsSince ---
1144
1146 int count_;
1147 bool ever_true_;
1148
1149 int saved_count_;
1150 bool saved_ever_true_;
1151
1152public:
1154 double compute(bool condition);
1155 double recompute(bool condition);
1156public:
1157 // All retained fields are inline scalars (or scalar-only aggregates).
1158 void observe_owned_storage(OwnedStorage&) const noexcept {}
1159};
1160
1161// --- ValueWhen ---
1162
1164 OwnedDeque<double> values_;
1165 int max_occurrence_;
1166
1167 OwnedDeque<double> saved_values_;
1168
1169public:
1170 explicit ValueWhen(int max_occurrence = 1);
1171 double compute(bool condition, double source, int occurrence);
1172 double recompute(bool condition, double source, int occurrence);
1173public:
1174 void observe_owned_storage(OwnedStorage& out) const noexcept {
1175 observe_owned_members(out, values_, saved_values_);
1176 }
1177};
1178
1179// --- Correlation ---
1180
1182 int length_;
1183 OwnedDeque<double> x_buffer_, y_buffer_;
1184
1185public:
1186 explicit Correlation(int length);
1187 double compute(double src1, double src2);
1188 double recompute(double src1, double src2);
1189public:
1190 void observe_owned_storage(OwnedStorage& out) const noexcept {
1191 observe_owned_members(out, x_buffer_, y_buffer_);
1192 }
1193};
1194
1195// --- TR (True Range as function) ---
1196
1197class TR {
1198 double prev_close_;
1199 int bar_count_;
1200 bool handle_na_;
1201
1202 double saved_prev_close_;
1203 int saved_bar_count_;
1204
1205public:
1206 explicit TR(bool handle_na = false);
1207 double compute(double high, double low, double close);
1208 double recompute(double high, double low, double close);
1209 // issue #178: the sparse-call form — true range against the previous
1210 // CHART bar's close (na on the first chart bar: handle_na decides).
1211 double compute(double high, double low, double close, double prev_chart_close);
1212 double recompute(double high, double low, double close, double prev_chart_close);
1213public:
1214 // All retained fields are inline scalars (or scalar-only aggregates).
1215 void observe_owned_storage(OwnedStorage&) const noexcept {}
1216};
1217
1218// --- PercentileWindow ---
1219// The window TradingView ranks its nearest-rank and linear-interpolation
1220// percentiles over: one array kept across bars
1221// (tests/fixtures/percentile_window). Once `length` values are held, the value
1222// `length` bars back leaves at its first occurrence (na matching na) and the
1223// new value enters before the first held element greater than it: the held
1224// non-na values stay ascending, and na, greater than nothing and with nothing
1225// greater than it, enters last.
1227 int length_;
1228 OwnedDeque<double> history_;
1229 std::vector<double> ranked_;
1230 // The last push, which a recompute of its bar undoes: where its value
1231 // entered, and the value that left and where it stood (-1: none left).
1232 int entered_at_ = -1;
1233 int left_at_ = -1;
1234 double left_value_ = na<double>();
1235
1236public:
1237 explicit PercentileWindow(int length);
1238 // The ranked array once `length` values are held, else null.
1239 const std::vector<double>* push(double src);
1240 // The bar's value replaced by `src` (a push when nothing was pushed yet).
1241 const std::vector<double>* repush(double src);
1242public:
1243 void observe_owned_storage(OwnedStorage& out) const noexcept {
1244 observe_owned_members(out, history_, ranked_);
1245 }
1246};
1247
1248// Shared nearest-rank selection for percentile windows. A null ranked window
1249// answers na, and a non-null window is already sorted as PercentileWindow
1250// maintains it.
1251double nearest_rank_of(const std::vector<double>* ranked, double percentage);
1252
1253// --- PercentileNearestRank ---
1254
1256 PercentileWindow window_;
1257
1258public:
1259 explicit PercentileNearestRank(int length);
1260 double compute(double src, double percentage);
1261 double recompute(double src, double percentage);
1262public:
1263 void observe_owned_storage(OwnedStorage& out) const noexcept {
1264 observe_owned_members(out, window_);
1265 }
1266};
1267
1268// --- PercentileLinearInterpolation ---
1269
1271 PercentileWindow window_;
1272
1273public:
1274 explicit PercentileLinearInterpolation(int length);
1275 double compute(double src, double percentage);
1276 double recompute(double src, double percentage);
1277public:
1278 void observe_owned_storage(OwnedStorage& out) const noexcept {
1279 observe_owned_members(out, window_);
1280 }
1281};
1282
1283// --- Volume indicators ---
1284class OBV {
1285 double sum_ = 0.0;
1286 double prev_close_ = na<double>();
1287 int bar_count_ = 0;
1288
1289 // Mirror the initial committed state (see RMA::RMA) so a recompute()
1290 // before the first compute() restores a well-defined pristine state.
1291 double saved_sum_ = 0.0, saved_prev_close_ = na<double>();
1292 int saved_bar_count_ = 0;
1293
1294public:
1295 OBV() = default;
1296 double compute(double close, double volume);
1297 double recompute(double close, double volume);
1298public:
1299 // All retained fields are inline scalars (or scalar-only aggregates).
1300 void observe_owned_storage(OwnedStorage&) const noexcept {}
1301};
1302
1303class AccDist {
1304 double sum_ = 0.0;
1305
1306 // Mirror the initial committed sum_ (see RMA::RMA) so a recompute()
1307 // before the first compute() restores a well-defined pristine state.
1308 double saved_sum_ = 0.0;
1309
1310public:
1311 AccDist() = default;
1312 double compute(double high, double low, double close, double volume);
1313 double recompute(double high, double low, double close, double volume);
1314public:
1315 // All retained fields are inline scalars (or scalar-only aggregates).
1316 void observe_owned_storage(OwnedStorage&) const noexcept {}
1317};
1318
1319class NVI {
1320 double nvi_ = 1.0;
1321 double prev_close_ = na<double>();
1322 double prev_volume_ = na<double>();
1323 int bar_count_ = 0;
1324
1325 // Mirror the initial committed state (see RMA::RMA) so a recompute()
1326 // before the first compute() restores a well-defined pristine state.
1327 double saved_nvi_ = 1.0, saved_prev_close_ = na<double>(),
1328 saved_prev_volume_ = na<double>();
1329 int saved_bar_count_ = 0;
1330
1331public:
1332 NVI() = default;
1333 double compute(double close, double volume);
1334 double recompute(double close, double volume);
1335public:
1336 // All retained fields are inline scalars (or scalar-only aggregates).
1337 void observe_owned_storage(OwnedStorage&) const noexcept {}
1338};
1339
1340class PVI {
1341 double pvi_ = 1.0;
1342 double prev_close_ = na<double>();
1343 double prev_volume_ = na<double>();
1344 int bar_count_ = 0;
1345
1346 // Mirror the initial committed state (see RMA::RMA) so a recompute()
1347 // before the first compute() restores a well-defined pristine state.
1348 double saved_pvi_ = 1.0, saved_prev_close_ = na<double>(),
1349 saved_prev_volume_ = na<double>();
1350 int saved_bar_count_ = 0;
1351
1352public:
1353 PVI() = default;
1354 double compute(double close, double volume);
1355 double recompute(double close, double volume);
1356public:
1357 // All retained fields are inline scalars (or scalar-only aggregates).
1358 void observe_owned_storage(OwnedStorage&) const noexcept {}
1359};
1360
1361class PVT {
1362 double pvt_ = 0.0;
1363 double prev_close_ = na<double>();
1364
1365 // Mirror the initial committed state (see RMA::RMA) so a recompute()
1366 // before the first compute() restores a well-defined pristine state.
1367 double saved_pvt_ = 0.0, saved_prev_close_ = na<double>();
1368
1369public:
1370 PVT() = default;
1371 double compute(double close, double volume);
1372 double recompute(double close, double volume);
1373public:
1374 // All retained fields are inline scalars (or scalar-only aggregates).
1375 void observe_owned_storage(OwnedStorage&) const noexcept {}
1376};
1377
1378class WAD {
1379 double wad_ = 0.0;
1380 double prev_close_ = na<double>();
1381
1382 // Mirror the initial committed state (see RMA::RMA) so a recompute()
1383 // before the first compute() restores a well-defined pristine state.
1384 double saved_wad_ = 0.0, saved_prev_close_ = na<double>();
1385
1386public:
1387 WAD() = default;
1388 double compute(double high, double low, double close);
1389 double recompute(double high, double low, double close);
1390public:
1391 // All retained fields are inline scalars (or scalar-only aggregates).
1392 void observe_owned_storage(OwnedStorage&) const noexcept {}
1393};
1394
1395class WVAD {
1396public:
1397 WVAD() = default;
1398 double compute(double open, double high, double low, double close, double volume);
1399 double recompute(double open, double high, double low, double close, double volume);
1400public:
1401 // All retained fields are inline scalars (or scalar-only aggregates).
1402 void observe_owned_storage(OwnedStorage&) const noexcept {}
1403};
1404
1405class III {
1406public:
1407 III() = default;
1408 double compute(double high, double low, double close, double volume);
1409 double recompute(double high, double low, double close, double volume);
1410public:
1411 // All retained fields are inline scalars (or scalar-only aggregates).
1412 void observe_owned_storage(OwnedStorage&) const noexcept {}
1413};
1414
1415// --- VWAP Bands result (3-tuple: vwap, upper_band, lower_band) ---
1417 double vwap;
1418 double upper;
1419 double lower;
1420 // All retained fields are inline scalars (or scalar-only aggregates).
1421 void observe_owned_storage(OwnedStorage&) const noexcept {}
1422};
1423
1424class VWAP {
1425 double cum_pv_ = 0.0;
1426 double cum_vol_ = 0.0;
1427 // Sum of (price^2 * volume) for running variance computation used by
1428 // compute_bands(). Variance = cum_pv_sq_ / cum_vol_ - mean^2.
1429 double cum_pv_sq_ = 0.0;
1430 // Anchor day index: the SESSION day of the bar (session_day_index —
1431 // timestamp_ms / 86_400_000 on a UTC/24x7 symbol, the 17:00-ET-keyed
1432 // trading day on forex, the 09:30 RTH day on equities). On the first
1433 // compute() call we record this from the bar timestamp; on every
1434 // subsequent compute() the cumulator is reset whenever the day index
1435 // advances. Pine v6 `ta.vwap(source)` defaults to a Daily anchor
1436 // (`anchor = timeframe.change("1D")` on the SYMBOL's daily bar); the
1437 // engine matches that when the codegen threads syminfo tz + session.
1438 int64_t anchor_day_ = std::numeric_limits<int64_t>::min();
1439
1440 // Mirror the initial committed state (see RMA::RMA) so a recompute()
1441 // before the first compute() restores a well-defined pristine state.
1442 double saved_cum_pv_ = 0.0, saved_cum_vol_ = 0.0, saved_cum_pv_sq_ = 0.0;
1443 int64_t saved_anchor_day_ = std::numeric_limits<int64_t>::min();
1444
1445 void roll_anchor(int64_t day);
1446
1447public:
1448 VWAP() = default;
1449 // tz-less forms key the anchor on the UTC day (the 24x7 corpus regime);
1450 // the tz/session forms key it on the symbol's session day and reduce to
1451 // the same integer math for tz="UTC" + empty/"24x7" session.
1452 // Feature macro PF_VWAP_HAS_SESSION_ANCHOR (below the class) lets
1453 // generated code compile the (tz, session) tail out on older engines.
1454 double compute(double src, double volume, int64_t timestamp_ms);
1455 double recompute(double src, double volume, int64_t timestamp_ms);
1456 double compute(double src, double volume, int64_t timestamp_ms,
1457 const std::string& tz, const std::string& session);
1458 double recompute(double src, double volume, int64_t timestamp_ms,
1459 const std::string& tz, const std::string& session);
1460 VWAPBandsResult compute_bands(double src, double volume, int64_t timestamp_ms, double stdev_mult);
1461 VWAPBandsResult recompute_bands(double src, double volume, int64_t timestamp_ms, double stdev_mult);
1462 VWAPBandsResult compute_bands(double src, double volume, int64_t timestamp_ms, double stdev_mult,
1463 const std::string& tz, const std::string& session);
1464 VWAPBandsResult recompute_bands(double src, double volume, int64_t timestamp_ms, double stdev_mult,
1465 const std::string& tz, const std::string& session);
1466public:
1467 // All retained fields are inline scalars (or scalar-only aggregates).
1468 void observe_owned_storage(OwnedStorage&) const noexcept {}
1469};
1470
1471// Feature macro: the emitted prelude's PF_VWAP_SESSION_ANCHOR_ARGS(tz, s)
1472// expands to `, tz, s` only when this is defined (see VWAP overloads above).
1473#define PF_VWAP_HAS_SESSION_ANCHOR 1
1474
1475// --- VWAP Bands wrapper class (3-tuple form: ta.vwap(src, anchor, stdev_mult)) ---
1476// Wraps VWAP and routes compute/recompute to compute_bands/recompute_bands with
1477// a fixed stdev_mult supplied at construction time. This lets the codegen use
1478// the standard .compute()/.recompute() dispatch pattern for tuple returns.
1480 VWAP vwap_;
1481 double stdev_mult_;
1482public:
1483 explicit VWAPBands(double stdev_mult) : stdev_mult_(stdev_mult) {}
1484 VWAPBandsResult compute(double src, double volume, int64_t timestamp_ms) {
1485 return vwap_.compute_bands(src, volume, timestamp_ms, stdev_mult_);
1486 }
1487 VWAPBandsResult recompute(double src, double volume, int64_t timestamp_ms) {
1488 return vwap_.recompute_bands(src, volume, timestamp_ms, stdev_mult_);
1489 }
1490 VWAPBandsResult compute(double src, double volume, int64_t timestamp_ms,
1491 const std::string& tz, const std::string& session) {
1492 return vwap_.compute_bands(src, volume, timestamp_ms, stdev_mult_, tz, session);
1493 }
1494 VWAPBandsResult recompute(double src, double volume, int64_t timestamp_ms,
1495 const std::string& tz, const std::string& session) {
1496 return vwap_.recompute_bands(src, volume, timestamp_ms, stdev_mult_, tz, session);
1497 }
1498public:
1499 void observe_owned_storage(OwnedStorage& out) const noexcept {
1500 observe_owned_members(out, vwap_);
1501 }
1502};
1503
1504// --- Anchored VWAP (the accumulation restarts where the caller says) ---
1505// VWAP over the bars since the most recent bar whose `anchor` was true, that
1506// bar included: an anchored bar starts a new accumulation, and until the first
1507// anchored bar the value is na (ta.vwap's anchor: "When true, calculations
1508// reset"; "Calculations only begin the first time the anchor condition
1509// becomes true. Until then, the function returns na"). The arithmetic is
1510// VWAP's -- running sums of src * volume, src * src * volume and volume, the
1511// bands mean +/- stdev_mult * sqrt(max(0, sum(src*src*volume) / sum(volume) -
1512// mean * mean)) -- so an anchor raised on the bars where VWAP's session day
1513// changes, and on the first bar, reproduces VWAP bit for bit. An na src or
1514// volume answers na and adds nothing; an anchor on such a bar still resets the
1515// sums. A zero summed volume answers na. recompute() re-runs the current bar
1516// from the state its first compute() found, anchor included.
1518 double cum_pv_ = 0.0;
1519 double cum_vol_ = 0.0;
1520 double cum_pv_sq_ = 0.0;
1521 bool started_ = false; // an anchored bar has been seen
1522
1523 // Mirror the initial committed state (see RMA::RMA) so a recompute()
1524 // before the first compute() restores a well-defined pristine state.
1525 double saved_cum_pv_ = 0.0, saved_cum_vol_ = 0.0, saved_cum_pv_sq_ = 0.0;
1526 bool saved_started_ = false;
1527
1528 // Folds one bar into the sums; false when the bar has no value.
1529 bool accumulate(double src, double volume, bool anchor);
1530
1531public:
1532 AnchoredVWAP() = default;
1533 double compute(double src, double volume, bool anchor);
1534 double recompute(double src, double volume, bool anchor);
1535 VWAPBandsResult compute_bands(double src, double volume, bool anchor, double stdev_mult);
1536 VWAPBandsResult recompute_bands(double src, double volume, bool anchor, double stdev_mult);
1537public:
1538 // All retained fields are inline scalars (or scalar-only aggregates).
1539 void observe_owned_storage(OwnedStorage&) const noexcept {}
1540};
1541
1542// The 3-tuple form with a construction-time stdev_mult, for the standard
1543// compute()/recompute() dispatch (VWAPBands' shape). A per-bar multiplier goes
1544// through AnchoredVWAP::compute_bands directly.
1546 AnchoredVWAP vwap_;
1547 double stdev_mult_;
1548public:
1549 explicit AnchoredVWAPBands(double stdev_mult) : stdev_mult_(stdev_mult) {}
1550 VWAPBandsResult compute(double src, double volume, bool anchor) {
1551 return vwap_.compute_bands(src, volume, anchor, stdev_mult_);
1552 }
1553 VWAPBandsResult recompute(double src, double volume, bool anchor) {
1554 return vwap_.recompute_bands(src, volume, anchor, stdev_mult_);
1555 }
1556public:
1557 void observe_owned_storage(OwnedStorage& out) const noexcept {
1558 observe_owned_members(out, vwap_);
1559 }
1560};
1561
1562// Feature macro: AnchoredVWAP / AnchoredVWAPBands exist (generated code may
1563// compile an anchored call site out on older engines, as with
1564// PF_VWAP_HAS_SESSION_ANCHOR).
1565#define PF_VWAP_HAS_ANCHOR_INPUT 1
1566
1567// --- Statistical ---
1568class Mode {
1569 struct CountEntry {
1570 double value = na<double>();
1571 int count = 0;
1572 unsigned char state = 0; // 0 empty, 1 occupied, 2 deleted
1573 void observe_owned_storage(OwnedStorage&) const noexcept {} // scalar record
1574 };
1575
1576 int length_;
1577 OwnedDeque<double> buffer_;
1578 std::vector<CountEntry> counts_;
1579
1580 void add_count(double value);
1581 void remove_count(double value);
1582 double current_mode() const;
1583
1584public:
1585 explicit Mode(int length);
1586 double compute(double src);
1587 double recompute(double src);
1588public:
1589 void observe_owned_storage(OwnedStorage& out) const noexcept {
1590 observe_owned_members(out, buffer_, counts_);
1591 }
1592};
1593
1594class Range {
1595 Highest highest_;
1596 Lowest lowest_;
1597public:
1598 explicit Range(int length) : highest_(length), lowest_(length) {}
1599 double compute(double src);
1600 double recompute(double src);
1601public:
1602 void observe_owned_storage(OwnedStorage& out) const noexcept {
1603 observe_owned_members(out, highest_, lowest_);
1604 }
1605};
1606
1607class Dev {
1608 int length_;
1609 OwnedDeque<double> buffer_;
1610public:
1611 explicit Dev(int length) : length_(length) {}
1612 double compute(double src);
1613 double recompute(double src);
1614public:
1615 void observe_owned_storage(OwnedStorage& out) const noexcept {
1616 observe_owned_members(out, buffer_);
1617 }
1618};
1619
1620// --- pivot_point_levels (free function) ---
1621// The 11 pivot levels [P, R1, S1, R2, S2, R3, S3, R4, S4, R5, S5] of one
1622// period's high, low and close, na for the levels a type does not define and
1623// all na for a missing input; an unknown name answers P alone. Traditional,
1624// Fibonacci, Classic and Camarilla are PivotPointLevels' formulas bit for bit.
1625// Woodie and DM are a historical approximation kept for source compatibility:
1626// this signature carries neither the next period's open, which Woodie's pivot
1627// weights (it weights the close, and spaces R3..S4 as Classic does), nor the
1628// period's open, which DM compares with the close (it branches on the close
1629// meeting the high or the low). The overload below takes both, and
1630// ta::PivotPointLevels is the TradingView form.
1631std::vector<double> pivot_point_levels(const std::string& method,
1632 double high, double low, double close);
1633
1634// The same 11 levels from the period's open, high, low and close and the open
1635// of the period after it -- the period the levels are for -- for every type as
1636// PivotPointLevels computes them: anchored on every bar with developing =
1637// false, its levels on a bar are this overload's of the bar before (open,
1638// high, low, close) and the bar's own open, bit for bit. Only Woodie reads
1639// next_open and only DM reads open; a formula missing an input it reads leaves
1640// all eleven na. The type by name: pivot_levels_type(), which throws
1641// std::invalid_argument for any other.
1642std::vector<double> pivot_point_levels(const std::string& method, double open, double high,
1643 double low, double close, double next_open);
1644
1645// --- Pivot point levels of an anchored period ---
1646// The six pivot types. DM is DeMark's.
1647enum class PivotLevelsType : unsigned char {
1652 DM = 4,
1654};
1655
1656// The type spelled "Traditional", "Fibonacci", "Woodie", "Classic", "DM" or
1657// "Camarilla"; std::invalid_argument for any other name.
1658PivotLevelsType pivot_levels_type(const std::string& name);
1659
1660// The 11 pivot levels [P, R1, S1, R2, S2, R3, S3, R4, S4, R5, S5] of a
1661// period of bars, na for the levels a type does not define. A period runs
1662// from an anchored bar (bar 0 before the first anchor) to the bar before the
1663// next anchored bar; a period is aggregated as its first finite open, highest
1664// finite high, lowest finite low and last finite close.
1665//
1666// developing = false: the levels computed on the last anchored bar, from the
1667// period that bar closed (and, for Woodie, that bar's own open -- the open of
1668// the period the levels are for), held until the next anchored bar; all na
1669// before the first anchored bar that closes a non-empty period.
1670// developing = true: the levels of the period in progress, this bar included,
1671// recomputed on every bar (DM reads the period's own open). Woodie has no
1672// developing levels -- its levels need the open of the period after the one
1673// measured -- so compute() and recompute() throw std::runtime_error for that
1674// pair, which fails a run as any exception out of a script callback does.
1675//
1676// The formulas are the standard pivot definitions, Traditional's R3..S5 and
1677// Woodie's among them, evaluated operation by operation as written: P =
1678// (H + L + C) / 3, R1 = P * 2 - L, ..., R3 = P * 2 + (H - 2 * L), ..., R5 =
1679// P * 4 + (H - 4 * L); Woodie P = (H + L + 2 * O_next) / 4, R3 = H + 2 * (P -
1680// L), R4 = R3 + (H - L); DM X = O == C ? H + L + 2 * C : C > O ? 2 * H + L +
1681// C : 2 * L + H + C, P = X / 4, R1 = X / 2 - L, S1 = X / 2 - H; Camarilla R1 =
1682// C + 1.1 * (H - L) / 12, ..., R5 = (H / L) * C (na on a zero low), S5 = C -
1683// (R5 - C). Anchored on every bar with developing = false, this is the
1684// six-argument free function above for every type, and the four-argument one
1685// for every type but Woodie and DM.
1686// recompute() re-runs the current bar from the state its first compute()
1687// found.
1689public:
1690 PivotPointLevels() = default;
1691 std::vector<double> compute(PivotLevelsType type, bool anchor, bool developing,
1692 double open, double high, double low, double close);
1693 std::vector<double> recompute(PivotLevelsType type, bool anchor, bool developing,
1694 double open, double high, double low, double close);
1695 // The type by name (pivot_levels_type()).
1696 std::vector<double> compute(const std::string& type, bool anchor, bool developing,
1697 double open, double high, double low, double close);
1698 std::vector<double> recompute(const std::string& type, bool anchor, bool developing,
1699 double open, double high, double low, double close);
1700
1701private:
1702 struct Period {
1703 double open = na<double>();
1704 double high = na<double>();
1705 double low = na<double>();
1706 double close = na<double>();
1707 void enter(double o, double h, double l, double c);
1708 };
1709 struct Levels {
1710 double v[11];
1711 };
1712 static Levels no_levels();
1713
1714 Period period_; // the period in progress
1715 Levels held_ = no_levels(); // the levels of the last closed period
1716 Period saved_period_;
1717 Levels saved_held_ = no_levels();
1718public:
1719 // All retained fields are inline scalars (or scalar-only aggregates).
1720 void observe_owned_storage(OwnedStorage&) const noexcept {}
1721};
1722
1723// Feature macro: PivotPointLevels / PivotLevelsType / pivot_levels_type exist.
1724#define PF_PIVOT_LEVELS_HAS_ANCHOR 1
1725
1726} // namespace ta
1727
1728} // namespace pineforge
double compute(double src)
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:985
ALMA(int length, double offset=0.85, double sigma=6.0, bool floor=false)
double recompute(double high, double low, double close)
double recompute(double high, double low, double close, double prev_chart_close)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:388
double compute(double high, double low, double close)
double compute(double high, double low, double close, double prev_chart_close)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1316
double compute(double high, double low, double close, double volume)
double recompute(double high, double low, double close, double volume)
double recompute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:862
double recompute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:878
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1557
VWAPBandsResult compute(double src, double volume, bool anchor)
Definition ta.hpp:1550
AnchoredVWAPBands(double stdev_mult)
Definition ta.hpp:1549
VWAPBandsResult recompute(double src, double volume, bool anchor)
Definition ta.hpp:1553
double recompute(double src, double volume, bool anchor)
double compute(double src, double volume, bool anchor)
VWAPBandsResult recompute_bands(double src, double volume, bool anchor, double stdev_mult)
VWAPBandsResult compute_bands(double src, double volume, bool anchor, double stdev_mult)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1539
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1119
double compute(double src)
double recompute(double src)
BBW(int length, double mult)
BBResult recompute(double src)
BB(int length, double mult)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:630
BBResult compute(double src)
BarContextScope(const BarContextScope &)=delete
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:134
BarContextScope & operator=(const BarContextScope &)=delete
BarContextScope(long long bar_index, long long origin)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1158
double compute(bool condition)
double recompute(bool condition)
double compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:826
double recompute(double src)
double recompute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1049
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1104
double recompute(double src)
double compute(double src)
double compute(double src, int length=1)
double recompute(double src, int length=1)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:420
Change(int max_length=1)
double compute(double src1, double src2)
double recompute(double src1, double src2)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1190
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:445
bool compute(double a, double b)
bool recompute(double a, double b)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:235
bool recompute(double a, double b)
bool compute(double a, double b)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:250
bool recompute(double a, double b)
bool compute(double a, double b)
double compute(double src)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:844
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:580
DMI(int di_length, int adx_smoothing)
DMIResult compute(double high, double low, double close)
DMIResult recompute(double high, double low, double close)
Dev(int length)
Definition ta.hpp:1611
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1615
double compute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:305
EMA(int length, EmaSeeding seeding)
double recompute(double src)
Result update(double src, bool advance, bool want_max)
WindowCacheStats cache_stats() const
Definition ta.hpp:156
ExtremeRing(int length, WindowCacheCapacity cache=window_cache_capacity())
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:176
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:810
double recompute(double src)
double compute(double src)
double compute(double src)
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:482
double compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:948
double recompute(double src)
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:343
double compute(double src)
double recompute(double high, double low, double close, double volume)
double compute(double high, double low, double close, double volume)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1412
double recompute(double src, double high, double low, double close)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1134
double compute(double src, double high, double low, double close)
KCW(int length, double mult, bool use_true_range=true)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:664
KCResult compute(double src, double high, double low, double close)
KC(int length, double mult, bool use_true_range=true)
KCResult recompute(double src, double high, double low, double close)
double recompute(double src, double offset)
double compute(double src, double offset)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:712
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:963
double recompute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:358
double compute(double src)
double recompute(double src)
MACDResult recompute(double src)
MACD(int fast_length, int slow_length, int signal_length)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:328
MACDResult compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1026
double compute(double src, double vol)
double recompute(double src, double vol)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:933
double recompute(double src)
double compute(double src)
double compute(double src)
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1589
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:762
double recompute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1337
double recompute(double close, double volume)
double compute(double close, double volume)
double recompute(double close, double volume)
double compute(double close, double volume)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1300
double recompute(double close, double volume)
double compute(double close, double volume)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1358
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1375
double recompute(double close, double volume)
double compute(double close, double volume)
double compute(double src)
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:728
double recompute(double src, double percentage)
double compute(double src, double percentage)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1278
double recompute(double src, double percentage)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1263
double compute(double src, double percentage)
const std::vector< double > * push(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1243
const std::vector< double > * repush(double src)
double compute(double src)
PivotHigh(int left_bars, int right_bars)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:680
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:696
PivotLow(int left_bars, int right_bars)
double recompute(double src)
double compute(double src)
std::vector< double > recompute(const std::string &type, bool anchor, bool developing, double open, double high, double low, double close)
std::vector< double > recompute(PivotLevelsType type, bool anchor, bool developing, double open, double high, double low, double close)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1720
std::vector< double > compute(const std::string &type, bool anchor, bool developing, double open, double high, double low, double close)
std::vector< double > compute(PivotLevelsType type, bool anchor, bool developing, double open, double high, double low, double close)
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:897
double compute(double src)
double compute(double src)
double recompute(double src)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:200
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:778
double recompute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:218
double compute(double src)
double recompute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1602
Range(int length)
Definition ta.hpp:1598
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:794
double compute(double src)
double recompute(double src)
SAR(double start, double increment, double maximum)
double compute(double high, double low, double close)
double recompute(double high, double low, double close)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:607
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:265
double compute(double src)
double compute(double src)
double recompute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1003
StdDev(int length, bool biased=true)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:515
double recompute(double src)
double compute(double src)
double compute(double src, double high, double low)
double recompute(double src, double high, double low)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:404
Supertrend(double factor, int atr_period)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:550
SupertrendResult recompute(double high, double low, double close)
SupertrendResult compute(double high, double low, double close)
double compute(double high, double low, double close, double prev_chart_close)
TR(bool handle_na=false)
double recompute(double high, double low, double close, double prev_chart_close)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1215
double recompute(double high, double low, double close)
double compute(double high, double low, double close)
double compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1072
TSI(int short_length, int long_length)
double recompute(double src)
VWAPBandsResult recompute(double src, double volume, int64_t timestamp_ms)
Definition ta.hpp:1487
VWAPBandsResult compute(double src, double volume, int64_t timestamp_ms)
Definition ta.hpp:1484
VWAPBands(double stdev_mult)
Definition ta.hpp:1483
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1499
VWAPBandsResult compute(double src, double volume, int64_t timestamp_ms, const std::string &tz, const std::string &session)
Definition ta.hpp:1490
VWAPBandsResult recompute(double src, double volume, int64_t timestamp_ms, const std::string &tz, const std::string &session)
Definition ta.hpp:1494
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1468
double recompute(double src, double volume, int64_t timestamp_ms)
double recompute(double src, double volume, int64_t timestamp_ms, const std::string &tz, const std::string &session)
VWAPBandsResult recompute_bands(double src, double volume, int64_t timestamp_ms, double stdev_mult)
double compute(double src, double volume, int64_t timestamp_ms, const std::string &tz, const std::string &session)
VWAPBandsResult recompute_bands(double src, double volume, int64_t timestamp_ms, double stdev_mult, const std::string &tz, const std::string &session)
VWAPBandsResult compute_bands(double src, double volume, int64_t timestamp_ms, double stdev_mult, const std::string &tz, const std::string &session)
double compute(double src, double volume, int64_t timestamp_ms)
VWAPBandsResult compute_bands(double src, double volume, int64_t timestamp_ms, double stdev_mult)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:746
double compute(double src, double vol)
double recompute(double src, double vol)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1174
double compute(bool condition, double source, int occurrence)
double recompute(bool condition, double source, int occurrence)
ValueWhen(int max_occurrence=1)
Variance(int length, bool biased=true)
double recompute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:914
double compute(double high, double low, double close)
double recompute(double high, double low, double close)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1392
WindowCacheStats cache_stats() const
Definition ta.hpp:463
double recompute(double src)
double compute(double src)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:465
WMA(int length, WindowCacheCapacity cache=window_cache_capacity())
double compute(double close, double high, double low)
void observe_owned_storage(OwnedStorage &out) const noexcept
Definition ta.hpp:1088
double recompute(double close, double high, double low)
double recompute(double open, double high, double low, double close, double volume)
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1402
double compute(double open, double high, double low, double close, double volume)
bool & ema_na_warmup_flag()
BarContext & bar_context()
std::vector< double > pivot_point_levels(const std::string &method, double high, double low, double close)
double nearest_rank_of(const std::vector< double > *ranked, double percentage)
PivotLevelsType pivot_levels_type(const std::string &name)
double na< double >()
Definition na.hpp:64
WindowCacheCapacity & window_cache_capacity()
Definition series.hpp:40
void observe_owned_members(OwnedStorage &out, const T &... values) noexcept
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:617
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:117
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:562
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:642
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:315
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:526
void observe_owned_storage(OwnedStorage &) const noexcept
Definition ta.hpp:1421